Merge branch 'master' into careminster
Conflicts: OpenSim/Region/Framework/Scenes/SceneObjectPart.cs OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.csavinationmerge
commit
0a876a305c
|
@ -97,7 +97,7 @@ namespace OpenSim.Framework.Console
|
||||||
if (!UUID.TryParse(rawUuid, out uuid))
|
if (!UUID.TryParse(rawUuid, out uuid))
|
||||||
{
|
{
|
||||||
if (console != null)
|
if (console != null)
|
||||||
console.OutputFormat("{0} is not a valid uuid", rawUuid);
|
console.OutputFormat("ERROR: {0} is not a valid uuid", rawUuid);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ namespace OpenSim.Framework.Console
|
||||||
if (!uint.TryParse(rawLocalId, out localId))
|
if (!uint.TryParse(rawLocalId, out localId))
|
||||||
{
|
{
|
||||||
if (console != null)
|
if (console != null)
|
||||||
console.OutputFormat("{0} is not a valid local id", localId);
|
console.OutputFormat("ERROR: {0} is not a valid local id", localId);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ namespace OpenSim.Framework.Console
|
||||||
if (localId == 0)
|
if (localId == 0)
|
||||||
{
|
{
|
||||||
if (console != null)
|
if (console != null)
|
||||||
console.OutputFormat("{0} is not a valid local id - it must be greater than 0", localId);
|
console.OutputFormat("ERROR: {0} is not a valid local id - it must be greater than 0", localId);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -150,11 +150,31 @@ namespace OpenSim.Framework.Console
|
||||||
}
|
}
|
||||||
|
|
||||||
if (console != null)
|
if (console != null)
|
||||||
console.OutputFormat("{0} is not a valid UUID or local id", rawId);
|
console.OutputFormat("ERROR: {0} is not a valid UUID or local id", rawId);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert a minimum vector input from the console to an OpenMetaverse.Vector3
|
||||||
|
/// </summary>
|
||||||
|
/// <param name='console'>Can be null if no console is available.</param>
|
||||||
|
/// <param name='rawConsoleVector'>/param>
|
||||||
|
/// <param name='vector'></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool TryParseConsoleInt(ICommandConsole console, string rawConsoleInt, out int i)
|
||||||
|
{
|
||||||
|
if (!int.TryParse(rawConsoleInt, out i))
|
||||||
|
{
|
||||||
|
if (console != null)
|
||||||
|
console.OutputFormat("ERROR: {0} is not a valid integer", rawConsoleInt);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Convert a minimum vector input from the console to an OpenMetaverse.Vector3
|
/// Convert a minimum vector input from the console to an OpenMetaverse.Vector3
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -92,6 +92,7 @@ namespace OpenSim.Framework
|
||||||
// Attempt to install the plugin disabled
|
// Attempt to install the plugin disabled
|
||||||
if (Install(ps, pack) == true)
|
if (Install(ps, pack) == true)
|
||||||
{
|
{
|
||||||
|
MainConsole.Instance.Output("Ignore the following error...");
|
||||||
PluginRegistry.Update(ps);
|
PluginRegistry.Update(ps);
|
||||||
Addin addin = PluginRegistry.GetAddin(aentry.Addin.Id);
|
Addin addin = PluginRegistry.GetAddin(aentry.Addin.Id);
|
||||||
PluginRegistry.DisableAddin(addin.Id);
|
PluginRegistry.DisableAddin(addin.Id);
|
||||||
|
@ -479,6 +480,7 @@ namespace OpenSim.Framework
|
||||||
ConsoleProgressStatus ps = new ConsoleProgressStatus(false);
|
ConsoleProgressStatus ps = new ConsoleProgressStatus(false);
|
||||||
if (!AddinManager.AddinEngine.IsAddinLoaded(addin.Id))
|
if (!AddinManager.AddinEngine.IsAddinLoaded(addin.Id))
|
||||||
{
|
{
|
||||||
|
MainConsole.Instance.Output("Ignore the following error...");
|
||||||
AddinManager.Registry.Rebuild(ps);
|
AddinManager.Registry.Rebuild(ps);
|
||||||
AddinManager.AddinEngine.LoadAddin(ps, addin.Id);
|
AddinManager.AddinEngine.LoadAddin(ps, addin.Id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12077,11 +12077,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
if (logPacket)
|
if (logPacket)
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
"[CLIENT]: PACKET IN from {0} ({1}) in {2} - {3}",
|
"[CLIENT]: PACKET IN from {0} ({1}) in {2} - {3}",
|
||||||
Name, SceneAgent.IsChildAgent ? "child" : "root ", m_scene.RegionInfo.RegionName, packet.Type);
|
Name, SceneAgent.IsChildAgent ? "child" : "root ", Scene.Name, packet.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ProcessPacketMethod(packet))
|
if (!ProcessPacketMethod(packet))
|
||||||
m_log.Warn("[CLIENT]: unhandled packet " + packet.Type);
|
m_log.WarnFormat(
|
||||||
|
"[CLIENT]: Unhandled packet {0} from {1} ({2}) in {3}. Ignoring.",
|
||||||
|
packet.Type, Name, SceneAgent.IsChildAgent ? "child" : "root ", Scene.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket)
|
private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket)
|
||||||
|
|
|
@ -71,7 +71,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
|
|
||||||
#region Internal functions
|
#region Internal functions
|
||||||
|
|
||||||
public AssetMetadata FetchMetadata(string url, UUID assetID)
|
private AssetMetadata FetchMetadata(string url, UUID assetID)
|
||||||
{
|
{
|
||||||
if (!url.EndsWith("/") && !url.EndsWith("="))
|
if (!url.EndsWith("/") && !url.EndsWith("="))
|
||||||
url = url + "/";
|
url = url + "/";
|
||||||
|
@ -86,6 +86,27 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
return meta;
|
return meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AssetBase FetchAsset(string url, UUID assetID)
|
||||||
|
{
|
||||||
|
// Test if it's already here
|
||||||
|
AssetBase asset = m_scene.AssetService.Get(assetID.ToString());
|
||||||
|
if (asset == null)
|
||||||
|
{
|
||||||
|
if (!url.EndsWith("/") && !url.EndsWith("="))
|
||||||
|
url = url + "/";
|
||||||
|
|
||||||
|
asset = m_scene.AssetService.Get(url + assetID.ToString());
|
||||||
|
|
||||||
|
//if (asset != null)
|
||||||
|
// m_log.DebugFormat("[HG ASSET MAPPER]: Fetched asset {0} of type {1} from {2} ", assetID, asset.Metadata.Type, url);
|
||||||
|
//else
|
||||||
|
// m_log.DebugFormat("[HG ASSET MAPPER]: Unable to fetch asset {0} from {1} ", assetID, url);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
|
||||||
public bool PostAsset(string url, AssetBase asset)
|
public bool PostAsset(string url, AssetBase asset)
|
||||||
{
|
{
|
||||||
if (asset != null)
|
if (asset != null)
|
||||||
|
@ -228,11 +249,22 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
if (meta == null)
|
if (meta == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// The act of gathering UUIDs downloads the assets from the remote server
|
// The act of gathering UUIDs downloads some assets from the remote server
|
||||||
|
// but not all...
|
||||||
Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>();
|
Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>();
|
||||||
HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL);
|
HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL);
|
||||||
uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids);
|
uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids);
|
||||||
|
m_log.DebugFormat("[HG ASSET MAPPER]: Preparing to get {0} assets", ids.Count);
|
||||||
|
bool success = true;
|
||||||
|
foreach (UUID uuid in ids.Keys)
|
||||||
|
if (FetchAsset(userAssetURL, uuid) == null)
|
||||||
|
success = false;
|
||||||
|
|
||||||
|
// maybe all pieces got here...
|
||||||
|
if (!success)
|
||||||
|
m_log.DebugFormat("[HG ASSET MAPPER]: Problems getting item {0} from asset server {1}", assetID, userAssetURL);
|
||||||
|
else
|
||||||
|
m_log.DebugFormat("[HG ASSET MAPPER]: Successfully got item {0} from asset server {1}", assetID, userAssetURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -181,6 +181,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||||
|
|
||||||
m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query);
|
m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query);
|
||||||
|
|
||||||
|
// searhc the user accounts service
|
||||||
List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query);
|
List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query);
|
||||||
|
|
||||||
List<UserData> users = new List<UserData>();
|
List<UserData> users = new List<UserData>();
|
||||||
|
@ -196,6 +197,12 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// search the local cache
|
||||||
|
foreach (UserData data in m_UserCache.Values)
|
||||||
|
if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null &&
|
||||||
|
(data.FirstName.StartsWith(query) || data.LastName.StartsWith(query)))
|
||||||
|
users.Add(data);
|
||||||
|
|
||||||
AddAdditionalUsers(avatarID, query, users);
|
AddAdditionalUsers(avatarID, query, users);
|
||||||
|
|
||||||
AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply);
|
AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply);
|
||||||
|
@ -433,6 +440,9 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||||
public void AddUser(UUID uuid, string first, string last, string homeURL)
|
public void AddUser(UUID uuid, string first, string last, string homeURL)
|
||||||
{
|
{
|
||||||
//m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL);
|
//m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL);
|
||||||
|
if (homeURL == string.Empty)
|
||||||
|
return;
|
||||||
|
|
||||||
AddUser(uuid, homeURL + ";" + first + " " + last);
|
AddUser(uuid, homeURL + ";" + first + " " + last);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ namespace OpenSim.Region.CoreModules.World.Sound
|
||||||
|
|
||||||
public void RemoveRegion(Scene scene)
|
public void RemoveRegion(Scene scene)
|
||||||
{
|
{
|
||||||
m_scene.EventManager.OnClientLogin -= OnNewClient;
|
m_scene.EventManager.OnNewClient -= OnNewClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RegionLoaded(Scene scene)
|
public void RegionLoaded(Scene scene)
|
||||||
|
@ -85,7 +85,7 @@ namespace OpenSim.Region.CoreModules.World.Sound
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_scene = scene;
|
m_scene = scene;
|
||||||
m_scene.EventManager.OnClientLogin += OnNewClient;
|
m_scene.EventManager.OnNewClient += OnNewClient;
|
||||||
|
|
||||||
m_scene.RegisterModuleInterface<ISoundModule>(this);
|
m_scene.RegisterModuleInterface<ISoundModule>(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
using log4net;
|
using log4net;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
|
@ -113,6 +114,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation
|
||||||
if (m_scenePresence.IsChildAgent)
|
if (m_scenePresence.IsChildAgent)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Removing animation {0} for {1}", animID, m_scenePresence.Name);
|
||||||
|
|
||||||
if (m_animations.Remove(animID))
|
if (m_animations.Remove(animID))
|
||||||
SendAnimPack();
|
SendAnimPack();
|
||||||
}
|
}
|
||||||
|
@ -519,6 +522,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation
|
||||||
if (m_scenePresence.IsChildAgent)
|
if (m_scenePresence.IsChildAgent)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[SCENE PRESENCE ANIMATOR]: Sending anim pack with animations '{0}', sequence '{1}', uuids '{2}'",
|
||||||
|
// string.Join(",", Array.ConvertAll<UUID, string>(animations, a => a.ToString())),
|
||||||
|
// string.Join(",", Array.ConvertAll<int, string>(seqs, s => s.ToString())),
|
||||||
|
// string.Join(",", Array.ConvertAll<UUID, string>(objectIDs, o => o.ToString())));
|
||||||
|
|
||||||
m_scenePresence.Scene.ForEachClient(
|
m_scenePresence.Scene.ForEachClient(
|
||||||
delegate(IClientAPI client)
|
delegate(IClientAPI client)
|
||||||
{
|
{
|
||||||
|
|
|
@ -683,12 +683,10 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
itemCopy.SalePrice = item.SalePrice;
|
itemCopy.SalePrice = item.SalePrice;
|
||||||
itemCopy.SaleType = item.SaleType;
|
itemCopy.SaleType = item.SaleType;
|
||||||
|
|
||||||
if (AddInventoryItem(itemCopy))
|
|
||||||
{
|
|
||||||
IInventoryAccessModule invAccess = RequestModuleInterface<IInventoryAccessModule>();
|
IInventoryAccessModule invAccess = RequestModuleInterface<IInventoryAccessModule>();
|
||||||
if (invAccess != null)
|
if (invAccess != null)
|
||||||
Util.FireAndForget(delegate { invAccess.TransferInventoryAssets(itemCopy, senderId, recipient); });
|
invAccess.TransferInventoryAssets(itemCopy, senderId, recipient);
|
||||||
}
|
AddInventoryItem(itemCopy);
|
||||||
|
|
||||||
if (!Permissions.BypassPermissions())
|
if (!Permissions.BypassPermissions())
|
||||||
{
|
{
|
||||||
|
|
|
@ -2895,11 +2895,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
public void PhysicsOutOfBounds(Vector3 pos)
|
public void PhysicsOutOfBounds(Vector3 pos)
|
||||||
{
|
{
|
||||||
m_log.Error("[PHYSICS]: Physical Object went out of bounds.");
|
// Note: This is only being called on the root prim at this time.
|
||||||
|
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[SCENE OBJECT PART]: Physical object {0}, localID {1} went out of bounds at {2} in {3}. Stopping at {4} and making non-physical.",
|
||||||
|
Name, LocalId, pos, ParentGroup.Scene.Name, AbsolutePosition);
|
||||||
|
|
||||||
RemFlag(PrimFlags.Physics);
|
RemFlag(PrimFlags.Physics);
|
||||||
DoPhysicsPropertyUpdate(false, true);
|
DoPhysicsPropertyUpdate(false, true);
|
||||||
//ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PhysicsRequestingTerseUpdate()
|
public void PhysicsRequestingTerseUpdate()
|
||||||
|
@ -4549,7 +4552,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
if (ParentGroup.RootPart == this)
|
if (ParentGroup.RootPart == this)
|
||||||
AngularVelocity = new Vector3(0, 0, 0);
|
AngularVelocity = new Vector3(0, 0, 0);
|
||||||
}
|
}
|
||||||
else
|
else if (SetVD != wasVD)
|
||||||
{
|
{
|
||||||
if (ParentGroup.Scene.CollidablePrims)
|
if (ParentGroup.Scene.CollidablePrims)
|
||||||
{
|
{
|
||||||
|
|
|
@ -214,8 +214,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
private Quaternion m_headrotation = Quaternion.Identity;
|
private Quaternion m_headrotation = Quaternion.Identity;
|
||||||
|
|
||||||
private string m_nextSitAnimation = String.Empty;
|
|
||||||
|
|
||||||
//PauPaw:Proper PID Controler for autopilot************
|
//PauPaw:Proper PID Controler for autopilot************
|
||||||
public bool MovingToTarget { get; private set; }
|
public bool MovingToTarget { get; private set; }
|
||||||
public Vector3 MoveToPositionTarget { get; private set; }
|
public Vector3 MoveToPositionTarget { get; private set; }
|
||||||
|
@ -2120,25 +2118,10 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
StandUp();
|
StandUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (!String.IsNullOrEmpty(sitAnimation))
|
|
||||||
// {
|
|
||||||
// m_nextSitAnimation = sitAnimation;
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
m_nextSitAnimation = "SIT";
|
|
||||||
// }
|
|
||||||
|
|
||||||
//SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
|
|
||||||
SceneObjectPart part = FindNextAvailableSitTarget(targetID);
|
SceneObjectPart part = FindNextAvailableSitTarget(targetID);
|
||||||
|
|
||||||
if (part != null)
|
if (part != null)
|
||||||
{
|
{
|
||||||
if (!String.IsNullOrEmpty(part.SitAnimation))
|
|
||||||
{
|
|
||||||
m_nextSitAnimation = part.SitAnimation;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_requestedSitTargetID = part.LocalId;
|
m_requestedSitTargetID = part.LocalId;
|
||||||
m_requestedSitTargetUUID = targetID;
|
m_requestedSitTargetUUID = targetID;
|
||||||
|
|
||||||
|
@ -2352,18 +2335,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
|
public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
|
||||||
{
|
|
||||||
if (!String.IsNullOrEmpty(m_nextSitAnimation))
|
|
||||||
{
|
|
||||||
HandleAgentSit(remoteClient, agentID, m_nextSitAnimation);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HandleAgentSit(remoteClient, agentID, "SIT");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HandleAgentSit(IClientAPI remoteClient, UUID agentID, string sitAnimation)
|
|
||||||
{
|
{
|
||||||
SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
|
SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
|
||||||
|
|
||||||
|
@ -2437,6 +2408,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
Velocity = Vector3.Zero;
|
Velocity = Vector3.Zero;
|
||||||
RemoveFromPhysicalScene();
|
RemoveFromPhysicalScene();
|
||||||
|
|
||||||
|
String sitAnimation = "SIT";
|
||||||
|
if (!String.IsNullOrEmpty(part.SitAnimation))
|
||||||
|
{
|
||||||
|
sitAnimation = part.SitAnimation;
|
||||||
|
}
|
||||||
Animator.TrySetMovementAnimation(sitAnimation);
|
Animator.TrySetMovementAnimation(sitAnimation);
|
||||||
SendAvatarDataToAllAgents();
|
SendAvatarDataToAllAgents();
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,26 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None));
|
Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSetNonPhysicsVolumeDetectSinglePrim()
|
||||||
|
{
|
||||||
|
TestHelpers.InMethod();
|
||||||
|
|
||||||
|
m_scene.AddSceneObject(m_so1);
|
||||||
|
|
||||||
|
SceneObjectPart rootPart = m_so1.RootPart;
|
||||||
|
Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None));
|
||||||
|
|
||||||
|
m_so1.ScriptSetVolumeDetect(true);
|
||||||
|
|
||||||
|
// Console.WriteLine("so.RootPart.Flags [{0}]", so.RootPart.Flags);
|
||||||
|
Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Phantom));
|
||||||
|
|
||||||
|
m_so1.ScriptSetVolumeDetect(false);
|
||||||
|
|
||||||
|
Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestSetPhysicsSinglePrim()
|
public void TestSetPhysicsSinglePrim()
|
||||||
{
|
{
|
||||||
|
@ -89,7 +109,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
|
|
||||||
m_so1.ScriptSetPhysicsStatus(true);
|
m_so1.ScriptSetPhysicsStatus(true);
|
||||||
|
|
||||||
// Console.WriteLine("so.RootPart.Flags [{0}]", so.RootPart.Flags);
|
|
||||||
Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Physics));
|
Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Physics));
|
||||||
|
|
||||||
m_so1.ScriptSetPhysicsStatus(false);
|
m_so1.ScriptSetPhysicsStatus(false);
|
||||||
|
@ -97,6 +116,26 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None));
|
Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSetPhysicsVolumeDetectSinglePrim()
|
||||||
|
{
|
||||||
|
TestHelpers.InMethod();
|
||||||
|
|
||||||
|
m_scene.AddSceneObject(m_so1);
|
||||||
|
|
||||||
|
SceneObjectPart rootPart = m_so1.RootPart;
|
||||||
|
Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None));
|
||||||
|
|
||||||
|
m_so1.ScriptSetPhysicsStatus(true);
|
||||||
|
m_so1.ScriptSetVolumeDetect(true);
|
||||||
|
|
||||||
|
Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Phantom | PrimFlags.Physics));
|
||||||
|
|
||||||
|
m_so1.ScriptSetVolumeDetect(false);
|
||||||
|
|
||||||
|
Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Physics));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestSetPhysicsLinkset()
|
public void TestSetPhysicsLinkset()
|
||||||
{
|
{
|
||||||
|
|
|
@ -105,12 +105,12 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}",
|
DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}",
|
||||||
LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass);
|
LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass);
|
||||||
|
|
||||||
// do actual create at taint time
|
// do actual creation in taint time
|
||||||
PhysicsScene.TaintedObject("BSCharacter.create", delegate()
|
PhysicsScene.TaintedObject("BSCharacter.create", delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSCharacter.create,taint", LocalID);
|
DetailLog("{0},BSCharacter.create,taint", LocalID);
|
||||||
// New body and shape into PhysBody and PhysShape
|
// New body and shape into PhysBody and PhysShape
|
||||||
PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, null, null);
|
PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this);
|
||||||
|
|
||||||
SetPhysicalProperties();
|
SetPhysicalProperties();
|
||||||
});
|
});
|
||||||
|
@ -124,7 +124,9 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
PhysicsScene.TaintedObject("BSCharacter.destroy", delegate()
|
PhysicsScene.TaintedObject("BSCharacter.destroy", delegate()
|
||||||
{
|
{
|
||||||
PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null);
|
PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null);
|
||||||
|
PhysBody.Clear();
|
||||||
PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null);
|
PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null);
|
||||||
|
PhysShape.Clear();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,9 +167,8 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
|
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
|
||||||
|
|
||||||
// Do this after the object has been added to the world
|
// Do this after the object has been added to the world
|
||||||
BulletSimAPI.SetCollisionGroupMask2(PhysBody.ptr,
|
PhysBody.collisionType = CollisionType.Avatar;
|
||||||
(uint)CollisionFilterGroups.AvatarGroup,
|
PhysBody.ApplyCollisionMask();
|
||||||
(uint)CollisionFilterGroups.AvatarMask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void RequestPhysicsterseUpdate()
|
public override void RequestPhysicsterseUpdate()
|
||||||
|
@ -187,22 +188,30 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
set {
|
set {
|
||||||
// When an avatar's size is set, only the height is changed.
|
// When an avatar's size is set, only the height is changed.
|
||||||
_size = value;
|
_size = value;
|
||||||
|
// Old versions of ScenePresence passed only the height. If width and/or depth are zero,
|
||||||
|
// replace with the default values.
|
||||||
|
if (_size.X == 0f) _size.X = PhysicsScene.Params.avatarCapsuleDepth;
|
||||||
|
if (_size.Y == 0f) _size.Y = PhysicsScene.Params.avatarCapsuleWidth;
|
||||||
|
|
||||||
ComputeAvatarScale(_size);
|
ComputeAvatarScale(_size);
|
||||||
ComputeAvatarVolumeAndMass();
|
ComputeAvatarVolumeAndMass();
|
||||||
DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}",
|
DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}",
|
||||||
LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass);
|
LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass);
|
||||||
|
|
||||||
PhysicsScene.TaintedObject("BSCharacter.setSize", delegate()
|
PhysicsScene.TaintedObject("BSCharacter.setSize", delegate()
|
||||||
|
{
|
||||||
|
if (PhysBody.HasPhysicalBody && PhysShape.HasPhysicalShape)
|
||||||
{
|
{
|
||||||
BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale);
|
BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale);
|
||||||
UpdatePhysicalMassProperties(RawMass);
|
UpdatePhysicalMassProperties(RawMass);
|
||||||
|
// Make sure this change appears as a property update event
|
||||||
|
BulletSimAPI.PushUpdate2(PhysBody.ptr);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override OMV.Vector3 Scale { get; set; }
|
|
||||||
|
|
||||||
public override PrimitiveBaseShape Shape
|
public override PrimitiveBaseShape Shape
|
||||||
{
|
{
|
||||||
set { BaseShape = value; }
|
set { BaseShape = value; }
|
||||||
|
@ -236,6 +245,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
// Zero some other properties directly into the physics engine
|
// Zero some other properties directly into the physics engine
|
||||||
PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate()
|
PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate()
|
||||||
{
|
{
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
BulletSimAPI.ClearAllForces2(PhysBody.ptr);
|
BulletSimAPI.ClearAllForces2(PhysBody.ptr);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -244,11 +254,14 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
_rotationalVelocity = OMV.Vector3.Zero;
|
_rotationalVelocity = OMV.Vector3.Zero;
|
||||||
|
|
||||||
PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate()
|
PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate()
|
||||||
|
{
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
{
|
{
|
||||||
BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero);
|
BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero);
|
||||||
BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero);
|
BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero);
|
||||||
// The next also get rid of applied linear force but the linear velocity is untouched.
|
// The next also get rid of applied linear force but the linear velocity is untouched.
|
||||||
BulletSimAPI.ClearForces2(PhysBody.ptr);
|
BulletSimAPI.ClearForces2(PhysBody.ptr);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,6 +286,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate()
|
PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
|
BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -332,6 +346,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate()
|
PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
|
BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
|
||||||
});
|
});
|
||||||
ret = true;
|
ret = true;
|
||||||
|
@ -359,6 +374,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate()
|
PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force);
|
DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force);
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force);
|
BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -398,6 +414,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
if (_currentFriction != PhysicsScene.Params.avatarStandingFriction)
|
if (_currentFriction != PhysicsScene.Params.avatarStandingFriction)
|
||||||
{
|
{
|
||||||
_currentFriction = PhysicsScene.Params.avatarStandingFriction;
|
_currentFriction = PhysicsScene.Params.avatarStandingFriction;
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction);
|
BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -406,6 +423,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
if (_currentFriction != PhysicsScene.Params.avatarFriction)
|
if (_currentFriction != PhysicsScene.Params.avatarFriction)
|
||||||
{
|
{
|
||||||
_currentFriction = PhysicsScene.Params.avatarFriction;
|
_currentFriction = PhysicsScene.Params.avatarFriction;
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction);
|
BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -442,9 +460,12 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
_orientation = value;
|
_orientation = value;
|
||||||
// m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation);
|
// m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation);
|
||||||
PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate()
|
PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate()
|
||||||
|
{
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
{
|
{
|
||||||
// _position = BulletSimAPI.GetPosition2(BSBody.ptr);
|
// _position = BulletSimAPI.GetPosition2(BSBody.ptr);
|
||||||
BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
|
BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -516,11 +537,14 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
set {
|
set {
|
||||||
_floatOnWater = value;
|
_floatOnWater = value;
|
||||||
PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate()
|
PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate()
|
||||||
|
{
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
{
|
{
|
||||||
if (_floatOnWater)
|
if (_floatOnWater)
|
||||||
CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
|
CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
|
||||||
else
|
else
|
||||||
CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
|
CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -553,6 +577,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
|
DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
|
||||||
// Buoyancy is faked by changing the gravity applied to the object
|
// Buoyancy is faked by changing the gravity applied to the object
|
||||||
float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
|
float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav));
|
BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -599,6 +624,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate()
|
PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force);
|
DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force);
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force);
|
BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -616,9 +642,6 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
|
|
||||||
private void ComputeAvatarScale(OMV.Vector3 size)
|
private void ComputeAvatarScale(OMV.Vector3 size)
|
||||||
{
|
{
|
||||||
// The 'size' given by the simulator is the mid-point of the avatar
|
|
||||||
// and X and Y are unspecified.
|
|
||||||
|
|
||||||
OMV.Vector3 newScale = size;
|
OMV.Vector3 newScale = size;
|
||||||
// newScale.X = PhysicsScene.Params.avatarCapsuleWidth;
|
// newScale.X = PhysicsScene.Params.avatarCapsuleWidth;
|
||||||
// newScale.Y = PhysicsScene.Params.avatarCapsuleDepth;
|
// newScale.Y = PhysicsScene.Params.avatarCapsuleDepth;
|
||||||
|
|
|
@ -57,7 +57,7 @@ public abstract class BSConstraint : IDisposable
|
||||||
if (m_enabled)
|
if (m_enabled)
|
||||||
{
|
{
|
||||||
m_enabled = false;
|
m_enabled = false;
|
||||||
if (m_constraint.ptr != IntPtr.Zero)
|
if (m_constraint.HasPhysicalConstraint)
|
||||||
{
|
{
|
||||||
bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr);
|
bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr);
|
||||||
m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}",
|
m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}",
|
||||||
|
@ -65,7 +65,7 @@ public abstract class BSConstraint : IDisposable
|
||||||
m_body1.ID, m_body1.ptr.ToString("X"),
|
m_body1.ID, m_body1.ptr.ToString("X"),
|
||||||
m_body2.ID, m_body2.ptr.ToString("X"),
|
m_body2.ID, m_body2.ptr.ToString("X"),
|
||||||
success);
|
success);
|
||||||
m_constraint.ptr = System.IntPtr.Zero;
|
m_constraint.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ public sealed class BSConstraint6Dof : BSConstraint
|
||||||
m_world = world;
|
m_world = world;
|
||||||
m_body1 = obj1;
|
m_body1 = obj1;
|
||||||
m_body2 = obj2;
|
m_body2 = obj2;
|
||||||
if (obj1.ptr == IntPtr.Zero || obj2.ptr == IntPtr.Zero)
|
if (!obj1.HasPhysicalBody || !obj2.HasPhysicalBody)
|
||||||
{
|
{
|
||||||
world.physicsScene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
|
world.physicsScene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
|
||||||
BSScene.DetailLogZero, world.worldID,
|
BSScene.DetailLogZero, world.worldID,
|
||||||
|
@ -83,7 +83,7 @@ public sealed class BSConstraint6Dof : BSConstraint
|
||||||
world.physicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}",
|
world.physicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}",
|
||||||
BSScene.DetailLogZero, world.worldID, m_constraint.ptr.ToString("X"),
|
BSScene.DetailLogZero, world.worldID, m_constraint.ptr.ToString("X"),
|
||||||
obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X"));
|
obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X"));
|
||||||
if (m_constraint.ptr == IntPtr.Zero)
|
if (!m_constraint.HasPhysicalConstraint)
|
||||||
{
|
{
|
||||||
world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}",
|
world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}",
|
||||||
LogHeader, obj1.ID, obj2.ID);
|
LogHeader, obj1.ID, obj2.ID);
|
||||||
|
|
|
@ -570,8 +570,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia);
|
BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia);
|
||||||
BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr);
|
BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr);
|
||||||
|
|
||||||
VDetailLog("{0},BSDynamics.Refresh,frict={1},inert={2},aDamp={3}",
|
VDetailLog("{0},BSDynamics.Refresh,mass={1},frict={2},inert={3},aDamp={4}",
|
||||||
Prim.LocalID, friction, localInertia, angularDamping);
|
Prim.LocalID, m_vehicleMass, friction, localInertia, angularDamping);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -818,6 +818,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
+ hoverContribution
|
+ hoverContribution
|
||||||
+ limitMotorUpContribution;
|
+ limitMotorUpContribution;
|
||||||
|
|
||||||
|
Vector3 newForce = buoyancyContribution;
|
||||||
|
|
||||||
// If not changing some axis, reduce out velocity
|
// If not changing some axis, reduce out velocity
|
||||||
if ((m_flags & (VehicleFlag.NO_X)) != 0)
|
if ((m_flags & (VehicleFlag.NO_X)) != 0)
|
||||||
newVelocity.X = 0;
|
newVelocity.X = 0;
|
||||||
|
@ -845,7 +847,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
VehicleVelocity = newVelocity;
|
VehicleVelocity = newVelocity;
|
||||||
|
|
||||||
// Other linear forces are applied as forces.
|
// Other linear forces are applied as forces.
|
||||||
Vector3 totalDownForce = buoyancyContribution * m_vehicleMass;
|
Vector3 totalDownForce = newForce * m_vehicleMass;
|
||||||
if (!totalDownForce.ApproxEquals(Vector3.Zero, 0.01f))
|
if (!totalDownForce.ApproxEquals(Vector3.Zero, 0.01f))
|
||||||
{
|
{
|
||||||
VehicleAddForce(totalDownForce);
|
VehicleAddForce(totalDownForce);
|
||||||
|
@ -991,8 +993,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
|
|
||||||
if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
|
if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
|
||||||
{
|
{
|
||||||
// If the vehicle is motoring into the sky, get it going back down.
|
float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition);
|
||||||
float distanceAboveGround = VehiclePosition.Z - GetTerrainHeight(VehiclePosition);
|
float distanceAboveGround = VehiclePosition.Z - targetHeight;
|
||||||
// Not colliding if the vehicle is off the ground
|
// Not colliding if the vehicle is off the ground
|
||||||
if (!Prim.IsColliding)
|
if (!Prim.IsColliding)
|
||||||
{
|
{
|
||||||
|
@ -1005,8 +1007,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
// has a decay factor. This says this force should
|
// has a decay factor. This says this force should
|
||||||
// be computed with a motor.
|
// be computed with a motor.
|
||||||
// TODO: add interaction with banking.
|
// TODO: add interaction with banking.
|
||||||
VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},downForce={2}",
|
VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}",
|
||||||
Prim.LocalID, distanceAboveGround, ret);
|
Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1055,7 +1057,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
// TODO: Should this be applied as an angular force (torque)?
|
// TODO: Should this be applied as an angular force (torque)?
|
||||||
if (!m_lastAngularCorrection.ApproxEquals(Vector3.Zero, 0.01f))
|
if (!m_lastAngularCorrection.ApproxEquals(Vector3.Zero, 0.01f))
|
||||||
{
|
{
|
||||||
Vector3 scaledCorrection = m_lastAngularCorrection * pTimestep;
|
// DEBUG DEBUG DEBUG: optionally scale the angular velocity. Debugging SL vs ODE turning functions.
|
||||||
|
Vector3 scaledCorrection = m_lastAngularCorrection;
|
||||||
|
if (PhysicsScene.VehicleScaleAngularVelocityByTimestep)
|
||||||
|
scaledCorrection *= pTimestep;
|
||||||
VehicleRotationalVelocity = scaledCorrection;
|
VehicleRotationalVelocity = scaledCorrection;
|
||||||
|
|
||||||
VDetailLog("{0}, MoveAngular,done,nonZero,angMotorContrib={1},vertAttrContrib={2},bankContrib={3},deflectContrib={4},totalContrib={5},scaledCorr={6}",
|
VDetailLog("{0}, MoveAngular,done,nonZero,angMotorContrib={1},vertAttrContrib={2},bankContrib={3},deflectContrib={4},totalContrib={5},scaledCorr={6}",
|
||||||
|
|
|
@ -32,6 +32,14 @@ using OMV = OpenMetaverse;
|
||||||
|
|
||||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// A BSPrim can get individual information about its linkedness attached
|
||||||
|
// to it through an instance of a subclass of LinksetInfo.
|
||||||
|
// Each type of linkset will define the information needed for its type.
|
||||||
|
public abstract class BSLinksetInfo
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public abstract class BSLinkset
|
public abstract class BSLinkset
|
||||||
{
|
{
|
||||||
// private static string LogHeader = "[BULLETSIM LINKSET]";
|
// private static string LogHeader = "[BULLETSIM LINKSET]";
|
||||||
|
@ -116,7 +124,7 @@ public abstract class BSLinkset
|
||||||
get { return ComputeLinksetGeometricCenter(); }
|
get { return ComputeLinksetGeometricCenter(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void Initialize(BSScene scene, BSPhysObject parent)
|
protected BSLinkset(BSScene scene, BSPhysObject parent)
|
||||||
{
|
{
|
||||||
// A simple linkset of one (no children)
|
// A simple linkset of one (no children)
|
||||||
LinksetID = m_nextLinksetID++;
|
LinksetID = m_nextLinksetID++;
|
||||||
|
@ -127,6 +135,7 @@ public abstract class BSLinkset
|
||||||
LinksetRoot = parent;
|
LinksetRoot = parent;
|
||||||
m_children = new HashSet<BSPhysObject>();
|
m_children = new HashSet<BSPhysObject>();
|
||||||
m_mass = parent.RawMass;
|
m_mass = parent.RawMass;
|
||||||
|
Rebuilding = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link to a linkset where the child knows the parent.
|
// Link to a linkset where the child knows the parent.
|
||||||
|
@ -229,6 +238,10 @@ public abstract class BSLinkset
|
||||||
// May be called at runtime or taint-time.
|
// May be called at runtime or taint-time.
|
||||||
public abstract void Refresh(BSPhysObject requestor);
|
public abstract void Refresh(BSPhysObject requestor);
|
||||||
|
|
||||||
|
// Flag denoting the linkset is in the process of being rebuilt.
|
||||||
|
// Used to know not the schedule a rebuild in the middle of a rebuild.
|
||||||
|
protected bool Rebuilding { get; set; }
|
||||||
|
|
||||||
// The object is going dynamic (physical). Do any setup necessary
|
// The object is going dynamic (physical). Do any setup necessary
|
||||||
// for a dynamic linkset.
|
// for a dynamic linkset.
|
||||||
// Only the state of the passed object can be modified. The rest of the linkset
|
// Only the state of the passed object can be modified. The rest of the linkset
|
||||||
|
|
|
@ -32,18 +32,43 @@ using OMV = OpenMetaverse;
|
||||||
|
|
||||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// When a child is linked, the relationship position of the child to the parent
|
||||||
|
// is remembered so the child's world position can be recomputed when it is
|
||||||
|
// removed from the linkset.
|
||||||
|
sealed class BSLinksetCompoundInfo : BSLinksetInfo
|
||||||
|
{
|
||||||
|
public OMV.Vector3 OffsetPos;
|
||||||
|
public OMV.Quaternion OffsetRot;
|
||||||
|
public BSLinksetCompoundInfo(OMV.Vector3 p, OMV.Quaternion r)
|
||||||
|
{
|
||||||
|
OffsetPos = p;
|
||||||
|
OffsetRot = r;
|
||||||
|
}
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
StringBuilder buff = new StringBuilder();
|
||||||
|
buff.Append("<p=");
|
||||||
|
buff.Append(OffsetPos.ToString());
|
||||||
|
buff.Append(",r=");
|
||||||
|
buff.Append(OffsetRot.ToString());
|
||||||
|
buff.Append(">");
|
||||||
|
return buff.ToString();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public sealed class BSLinksetCompound : BSLinkset
|
public sealed class BSLinksetCompound : BSLinkset
|
||||||
{
|
{
|
||||||
private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]";
|
private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]";
|
||||||
|
|
||||||
public BSLinksetCompound(BSScene scene, BSPhysObject parent)
|
public BSLinksetCompound(BSScene scene, BSPhysObject parent) : base(scene, parent)
|
||||||
{
|
{
|
||||||
base.Initialize(scene, parent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For compound implimented linksets, if there are children, use compound shape for the root.
|
// For compound implimented linksets, if there are children, use compound shape for the root.
|
||||||
public override BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
|
public override BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
|
||||||
{
|
{
|
||||||
|
// Returning 'unknown' means we don't have a preference.
|
||||||
BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
if (IsRoot(requestor) && HasAnyChildren)
|
if (IsRoot(requestor) && HasAnyChildren)
|
||||||
{
|
{
|
||||||
|
@ -55,24 +80,28 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
|
|
||||||
// When physical properties are changed the linkset needs to recalculate
|
// When physical properties are changed the linkset needs to recalculate
|
||||||
// its internal properties.
|
// its internal properties.
|
||||||
// This is queued in the 'post taint' queue so the
|
|
||||||
// refresh will happen once after all the other taints are applied.
|
|
||||||
public override void Refresh(BSPhysObject requestor)
|
public override void Refresh(BSPhysObject requestor)
|
||||||
{
|
{
|
||||||
// External request for Refresh (from BSPrim) doesn't need to do anything
|
// External request for Refresh (from BSPrim) doesn't need to do anything
|
||||||
// InternalRefresh(requestor);
|
// InternalRefresh(requestor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Schedule a refresh to happen after all the other taint processing.
|
||||||
private void InternalRefresh(BSPhysObject requestor)
|
private void InternalRefresh(BSPhysObject requestor)
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID);
|
DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1},rebuilding={2}",
|
||||||
// Queue to happen after all the other taint processing
|
LinksetRoot.LocalID, requestor.LocalID, Rebuilding);
|
||||||
|
// When rebuilding, it is possible to set properties that would normally require a rebuild.
|
||||||
|
// If already rebuilding, don't request another rebuild.
|
||||||
|
if (!Rebuilding)
|
||||||
|
{
|
||||||
PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate()
|
PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate()
|
||||||
{
|
{
|
||||||
if (IsRoot(requestor) && HasAnyChildren)
|
if (IsRoot(requestor) && HasAnyChildren)
|
||||||
RecomputeLinksetCompound();
|
RecomputeLinksetCompound();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The object is going dynamic (physical). Do any setup necessary
|
// The object is going dynamic (physical). Do any setup necessary
|
||||||
// for a dynamic linkset.
|
// for a dynamic linkset.
|
||||||
|
@ -84,12 +113,24 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
DetailLog("{0},BSLinksetCompound.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child));
|
DetailLog("{0},BSLinksetCompound.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child));
|
||||||
if (!IsRoot(child))
|
if (IsRoot(child))
|
||||||
|
{
|
||||||
|
// The root is going dynamic. Make sure mass is properly set.
|
||||||
|
m_mass = ComputeLinksetMass();
|
||||||
|
if (HasAnyChildren)
|
||||||
|
InternalRefresh(LinksetRoot);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// The origional prims are removed from the world as the shape of the root compound
|
// The origional prims are removed from the world as the shape of the root compound
|
||||||
// shape takes over.
|
// shape takes over.
|
||||||
BulletSimAPI.AddToCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
|
BulletSimAPI.AddToCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
|
||||||
BulletSimAPI.ForceActivationState2(child.PhysBody.ptr, ActivationState.DISABLE_SIMULATION);
|
BulletSimAPI.ForceActivationState2(child.PhysBody.ptr, ActivationState.DISABLE_SIMULATION);
|
||||||
|
// We don't want collisions from the old linkset children.
|
||||||
|
BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||||
|
|
||||||
|
child.PhysBody.collisionType = CollisionType.LinksetChild;
|
||||||
|
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -104,11 +145,19 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child));
|
DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child));
|
||||||
if (!IsRoot(child))
|
if (IsRoot(child))
|
||||||
|
{
|
||||||
|
if (HasAnyChildren)
|
||||||
|
InternalRefresh(LinksetRoot);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// The non-physical children can come back to life.
|
// The non-physical children can come back to life.
|
||||||
BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
|
BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
|
||||||
// Don't force activation so setting of DISABLE_SIMULATION can stay.
|
|
||||||
|
child.PhysBody.collisionType = CollisionType.LinksetChild;
|
||||||
|
|
||||||
|
// Don't force activation so setting of DISABLE_SIMULATION can stay if used.
|
||||||
BulletSimAPI.Activate2(child.PhysBody.ptr, false);
|
BulletSimAPI.Activate2(child.PhysBody.ptr, false);
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
|
@ -146,11 +195,15 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
|
|
||||||
if (!IsRoot(child))
|
if (!IsRoot(child))
|
||||||
{
|
{
|
||||||
// Cause the current shape to be freed and the new one to be built.
|
// Because it is a convenient time, recompute child world position and rotation based on
|
||||||
InternalRefresh(LinksetRoot);
|
// its position in the linkset.
|
||||||
ret = true;
|
RecomputeChildWorldPosition(child, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cannot schedule a refresh/rebuild here because this routine is called when
|
||||||
|
// the linkset is being rebuilt.
|
||||||
|
// InternalRefresh(LinksetRoot);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +212,41 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
// Called at taint-time!!
|
// Called at taint-time!!
|
||||||
public override void RestoreBodyDependencies(BSPrim child)
|
public override void RestoreBodyDependencies(BSPrim child)
|
||||||
{
|
{
|
||||||
// The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints.
|
}
|
||||||
|
|
||||||
|
// When the linkset is built, the child shape is added to the compound shape relative to the
|
||||||
|
// root shape. The linkset then moves around but this does not move the actual child
|
||||||
|
// prim. The child prim's location must be recomputed based on the location of the root shape.
|
||||||
|
private void RecomputeChildWorldPosition(BSPhysObject child, bool inTaintTime)
|
||||||
|
{
|
||||||
|
BSLinksetCompoundInfo lci = child.LinksetInfo as BSLinksetCompoundInfo;
|
||||||
|
if (lci != null)
|
||||||
|
{
|
||||||
|
if (inTaintTime)
|
||||||
|
{
|
||||||
|
OMV.Vector3 oldPos = child.RawPosition;
|
||||||
|
child.ForcePosition = LinksetRoot.RawPosition + lci.OffsetPos;
|
||||||
|
child.ForceOrientation = LinksetRoot.RawOrientation * lci.OffsetRot;
|
||||||
|
DetailLog("{0},BSLinksetCompound.RecomputeChildWorldPosition,oldPos={1},lci={2},newPos={3}",
|
||||||
|
child.LocalID, oldPos, lci, child.RawPosition);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TaintedObject is not used here so the raw position is set now and not at taint-time.
|
||||||
|
child.Position = LinksetRoot.RawPosition + lci.OffsetPos;
|
||||||
|
child.Orientation = LinksetRoot.RawOrientation * lci.OffsetRot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This happens when children have been added to the linkset but the linkset
|
||||||
|
// has not been constructed yet. So like, at taint time, adding children to a linkset
|
||||||
|
// and then changing properties of the children (makePhysical, for instance)
|
||||||
|
// but the post-print action of actually rebuilding the linkset has not yet happened.
|
||||||
|
// PhysicsScene.Logger.WarnFormat("{0} Restoring linkset child position failed because of no relative position computed. ID={1}",
|
||||||
|
// LogHeader, child.LocalID);
|
||||||
|
DetailLog("{0},BSLinksetCompound.recomputeChildWorldPosition,noRelativePositonInfo", child.LocalID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ================================================================
|
// ================================================================
|
||||||
|
@ -181,7 +268,7 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the specified child from the linkset.
|
// Remove the specified child from the linkset.
|
||||||
// Safe to call even if the child is not really in my linkset.
|
// Safe to call even if the child is not really in the linkset.
|
||||||
protected override void RemoveChildFromLinkset(BSPhysObject child)
|
protected override void RemoveChildFromLinkset(BSPhysObject child)
|
||||||
{
|
{
|
||||||
if (m_children.Remove(child))
|
if (m_children.Remove(child))
|
||||||
|
@ -192,6 +279,7 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
child.LocalID, child.PhysBody.ptr.ToString("X"));
|
child.LocalID, child.PhysBody.ptr.ToString("X"));
|
||||||
|
|
||||||
// Cause the child's body to be rebuilt and thus restored to normal operation
|
// Cause the child's body to be rebuilt and thus restored to normal operation
|
||||||
|
RecomputeChildWorldPosition(child, false);
|
||||||
child.ForceBodyShapeRebuild(false);
|
child.ForceBodyShapeRebuild(false);
|
||||||
|
|
||||||
if (!HasAnyChildren)
|
if (!HasAnyChildren)
|
||||||
|
@ -215,6 +303,11 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
// Called at taint time!!
|
// Called at taint time!!
|
||||||
private void RecomputeLinksetCompound()
|
private void RecomputeLinksetCompound()
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Suppress rebuilding while rebuilding
|
||||||
|
Rebuilding = true;
|
||||||
|
|
||||||
// Cause the root shape to be rebuilt as a compound object with just the root in it
|
// Cause the root shape to be rebuilt as a compound object with just the root in it
|
||||||
LinksetRoot.ForceBodyShapeRebuild(true);
|
LinksetRoot.ForceBodyShapeRebuild(true);
|
||||||
|
|
||||||
|
@ -225,49 +318,68 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
ForEachMember(delegate(BSPhysObject cPrim)
|
ForEachMember(delegate(BSPhysObject cPrim)
|
||||||
{
|
{
|
||||||
if (!IsRoot(cPrim))
|
if (!IsRoot(cPrim))
|
||||||
|
{
|
||||||
|
// Compute the displacement of the child from the root of the linkset.
|
||||||
|
// This info is saved in the child prim so the relationship does not
|
||||||
|
// change over time and the new child position can be computed
|
||||||
|
// when the linkset is being disassembled (the linkset may have moved).
|
||||||
|
BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo;
|
||||||
|
if (lci == null)
|
||||||
{
|
{
|
||||||
// Each child position and rotation is given relative to the root.
|
// Each child position and rotation is given relative to the root.
|
||||||
OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation);
|
OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation);
|
||||||
OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation;
|
OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation;
|
||||||
OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation;
|
OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation;
|
||||||
|
|
||||||
|
// Save relative position for recomputing child's world position after moving linkset.
|
||||||
|
lci = new BSLinksetCompoundInfo(displacementPos, displacementRot);
|
||||||
|
cPrim.LinksetInfo = lci;
|
||||||
|
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci);
|
||||||
|
}
|
||||||
|
|
||||||
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}",
|
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}",
|
||||||
LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, displacementPos, displacementRot);
|
LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot);
|
||||||
|
|
||||||
if (cPrim.PhysShape.isNativeShape)
|
if (cPrim.PhysShape.isNativeShape)
|
||||||
{
|
{
|
||||||
// Native shapes are not shared so we need to create a new one.
|
// A native shape is turning into a hull collision shape because native
|
||||||
// A mesh or hull is created because scale is not available on a native shape.
|
// shapes are not shared so we have to hullify it so it will be tracked
|
||||||
// (TODO: Bullet does have a btScaledCollisionShape. Can that be used?)
|
// and freed at the correct time. This also solves the scaling problem
|
||||||
|
// (native shapes scaled but hull/meshes are assumed to not be).
|
||||||
|
// TODO: decide of the native shape can just be used in the compound shape.
|
||||||
|
// Use call to CreateGeomNonSpecial().
|
||||||
BulletShape saveShape = cPrim.PhysShape;
|
BulletShape saveShape = cPrim.PhysShape;
|
||||||
cPrim.PhysShape.ptr = IntPtr.Zero; // Don't let the create free the child's shape
|
cPrim.PhysShape.Clear(); // Don't let the create free the child's shape
|
||||||
|
// PhysicsScene.Shapes.CreateGeomNonSpecial(true, cPrim, null);
|
||||||
PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
|
PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
|
||||||
BulletShape newShape = cPrim.PhysShape;
|
BulletShape newShape = cPrim.PhysShape;
|
||||||
cPrim.PhysShape = saveShape;
|
cPrim.PhysShape = saveShape;
|
||||||
BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, displacementPos, displacementRot);
|
BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, lci.OffsetPos, lci.OffsetRot);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// For the shared shapes (meshes and hulls), just use the shape in the child.
|
// For the shared shapes (meshes and hulls), just use the shape in the child.
|
||||||
|
// The reference count added here will be decremented when the compound shape
|
||||||
|
// is destroyed in BSShapeCollection (the child shapes are looped over and dereferenced).
|
||||||
if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape))
|
if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape))
|
||||||
{
|
{
|
||||||
PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
|
PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
|
||||||
LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
|
LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
|
||||||
}
|
}
|
||||||
BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, displacementPos, displacementRot);
|
BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, lci.OffsetPos, lci.OffsetRot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: need to phantomize the child prims left behind.
|
|
||||||
// Maybe just destroy the children bodies and shapes and have them rebuild on unlink.
|
|
||||||
// Selection/deselection might cause way too many build/destructions esp. for LARGE linksets.
|
|
||||||
|
|
||||||
return false; // 'false' says to move onto the next child in the list
|
return false; // 'false' says to move onto the next child in the list
|
||||||
});
|
});
|
||||||
|
|
||||||
// With all of the linkset packed into the root prim, it has the mass of everyone.
|
// With all of the linkset packed into the root prim, it has the mass of everyone.
|
||||||
float linksetMass = LinksetMass;
|
float linksetMass = LinksetMass;
|
||||||
LinksetRoot.UpdatePhysicalMassProperties(linksetMass);
|
LinksetRoot.UpdatePhysicalMassProperties(linksetMass);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Rebuilding = false;
|
||||||
|
}
|
||||||
|
|
||||||
BulletSimAPI.RecalculateCompoundShapeLocalAabb2(LinksetRoot.PhysShape.ptr);
|
BulletSimAPI.RecalculateCompoundShapeLocalAabb2(LinksetRoot.PhysShape.ptr);
|
||||||
|
|
||||||
|
|
|
@ -36,9 +36,8 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||||
{
|
{
|
||||||
// private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]";
|
// private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]";
|
||||||
|
|
||||||
public BSLinksetConstraints(BSScene scene, BSPhysObject parent)
|
public BSLinksetConstraints(BSScene scene, BSPhysObject parent) : base(scene, parent)
|
||||||
{
|
{
|
||||||
base.Initialize(scene, parent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// When physical properties are changed the linkset needs to recalculate
|
// When physical properties are changed the linkset needs to recalculate
|
||||||
|
|
|
@ -50,10 +50,11 @@ public struct MaterialAttributes
|
||||||
Avatar,
|
Avatar,
|
||||||
NumberOfTypes // the count of types in the enum.
|
NumberOfTypes // the count of types in the enum.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Names must be in the order of the above enum.
|
// Names must be in the order of the above enum.
|
||||||
public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood",
|
// These names must coorespond to the lower case field names in the MaterialAttributes
|
||||||
"Flesh", "Plastic", "Rubber", "Light", "Avatar" };
|
// structure as reflection is used to select the field to put the value in.
|
||||||
public static string[] MaterialAttribs = { "Density", "Friction", "Restitution"};
|
public static readonly string[] MaterialAttribs = { "Density", "Friction", "Restitution"};
|
||||||
|
|
||||||
public MaterialAttributes(string t, float d, float f, float r)
|
public MaterialAttributes(string t, float d, float f, float r)
|
||||||
{
|
{
|
||||||
|
@ -70,23 +71,37 @@ public struct MaterialAttributes
|
||||||
|
|
||||||
public static class BSMaterials
|
public static class BSMaterials
|
||||||
{
|
{
|
||||||
public static MaterialAttributes[] Attributes;
|
// Attributes for each material type
|
||||||
|
private static readonly MaterialAttributes[] Attributes;
|
||||||
|
|
||||||
|
// Map of material name to material type code
|
||||||
|
public static readonly Dictionary<string, MaterialAttributes.Material> MaterialMap;
|
||||||
|
|
||||||
static BSMaterials()
|
static BSMaterials()
|
||||||
{
|
{
|
||||||
// Attribute sets for both the non-physical and physical instances of materials.
|
// Attribute sets for both the non-physical and physical instances of materials.
|
||||||
Attributes = new MaterialAttributes[(int)MaterialAttributes.Material.NumberOfTypes * 2];
|
Attributes = new MaterialAttributes[(int)MaterialAttributes.Material.NumberOfTypes * 2];
|
||||||
|
|
||||||
|
// Map of name to type code.
|
||||||
|
MaterialMap = new Dictionary<string, MaterialAttributes.Material>();
|
||||||
|
MaterialMap.Add("Stone", MaterialAttributes.Material.Stone);
|
||||||
|
MaterialMap.Add("Metal", MaterialAttributes.Material.Metal);
|
||||||
|
MaterialMap.Add("Glass", MaterialAttributes.Material.Glass);
|
||||||
|
MaterialMap.Add("Wood", MaterialAttributes.Material.Wood);
|
||||||
|
MaterialMap.Add("Flesh", MaterialAttributes.Material.Flesh);
|
||||||
|
MaterialMap.Add("Plastic", MaterialAttributes.Material.Plastic);
|
||||||
|
MaterialMap.Add("Rubber", MaterialAttributes.Material.Rubber);
|
||||||
|
MaterialMap.Add("Light", MaterialAttributes.Material.Light);
|
||||||
|
MaterialMap.Add("Avatar", MaterialAttributes.Material.Avatar);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is where all the default material attributes are defined.
|
// This is where all the default material attributes are defined.
|
||||||
public static void InitializeFromDefaults(ConfigurationParameters parms)
|
public static void InitializeFromDefaults(ConfigurationParameters parms)
|
||||||
{
|
{
|
||||||
// Values from http://wiki.secondlife.com/wiki/PRIM_MATERIAL
|
// Values from http://wiki.secondlife.com/wiki/PRIM_MATERIAL
|
||||||
// public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood",
|
float dDensity = parms.defaultDensity;
|
||||||
// "Flesh", "Plastic", "Rubber", "Light", "Avatar" };
|
|
||||||
float dFriction = parms.defaultFriction;
|
float dFriction = parms.defaultFriction;
|
||||||
float dRestitution = parms.defaultRestitution;
|
float dRestitution = parms.defaultRestitution;
|
||||||
float dDensity = parms.defaultDensity;
|
|
||||||
Attributes[(int)MaterialAttributes.Material.Stone] =
|
Attributes[(int)MaterialAttributes.Material.Stone] =
|
||||||
new MaterialAttributes("stone",dDensity, 0.8f, 0.4f);
|
new MaterialAttributes("stone",dDensity, 0.8f, 0.4f);
|
||||||
Attributes[(int)MaterialAttributes.Material.Metal] =
|
Attributes[(int)MaterialAttributes.Material.Metal] =
|
||||||
|
@ -139,34 +154,34 @@ public static class BSMaterials
|
||||||
// the physical value.
|
// the physical value.
|
||||||
public static void InitializefromParameters(IConfig pConfig)
|
public static void InitializefromParameters(IConfig pConfig)
|
||||||
{
|
{
|
||||||
int matType = 0;
|
foreach (KeyValuePair<string, MaterialAttributes.Material> kvp in MaterialMap)
|
||||||
foreach (string matName in MaterialAttributes.MaterialNames)
|
|
||||||
{
|
{
|
||||||
|
string matName = kvp.Key;
|
||||||
foreach (string attribName in MaterialAttributes.MaterialAttribs)
|
foreach (string attribName in MaterialAttributes.MaterialAttribs)
|
||||||
{
|
{
|
||||||
string paramName = matName + attribName;
|
string paramName = matName + attribName;
|
||||||
if (pConfig.Contains(paramName))
|
if (pConfig.Contains(paramName))
|
||||||
{
|
{
|
||||||
float paramValue = pConfig.GetFloat(paramName);
|
float paramValue = pConfig.GetFloat(paramName);
|
||||||
SetAttributeValue(matType, attribName, paramValue);
|
SetAttributeValue((int)kvp.Value, attribName, paramValue);
|
||||||
// set the physical value also
|
// set the physical value also
|
||||||
SetAttributeValue(matType + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue);
|
SetAttributeValue((int)kvp.Value + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue);
|
||||||
}
|
}
|
||||||
paramName += "Physical";
|
paramName += "Physical";
|
||||||
if (pConfig.Contains(paramName))
|
if (pConfig.Contains(paramName))
|
||||||
{
|
{
|
||||||
float paramValue = pConfig.GetFloat(paramName);
|
float paramValue = pConfig.GetFloat(paramName);
|
||||||
SetAttributeValue(matType + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue);
|
SetAttributeValue((int)kvp.Value + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
matType++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use reflection to set the value in the attribute structure.
|
||||||
private static void SetAttributeValue(int matType, string attribName, float val)
|
private static void SetAttributeValue(int matType, string attribName, float val)
|
||||||
{
|
{
|
||||||
MaterialAttributes thisAttrib = Attributes[matType];
|
MaterialAttributes thisAttrib = Attributes[matType];
|
||||||
FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName);
|
FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName.ToLower());
|
||||||
if (fieldInfo != null)
|
if (fieldInfo != null)
|
||||||
{
|
{
|
||||||
fieldInfo.SetValue(thisAttrib, val);
|
fieldInfo.SetValue(thisAttrib, val);
|
||||||
|
@ -174,12 +189,12 @@ public static class BSMaterials
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Given a material type, return a structure of attributes.
|
||||||
public static MaterialAttributes GetAttributes(MaterialAttributes.Material type, bool isPhysical)
|
public static MaterialAttributes GetAttributes(MaterialAttributes.Material type, bool isPhysical)
|
||||||
{
|
{
|
||||||
int ind = (int)type;
|
int ind = (int)type;
|
||||||
if (isPhysical) ind += (int)MaterialAttributes.Material.NumberOfTypes;
|
if (isPhysical) ind += (int)MaterialAttributes.Material.NumberOfTypes;
|
||||||
return Attributes[ind];
|
return Attributes[ind];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ public abstract class BSMotor
|
||||||
// Can all the incremental stepping be replaced with motor classes?
|
// Can all the incremental stepping be replaced with motor classes?
|
||||||
|
|
||||||
// Motor which moves CurrentValue to TargetValue over TimeScale seconds.
|
// Motor which moves CurrentValue to TargetValue over TimeScale seconds.
|
||||||
// The TargetValue is decays in TargetValueDecayTimeScale and
|
// The TargetValue decays in TargetValueDecayTimeScale and
|
||||||
// the CurrentValue will be held back by FrictionTimeScale.
|
// the CurrentValue will be held back by FrictionTimeScale.
|
||||||
// TimeScale and TargetDelayTimeScale may be 'infinite' which means go decay.
|
// TimeScale and TargetDelayTimeScale may be 'infinite' which means go decay.
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,9 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
Linkset = BSLinkset.Factory(PhysicsScene, this);
|
Linkset = BSLinkset.Factory(PhysicsScene, this);
|
||||||
LastAssetBuildFailed = false;
|
LastAssetBuildFailed = false;
|
||||||
|
|
||||||
|
// Default material type
|
||||||
|
Material = MaterialAttributes.Material.Wood;
|
||||||
|
|
||||||
CollisionCollection = new CollisionEventUpdate();
|
CollisionCollection = new CollisionEventUpdate();
|
||||||
SubscribedEventsMs = 0;
|
SubscribedEventsMs = 0;
|
||||||
CollidingStep = 0;
|
CollidingStep = 0;
|
||||||
|
@ -72,6 +75,7 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
public string TypeName { get; protected set; }
|
public string TypeName { get; protected set; }
|
||||||
|
|
||||||
public BSLinkset Linkset { get; set; }
|
public BSLinkset Linkset { get; set; }
|
||||||
|
public BSLinksetInfo LinksetInfo { get; set; }
|
||||||
|
|
||||||
// Return the object mass without calculating it or having side effects
|
// Return the object mass without calculating it or having side effects
|
||||||
public abstract float RawMass { get; }
|
public abstract float RawMass { get; }
|
||||||
|
@ -105,10 +109,17 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
public EntityProperties CurrentEntityProperties { get; set; }
|
public EntityProperties CurrentEntityProperties { get; set; }
|
||||||
public EntityProperties LastEntityProperties { get; set; }
|
public EntityProperties LastEntityProperties { get; set; }
|
||||||
|
|
||||||
public abstract OMV.Vector3 Scale { get; set; }
|
public virtual OMV.Vector3 Scale { get; set; }
|
||||||
public abstract bool IsSolid { get; }
|
public abstract bool IsSolid { get; }
|
||||||
public abstract bool IsStatic { get; }
|
public abstract bool IsStatic { get; }
|
||||||
|
|
||||||
|
// Materialness
|
||||||
|
public MaterialAttributes.Material Material { get; private set; }
|
||||||
|
public override void SetMaterial(int material)
|
||||||
|
{
|
||||||
|
Material = (MaterialAttributes.Material)material;
|
||||||
|
}
|
||||||
|
|
||||||
// Stop all physical motion.
|
// Stop all physical motion.
|
||||||
public abstract void ZeroMotion(bool inTaintTime);
|
public abstract void ZeroMotion(bool inTaintTime);
|
||||||
public abstract void ZeroAngularMotion(bool inTaintTime);
|
public abstract void ZeroAngularMotion(bool inTaintTime);
|
||||||
|
@ -128,6 +139,17 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
public abstract OMV.Quaternion RawOrientation { get; set; }
|
public abstract OMV.Quaternion RawOrientation { get; set; }
|
||||||
public abstract OMV.Quaternion ForceOrientation { get; set; }
|
public abstract OMV.Quaternion ForceOrientation { get; set; }
|
||||||
|
|
||||||
|
// The system is telling us the velocity it wants to move at.
|
||||||
|
protected OMV.Vector3 m_targetVelocity;
|
||||||
|
public override OMV.Vector3 TargetVelocity
|
||||||
|
{
|
||||||
|
get { return m_targetVelocity; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
m_targetVelocity = value;
|
||||||
|
Velocity = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
public abstract OMV.Vector3 ForceVelocity { get; set; }
|
public abstract OMV.Vector3 ForceVelocity { get; set; }
|
||||||
|
|
||||||
public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
|
public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
|
||||||
|
@ -243,6 +265,8 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
SubscribedEventsMs = 0;
|
SubscribedEventsMs = 0;
|
||||||
PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate()
|
PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate()
|
||||||
{
|
{
|
||||||
|
// Make sure there is a body there because sometimes destruction happens in an un-ideal order.
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,6 @@ public sealed class BSPrim : BSPhysObject
|
||||||
private static readonly string LogHeader = "[BULLETS PRIM]";
|
private static readonly string LogHeader = "[BULLETS PRIM]";
|
||||||
|
|
||||||
// _size is what the user passed. Scale is what we pass to the physics engine with the mesh.
|
// _size is what the user passed. Scale is what we pass to the physics engine with the mesh.
|
||||||
// Often Scale is unity because the meshmerizer will apply _size when creating the mesh.
|
|
||||||
private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user
|
private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user
|
||||||
|
|
||||||
private bool _grabbed;
|
private bool _grabbed;
|
||||||
|
@ -93,7 +92,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
_physicsActorType = (int)ActorTypes.Prim;
|
_physicsActorType = (int)ActorTypes.Prim;
|
||||||
_position = pos;
|
_position = pos;
|
||||||
_size = size;
|
_size = size;
|
||||||
Scale = size; // the scale will be set by CreateGeom depending on object type
|
Scale = size; // prims are the size the user wants them to be (different for BSCharactes).
|
||||||
_orientation = rotation;
|
_orientation = rotation;
|
||||||
_buoyancy = 1f;
|
_buoyancy = 1f;
|
||||||
_velocity = OMV.Vector3.Zero;
|
_velocity = OMV.Vector3.Zero;
|
||||||
|
@ -108,8 +107,8 @@ public sealed class BSPrim : BSPhysObject
|
||||||
_mass = CalculateMass();
|
_mass = CalculateMass();
|
||||||
|
|
||||||
// No body or shape yet
|
// No body or shape yet
|
||||||
PhysBody = new BulletBody(LocalID, IntPtr.Zero);
|
PhysBody = new BulletBody(LocalID);
|
||||||
PhysShape = new BulletShape(IntPtr.Zero);
|
PhysShape = new BulletShape();
|
||||||
|
|
||||||
DetailLog("{0},BSPrim.constructor,call", LocalID);
|
DetailLog("{0},BSPrim.constructor,call", LocalID);
|
||||||
// do the actual object creation at taint time
|
// do the actual object creation at taint time
|
||||||
|
@ -143,7 +142,9 @@ public sealed class BSPrim : BSPhysObject
|
||||||
DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
|
DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
|
||||||
// If there are physical body and shape, release my use of same.
|
// If there are physical body and shape, release my use of same.
|
||||||
PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null);
|
PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null);
|
||||||
|
PhysBody.Clear();
|
||||||
PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null);
|
PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null);
|
||||||
|
PhysShape.Clear();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,12 +158,10 @@ public sealed class BSPrim : BSPhysObject
|
||||||
// We presume the scale and size are the same. If scale must be changed for
|
// We presume the scale and size are the same. If scale must be changed for
|
||||||
// the physical shape, that is done when the geometry is built.
|
// the physical shape, that is done when the geometry is built.
|
||||||
_size = value;
|
_size = value;
|
||||||
|
Scale = _size;
|
||||||
ForceBodyShapeRebuild(false);
|
ForceBodyShapeRebuild(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Scale is what we set in the physics engine. It is different than 'size' in that
|
|
||||||
// 'size' can be encorporated into the mesh. In that case, the scale is <1,1,1>.
|
|
||||||
public override OMV.Vector3 Scale { get; set; }
|
|
||||||
|
|
||||||
public override PrimitiveBaseShape Shape {
|
public override PrimitiveBaseShape Shape {
|
||||||
set {
|
set {
|
||||||
|
@ -189,7 +188,8 @@ public sealed class BSPrim : BSPhysObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public override bool Selected {
|
public override bool Selected {
|
||||||
set {
|
set
|
||||||
|
{
|
||||||
if (value != _isSelected)
|
if (value != _isSelected)
|
||||||
{
|
{
|
||||||
_isSelected = value;
|
_isSelected = value;
|
||||||
|
@ -247,6 +247,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
// Zero some other properties in the physics engine
|
// Zero some other properties in the physics engine
|
||||||
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
|
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
|
||||||
{
|
{
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
BulletSimAPI.ClearAllForces2(PhysBody.ptr);
|
BulletSimAPI.ClearAllForces2(PhysBody.ptr);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -257,8 +258,11 @@ public sealed class BSPrim : BSPhysObject
|
||||||
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
|
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
|
||||||
{
|
{
|
||||||
// DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity);
|
// DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity);
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
|
{
|
||||||
BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
|
BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
|
||||||
BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
|
BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,8 +299,11 @@ public sealed class BSPrim : BSPhysObject
|
||||||
PhysicsScene.TaintedObject("BSPrim.setPosition", delegate()
|
PhysicsScene.TaintedObject("BSPrim.setPosition", delegate()
|
||||||
{
|
{
|
||||||
// DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
// DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
|
{
|
||||||
BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
|
BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
|
||||||
ActivateIfPhysical(false);
|
ActivateIfPhysical(false);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -322,12 +329,12 @@ public sealed class BSPrim : BSPhysObject
|
||||||
|
|
||||||
float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position);
|
float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position);
|
||||||
OMV.Vector3 upForce = OMV.Vector3.Zero;
|
OMV.Vector3 upForce = OMV.Vector3.Zero;
|
||||||
if (Position.Z < terrainHeight)
|
if (RawPosition.Z < terrainHeight)
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
|
DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
|
||||||
float targetHeight = terrainHeight + (Size.Z / 2f);
|
float targetHeight = terrainHeight + (Size.Z / 2f);
|
||||||
// Upforce proportional to the distance away from the terrain. Correct the error in 1 sec.
|
// Upforce proportional to the distance away from the terrain. Correct the error in 1 sec.
|
||||||
upForce.Z = (terrainHeight - Position.Z) * 1f;
|
upForce.Z = (terrainHeight - RawPosition.Z) * 1f;
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,10 +342,10 @@ public sealed class BSPrim : BSPhysObject
|
||||||
{
|
{
|
||||||
float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position);
|
float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position);
|
||||||
// TODO: a floating motor so object will bob in the water
|
// TODO: a floating motor so object will bob in the water
|
||||||
if (Math.Abs(Position.Z - waterHeight) > 0.1f)
|
if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f)
|
||||||
{
|
{
|
||||||
// Upforce proportional to the distance away from the water. Correct the error in 1 sec.
|
// Upforce proportional to the distance away from the water. Correct the error in 1 sec.
|
||||||
upForce.Z = (waterHeight - Position.Z) * 1f;
|
upForce.Z = (waterHeight - RawPosition.Z) * 1f;
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -413,6 +420,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
PhysicsScene.TaintedObject("BSPrim.setForce", delegate()
|
PhysicsScene.TaintedObject("BSPrim.setForce", delegate()
|
||||||
{
|
{
|
||||||
// DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
|
// DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force);
|
BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -507,6 +515,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate()
|
PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate()
|
||||||
{
|
{
|
||||||
// DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
|
// DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity);
|
BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -555,10 +564,13 @@ public sealed class BSPrim : BSPhysObject
|
||||||
_orientation = value;
|
_orientation = value;
|
||||||
// TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
|
// TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
|
||||||
PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
|
PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
|
||||||
|
{
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
{
|
{
|
||||||
// _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr);
|
// _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr);
|
||||||
// DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
// DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||||
BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
|
BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -649,14 +661,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
|
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
|
||||||
|
|
||||||
// Collision filter can be set only when the object is in the world
|
// Collision filter can be set only when the object is in the world
|
||||||
if (PhysBody.collisionGroup != 0 || PhysBody.collisionMask != 0)
|
PhysBody.ApplyCollisionMask();
|
||||||
{
|
|
||||||
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.
|
// Recompute any linkset parameters.
|
||||||
// When going from non-physical to physical, this re-enables the constraints that
|
// When going from non-physical to physical, this re-enables the constraints that
|
||||||
|
@ -683,8 +688,9 @@ public sealed class BSPrim : BSPhysObject
|
||||||
ZeroMotion(true);
|
ZeroMotion(true);
|
||||||
|
|
||||||
// Set various physical properties so other object interact properly
|
// Set various physical properties so other object interact properly
|
||||||
BulletSimAPI.SetFriction2(PhysBody.ptr, PhysicsScene.Params.defaultFriction);
|
MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false);
|
||||||
BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.defaultRestitution);
|
BulletSimAPI.SetFriction2(PhysBody.ptr, matAttrib.friction);
|
||||||
|
BulletSimAPI.SetRestitution2(PhysBody.ptr, matAttrib.restitution);
|
||||||
|
|
||||||
// Mass is zero which disables a bunch of physics stuff in Bullet
|
// Mass is zero which disables a bunch of physics stuff in Bullet
|
||||||
UpdatePhysicalMassProperties(0f);
|
UpdatePhysicalMassProperties(0f);
|
||||||
|
@ -700,20 +706,21 @@ public sealed class BSPrim : BSPhysObject
|
||||||
// Start it out sleeping and physical actions could wake it up.
|
// Start it out sleeping and physical actions could wake it up.
|
||||||
BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ISLAND_SLEEPING);
|
BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ISLAND_SLEEPING);
|
||||||
|
|
||||||
|
// This collides like a static object
|
||||||
|
PhysBody.collisionType = CollisionType.Static;
|
||||||
|
|
||||||
// There can be special things needed for implementing linksets
|
// There can be special things needed for implementing linksets
|
||||||
Linkset.MakeStatic(this);
|
Linkset.MakeStatic(this);
|
||||||
|
|
||||||
PhysBody.collisionGroup = CollisionFilterGroups.StaticObjectGroup;
|
|
||||||
PhysBody.collisionMask = CollisionFilterGroups.StaticObjectMask;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Not a Bullet static object
|
// Not a Bullet static object
|
||||||
CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
|
CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
|
||||||
|
|
||||||
// Set various physical properties so internal dynamic properties will get computed correctly as they are set
|
// Set various physical properties so other object interact properly
|
||||||
BulletSimAPI.SetFriction2(PhysBody.ptr, PhysicsScene.Params.defaultFriction);
|
MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, true);
|
||||||
BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.defaultRestitution);
|
BulletSimAPI.SetFriction2(PhysBody.ptr, matAttrib.friction);
|
||||||
|
BulletSimAPI.SetRestitution2(PhysBody.ptr, matAttrib.restitution);
|
||||||
|
|
||||||
// per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
|
// per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
|
||||||
// Since this can be called multiple times, only zero forces when becoming physical
|
// Since this can be called multiple times, only zero forces when becoming physical
|
||||||
|
@ -741,16 +748,15 @@ public sealed class BSPrim : BSPhysObject
|
||||||
BulletSimAPI.SetSleepingThresholds2(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold);
|
BulletSimAPI.SetSleepingThresholds2(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold);
|
||||||
BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold);
|
BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold);
|
||||||
|
|
||||||
// There might be special things needed for implementing linksets.
|
// This collides like an object.
|
||||||
Linkset.MakeDynamic(this);
|
PhysBody.collisionType = CollisionType.Dynamic;
|
||||||
|
|
||||||
// Force activation of the object so Bullet will act on it.
|
// Force activation of the object so Bullet will act on it.
|
||||||
// Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
|
// Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
|
||||||
BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG);
|
BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG);
|
||||||
// BulletSimAPI.Activate2(BSBody.ptr, true);
|
|
||||||
|
|
||||||
PhysBody.collisionGroup = CollisionFilterGroups.ObjectGroup;
|
// There might be special things needed for implementing linksets.
|
||||||
PhysBody.collisionMask = CollisionFilterGroups.ObjectMask;
|
Linkset.MakeDynamic(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -777,8 +783,9 @@ 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);
|
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);
|
CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
|
||||||
PhysBody.collisionGroup = CollisionFilterGroups.VolumeDetectGroup;
|
|
||||||
PhysBody.collisionMask = CollisionFilterGroups.VolumeDetectMask;
|
// Change collision info from a static object to a ghosty collision object
|
||||||
|
PhysBody.collisionType = CollisionType.VolumeDetect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -861,6 +868,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
|
PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
|
DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
|
BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -896,10 +904,13 @@ public sealed class BSPrim : BSPhysObject
|
||||||
_buoyancy = value;
|
_buoyancy = value;
|
||||||
// DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
|
// DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
|
||||||
// Buoyancy is faked by changing the gravity applied to the object
|
// Buoyancy is faked by changing the gravity applied to the object
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
|
{
|
||||||
float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
|
float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
|
||||||
BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav));
|
BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Used for MoveTo
|
// Used for MoveTo
|
||||||
public override OMV.Vector3 PIDTarget {
|
public override OMV.Vector3 PIDTarget {
|
||||||
|
@ -965,6 +976,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
}
|
}
|
||||||
DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum);
|
DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum);
|
||||||
if (fSum != OMV.Vector3.Zero)
|
if (fSum != OMV.Vector3.Zero)
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum);
|
BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -976,6 +988,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyForceImpulse", delegate()
|
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyForceImpulse", delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSPrim.ApplyForceImpulse,taint,tImpulse={1}", LocalID, applyImpulse);
|
DetailLog("{0},BSPrim.ApplyForceImpulse,taint,tImpulse={1}", LocalID, applyImpulse);
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
BulletSimAPI.ApplyCentralImpulse2(PhysBody.ptr, applyImpulse);
|
BulletSimAPI.ApplyCentralImpulse2(PhysBody.ptr, applyImpulse);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1012,6 +1025,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum);
|
DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum);
|
||||||
if (fSum != OMV.Vector3.Zero)
|
if (fSum != OMV.Vector3.Zero)
|
||||||
{
|
{
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum);
|
BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum);
|
||||||
_torque = fSum;
|
_torque = fSum;
|
||||||
}
|
}
|
||||||
|
@ -1026,6 +1040,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
OMV.Vector3 applyImpulse = impulse;
|
OMV.Vector3 applyImpulse = impulse;
|
||||||
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate()
|
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate()
|
||||||
{
|
{
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse);
|
BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1344,7 +1359,6 @@ public sealed class BSPrim : BSPhysObject
|
||||||
// Create the correct physical representation for this type of object.
|
// Create the correct physical representation for this type of object.
|
||||||
// Updates PhysBody and PhysShape with the new information.
|
// Updates PhysBody and PhysShape with the new information.
|
||||||
// Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary.
|
// Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary.
|
||||||
// Returns 'true' if either the body or the shape was changed.
|
|
||||||
PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody)
|
PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody)
|
||||||
{
|
{
|
||||||
// Called if the current prim body is about to be destroyed.
|
// Called if the current prim body is about to be destroyed.
|
||||||
|
|
|
@ -188,6 +188,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
private bool m_physicsLoggingDoFlush;
|
private bool m_physicsLoggingDoFlush;
|
||||||
// 'true' of the vehicle code is to log lots of details
|
// 'true' of the vehicle code is to log lots of details
|
||||||
public bool VehicleLoggingEnabled { get; private set; }
|
public bool VehicleLoggingEnabled { get; private set; }
|
||||||
|
public bool VehiclePhysicalLoggingEnabled { get; private set; }
|
||||||
|
public bool VehicleScaleAngularVelocityByTimestep { get; private set; }
|
||||||
|
|
||||||
#region Construction and Initialization
|
#region Construction and Initialization
|
||||||
public BSScene(string identifier)
|
public BSScene(string identifier)
|
||||||
|
@ -297,6 +299,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
m_physicsLoggingDoFlush = pConfig.GetBoolean("PhysicsLoggingDoFlush", false);
|
m_physicsLoggingDoFlush = pConfig.GetBoolean("PhysicsLoggingDoFlush", false);
|
||||||
// Very detailed logging for vehicle debugging
|
// Very detailed logging for vehicle debugging
|
||||||
VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
|
VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
|
||||||
|
VehiclePhysicalLoggingEnabled = pConfig.GetBoolean("VehiclePhysicalLoggingEnabled", false);
|
||||||
|
|
||||||
// Do any replacements in the parameters
|
// Do any replacements in the parameters
|
||||||
m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
|
m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
|
||||||
|
@ -306,6 +309,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
BSMaterials.InitializeFromDefaults(Params);
|
BSMaterials.InitializeFromDefaults(Params);
|
||||||
if (pConfig != null)
|
if (pConfig != null)
|
||||||
{
|
{
|
||||||
|
// Let the user add new and interesting material property values.
|
||||||
BSMaterials.InitializefromParameters(pConfig);
|
BSMaterials.InitializefromParameters(pConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -501,7 +505,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG
|
if (VehiclePhysicalLoggingEnabled) DumpVehicles(); // DEBUG
|
||||||
if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
|
if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
|
||||||
|
|
||||||
numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep,
|
numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep,
|
||||||
|
@ -510,7 +514,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime);
|
if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime);
|
||||||
DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}",
|
DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}",
|
||||||
DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount);
|
DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount);
|
||||||
if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG
|
if (VehiclePhysicalLoggingEnabled) DumpVehicles(); // DEBUG
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -1226,6 +1230,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
(s,cf,p,v) => { s.m_params[0].vehicleAngularDamping = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { s.m_params[0].vehicleAngularDamping = cf.GetFloat(p, v); },
|
||||||
(s) => { return s.m_params[0].vehicleAngularDamping; },
|
(s) => { return s.m_params[0].vehicleAngularDamping; },
|
||||||
(s,p,l,v) => { s.m_params[0].vehicleAngularDamping = v; } ),
|
(s,p,l,v) => { s.m_params[0].vehicleAngularDamping = v; } ),
|
||||||
|
new ParameterDefn("VehicleScaleAngularVelocityByTimestep", "If true, scale angular turning by timestep",
|
||||||
|
ConfigurationParameters.numericFalse,
|
||||||
|
(s,cf,p,v) => { s.VehicleScaleAngularVelocityByTimestep = cf.GetBoolean(p, s.BoolNumeric(v)); },
|
||||||
|
(s) => { return s.NumericBool(s.VehicleScaleAngularVelocityByTimestep); },
|
||||||
|
(s,p,l,v) => { s.VehicleScaleAngularVelocityByTimestep = s.BoolNumeric(v); } ),
|
||||||
|
|
||||||
new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
|
new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
|
||||||
0f,
|
0f,
|
||||||
|
|
|
@ -126,6 +126,11 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim)
|
||||||
|
{
|
||||||
|
return GetBodyAndShape(forceRebuild, sim, prim, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
// Track another user of a body.
|
// Track another user of a body.
|
||||||
// We presume the caller has allocated the body.
|
// We presume the caller has allocated the body.
|
||||||
// Bodies only have one user so the body is just put into the world if not already there.
|
// Bodies only have one user so the body is just put into the world if not already there.
|
||||||
|
@ -149,7 +154,7 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
// Called when releasing use of a BSBody. BSShape is handled separately.
|
// Called when releasing use of a BSBody. BSShape is handled separately.
|
||||||
public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback )
|
public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback )
|
||||||
{
|
{
|
||||||
if (body.ptr == IntPtr.Zero)
|
if (!body.HasPhysicalBody)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lock (m_collectionActivityLock)
|
lock (m_collectionActivityLock)
|
||||||
|
@ -243,12 +248,12 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
// Release the usage of a shape.
|
// Release the usage of a shape.
|
||||||
public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback)
|
public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback)
|
||||||
{
|
{
|
||||||
if (shape.ptr == IntPtr.Zero)
|
if (!shape.HasPhysicalShape)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate()
|
PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate()
|
||||||
{
|
{
|
||||||
if (shape.ptr != IntPtr.Zero)
|
if (shape.HasPhysicalShape)
|
||||||
{
|
{
|
||||||
if (shape.isNativeShape)
|
if (shape.isNativeShape)
|
||||||
{
|
{
|
||||||
|
@ -440,7 +445,7 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a mesh/hull shape or a native shape if 'nativeShapePossible' is 'true'.
|
// Create a mesh/hull shape or a native shape if 'nativeShapePossible' is 'true'.
|
||||||
private bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
|
public bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
bool haveShape = false;
|
bool haveShape = false;
|
||||||
|
@ -460,6 +465,11 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
&& pbs.PathScaleX == 100 && pbs.PathScaleY == 100
|
&& pbs.PathScaleX == 100 && pbs.PathScaleY == 100
|
||||||
&& pbs.PathShearX == 0 && pbs.PathShearY == 0) ) )
|
&& pbs.PathShearX == 0 && pbs.PathShearY == 0) ) )
|
||||||
{
|
{
|
||||||
|
// Get the scale of any existing shape so we can see if the new shape is same native type and same size.
|
||||||
|
OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero;
|
||||||
|
if (prim.PhysShape.HasPhysicalShape)
|
||||||
|
scaleOfExistingShape = BulletSimAPI.GetLocalScaling2(prim.PhysShape.ptr);
|
||||||
|
|
||||||
if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}",
|
if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}",
|
||||||
prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.type);
|
prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.type);
|
||||||
|
|
||||||
|
@ -469,7 +479,7 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
{
|
{
|
||||||
haveShape = true;
|
haveShape = true;
|
||||||
if (forceRebuild
|
if (forceRebuild
|
||||||
|| prim.Scale != prim.Size
|
|| prim.Scale != scaleOfExistingShape
|
||||||
|| prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE
|
|| prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -483,7 +493,7 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
{
|
{
|
||||||
haveShape = true;
|
haveShape = true;
|
||||||
if (forceRebuild
|
if (forceRebuild
|
||||||
|| prim.Scale != prim.Size
|
|| prim.Scale != scaleOfExistingShape
|
||||||
|| prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX
|
|| prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -542,7 +552,6 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
prim.LocalID, newShape, prim.Scale);
|
prim.LocalID, newShape, prim.Scale);
|
||||||
|
|
||||||
// native shapes are scaled by Bullet
|
// native shapes are scaled by Bullet
|
||||||
prim.Scale = prim.Size;
|
|
||||||
prim.PhysShape = newShape;
|
prim.PhysShape = newShape;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -555,8 +564,8 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
ShapeData nativeShapeData = new ShapeData();
|
ShapeData nativeShapeData = new ShapeData();
|
||||||
nativeShapeData.Type = shapeType;
|
nativeShapeData.Type = shapeType;
|
||||||
nativeShapeData.ID = prim.LocalID;
|
nativeShapeData.ID = prim.LocalID;
|
||||||
nativeShapeData.Scale = prim.Size;
|
nativeShapeData.Scale = prim.Scale;
|
||||||
nativeShapeData.Size = prim.Size; // unneeded, I think.
|
nativeShapeData.Size = prim.Scale; // unneeded, I think.
|
||||||
nativeShapeData.MeshKey = (ulong)shapeKey;
|
nativeShapeData.MeshKey = (ulong)shapeKey;
|
||||||
nativeShapeData.HullKey = (ulong)shapeKey;
|
nativeShapeData.HullKey = (ulong)shapeKey;
|
||||||
|
|
||||||
|
@ -573,7 +582,7 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
// Native shapes are scaled in Bullet so set the scaling to the size
|
// Native shapes are scaled in Bullet so set the scaling to the size
|
||||||
newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType);
|
newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType);
|
||||||
}
|
}
|
||||||
if (newShape.ptr == IntPtr.Zero)
|
if (!newShape.HasPhysicalShape)
|
||||||
{
|
{
|
||||||
PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
|
PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
|
||||||
LogHeader, prim.LocalID, shapeType);
|
LogHeader, prim.LocalID, shapeType);
|
||||||
|
@ -590,7 +599,7 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
// Called at taint-time!
|
// Called at taint-time!
|
||||||
private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
|
private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
|
||||||
{
|
{
|
||||||
BulletShape newShape = new BulletShape(IntPtr.Zero);
|
BulletShape newShape = new BulletShape();
|
||||||
|
|
||||||
float lod;
|
float lod;
|
||||||
System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
|
System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
|
||||||
|
@ -611,8 +620,6 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
|
|
||||||
ReferenceShape(newShape);
|
ReferenceShape(newShape);
|
||||||
|
|
||||||
// meshes are already scaled by the meshmerizer
|
|
||||||
prim.Scale = new OMV.Vector3(1f, 1f, 1f);
|
|
||||||
prim.PhysShape = newShape;
|
prim.PhysShape = newShape;
|
||||||
|
|
||||||
return true; // 'true' means a new shape has been added to this prim
|
return true; // 'true' means a new shape has been added to this prim
|
||||||
|
@ -683,8 +690,6 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
|
|
||||||
ReferenceShape(newShape);
|
ReferenceShape(newShape);
|
||||||
|
|
||||||
// hulls are already scaled by the meshmerizer
|
|
||||||
prim.Scale = new OMV.Vector3(1f, 1f, 1f);
|
|
||||||
prim.PhysShape = newShape;
|
prim.PhysShape = newShape;
|
||||||
return true; // 'true' means a new shape has been added to this prim
|
return true; // 'true' means a new shape has been added to this prim
|
||||||
}
|
}
|
||||||
|
@ -793,7 +798,7 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
BulletShape newShape = new BulletShape(hullPtr, BSPhysicsShapeType.SHAPE_HULL);
|
BulletShape newShape = new BulletShape(hullPtr, BSPhysicsShapeType.SHAPE_HULL);
|
||||||
newShape.shapeKey = newHullKey;
|
newShape.shapeKey = newHullKey;
|
||||||
|
|
||||||
return newShape; // 'true' means a new shape has been added to this prim
|
return newShape;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Callback from convex hull creater with a newly created hull.
|
// Callback from convex hull creater with a newly created hull.
|
||||||
|
@ -860,7 +865,7 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim)
|
private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim)
|
||||||
{
|
{
|
||||||
// If the shape was successfully created, nothing more to do
|
// If the shape was successfully created, nothing more to do
|
||||||
if (newShape.ptr != IntPtr.Zero)
|
if (newShape.HasPhysicalShape)
|
||||||
return newShape;
|
return newShape;
|
||||||
|
|
||||||
// If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
|
// If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
|
||||||
|
@ -919,7 +924,7 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
// the mesh, hull or native shape must have already been created in Bullet
|
// the mesh, hull or native shape must have already been created in Bullet
|
||||||
bool mustRebuild = (prim.PhysBody.ptr == IntPtr.Zero);
|
bool mustRebuild = !prim.PhysBody.HasPhysicalBody;
|
||||||
|
|
||||||
// If there is an existing body, verify it's of an acceptable type.
|
// If there is an existing body, verify it's of an acceptable type.
|
||||||
// If not a solid object, body is a GhostObject. Otherwise a RigidBody.
|
// If not a solid object, body is a GhostObject. Otherwise a RigidBody.
|
||||||
|
|
|
@ -121,9 +121,8 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
|
||||||
// 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_mapInfo.terrainBody.ptr);
|
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr);
|
||||||
|
|
||||||
BulletSimAPI.SetCollisionGroupMask2(m_mapInfo.terrainBody.ptr,
|
m_mapInfo.terrainBody.collisionType = CollisionType.Terrain;
|
||||||
(uint)CollisionFilterGroups.TerrainGroup,
|
m_mapInfo.terrainBody.ApplyCollisionMask();
|
||||||
(uint)CollisionFilterGroups.TerrainMask);
|
|
||||||
|
|
||||||
// Make it so the terrain will not move or be considered for movement.
|
// Make it so the terrain will not move or be considered for movement.
|
||||||
BulletSimAPI.ForceActivationState2(m_mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION);
|
BulletSimAPI.ForceActivationState2(m_mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION);
|
||||||
|
@ -136,7 +135,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
|
||||||
{
|
{
|
||||||
if (m_mapInfo != null)
|
if (m_mapInfo != null)
|
||||||
{
|
{
|
||||||
if (m_mapInfo.terrainBody.ptr != IntPtr.Zero)
|
if (m_mapInfo.terrainBody.HasPhysicalBody)
|
||||||
{
|
{
|
||||||
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr);
|
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr);
|
||||||
// Frees both the body and the shape.
|
// Frees both the body and the shape.
|
||||||
|
|
|
@ -140,8 +140,8 @@ public sealed class BSTerrainManager
|
||||||
// Ground plane does not move
|
// Ground plane does not move
|
||||||
BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION);
|
BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION);
|
||||||
// Everything collides with the ground plane.
|
// Everything collides with the ground plane.
|
||||||
BulletSimAPI.SetCollisionGroupMask2(m_groundPlane.ptr,
|
m_groundPlane.collisionType = CollisionType.Groundplane;
|
||||||
(uint)CollisionFilterGroups.GroundPlaneGroup, (uint)CollisionFilterGroups.GroundPlaneMask);
|
m_groundPlane.ApplyCollisionMask();
|
||||||
|
|
||||||
// Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain.
|
// 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);
|
BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize);
|
||||||
|
@ -151,13 +151,13 @@ public sealed class BSTerrainManager
|
||||||
// Release all the terrain structures we might have allocated
|
// Release all the terrain structures we might have allocated
|
||||||
public void ReleaseGroundPlaneAndTerrain()
|
public void ReleaseGroundPlaneAndTerrain()
|
||||||
{
|
{
|
||||||
if (m_groundPlane.ptr != IntPtr.Zero)
|
if (m_groundPlane.HasPhysicalBody)
|
||||||
{
|
{
|
||||||
if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr))
|
if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr))
|
||||||
{
|
{
|
||||||
BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_groundPlane.ptr);
|
BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_groundPlane.ptr);
|
||||||
}
|
}
|
||||||
m_groundPlane.ptr = IntPtr.Zero;
|
m_groundPlane.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
ReleaseTerrain();
|
ReleaseTerrain();
|
||||||
|
|
|
@ -94,7 +94,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
||||||
m_terrainShape = new BulletShape(BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr,
|
m_terrainShape = new BulletShape(BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr,
|
||||||
indicesCount, indices, verticesCount, vertices),
|
indicesCount, indices, verticesCount, vertices),
|
||||||
BSPhysicsShapeType.SHAPE_MESH);
|
BSPhysicsShapeType.SHAPE_MESH);
|
||||||
if (m_terrainShape.ptr == IntPtr.Zero)
|
if (!m_terrainShape.HasPhysicalShape)
|
||||||
{
|
{
|
||||||
// DISASTER!!
|
// DISASTER!!
|
||||||
PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID);
|
PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID);
|
||||||
|
@ -107,7 +107,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
||||||
Quaternion rot = Quaternion.Identity;
|
Quaternion rot = Quaternion.Identity;
|
||||||
|
|
||||||
m_terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2( m_terrainShape.ptr, ID, pos, rot));
|
m_terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2( m_terrainShape.ptr, ID, pos, rot));
|
||||||
if (m_terrainBody.ptr == IntPtr.Zero)
|
if (!m_terrainBody.HasPhysicalBody)
|
||||||
{
|
{
|
||||||
// DISASTER!!
|
// DISASTER!!
|
||||||
physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase);
|
physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase);
|
||||||
|
@ -130,9 +130,8 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
||||||
// 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.UpdateSingleAabb2(PhysicsScene.World.ptr, m_terrainBody.ptr);
|
||||||
|
|
||||||
BulletSimAPI.SetCollisionGroupMask2(m_terrainBody.ptr,
|
m_terrainBody.collisionType = CollisionType.Terrain;
|
||||||
(uint)CollisionFilterGroups.TerrainGroup,
|
m_terrainBody.ApplyCollisionMask();
|
||||||
(uint)CollisionFilterGroups.TerrainMask);
|
|
||||||
|
|
||||||
// Make it so the terrain will not move or be considered for movement.
|
// Make it so the terrain will not move or be considered for movement.
|
||||||
BulletSimAPI.ForceActivationState2(m_terrainBody.ptr, ActivationState.DISABLE_SIMULATION);
|
BulletSimAPI.ForceActivationState2(m_terrainBody.ptr, ActivationState.DISABLE_SIMULATION);
|
||||||
|
@ -140,7 +139,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
||||||
|
|
||||||
public override void Dispose()
|
public override void Dispose()
|
||||||
{
|
{
|
||||||
if (m_terrainBody.ptr != IntPtr.Zero)
|
if (m_terrainBody.HasPhysicalBody)
|
||||||
{
|
{
|
||||||
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr);
|
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr);
|
||||||
// Frees both the body and the shape.
|
// Frees both the body and the shape.
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Security;
|
using System.Security;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
@ -32,93 +33,6 @@ using OpenMetaverse;
|
||||||
|
|
||||||
namespace OpenSim.Region.Physics.BulletSPlugin {
|
namespace OpenSim.Region.Physics.BulletSPlugin {
|
||||||
|
|
||||||
// Classes to allow some type checking for the API
|
|
||||||
// These hold pointers to allocated objects in the unmanaged space.
|
|
||||||
|
|
||||||
// The physics engine controller class created at initialization
|
|
||||||
public struct BulletSim
|
|
||||||
{
|
|
||||||
public BulletSim(uint worldId, BSScene bss, IntPtr xx)
|
|
||||||
{
|
|
||||||
ptr = xx;
|
|
||||||
worldID = worldId;
|
|
||||||
physicsScene = bss;
|
|
||||||
}
|
|
||||||
public IntPtr ptr;
|
|
||||||
public uint worldID;
|
|
||||||
// The scene is only in here so very low level routines have a handle to print debug/error messages
|
|
||||||
public BSScene physicsScene;
|
|
||||||
}
|
|
||||||
|
|
||||||
// An allocated Bullet btRigidBody
|
|
||||||
public struct BulletBody
|
|
||||||
{
|
|
||||||
public BulletBody(uint id, IntPtr xx)
|
|
||||||
{
|
|
||||||
ID = id;
|
|
||||||
ptr = xx;
|
|
||||||
collisionGroup = 0;
|
|
||||||
collisionMask = 0;
|
|
||||||
}
|
|
||||||
public IntPtr ptr;
|
|
||||||
public uint ID;
|
|
||||||
public CollisionFilterGroups collisionGroup;
|
|
||||||
public CollisionFilterGroups collisionMask;
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
StringBuilder buff = new StringBuilder();
|
|
||||||
buff.Append("<id=");
|
|
||||||
buff.Append(ID.ToString());
|
|
||||||
buff.Append(",p=");
|
|
||||||
buff.Append(ptr.ToString("X"));
|
|
||||||
if (collisionGroup != 0 || collisionMask != 0)
|
|
||||||
{
|
|
||||||
buff.Append(",g=");
|
|
||||||
buff.Append(collisionGroup.ToString("X"));
|
|
||||||
buff.Append(",m=");
|
|
||||||
buff.Append(collisionMask.ToString("X"));
|
|
||||||
}
|
|
||||||
buff.Append(">");
|
|
||||||
return buff.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct BulletShape
|
|
||||||
{
|
|
||||||
public BulletShape(IntPtr xx)
|
|
||||||
{
|
|
||||||
ptr = xx;
|
|
||||||
type=BSPhysicsShapeType.SHAPE_UNKNOWN;
|
|
||||||
shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE;
|
|
||||||
isNativeShape = false;
|
|
||||||
}
|
|
||||||
public BulletShape(IntPtr xx, BSPhysicsShapeType typ)
|
|
||||||
{
|
|
||||||
ptr = xx;
|
|
||||||
type = typ;
|
|
||||||
shapeKey = 0;
|
|
||||||
isNativeShape = false;
|
|
||||||
}
|
|
||||||
public IntPtr ptr;
|
|
||||||
public BSPhysicsShapeType type;
|
|
||||||
public System.UInt64 shapeKey;
|
|
||||||
public bool isNativeShape;
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
StringBuilder buff = new StringBuilder();
|
|
||||||
buff.Append("<p=");
|
|
||||||
buff.Append(ptr.ToString("X"));
|
|
||||||
buff.Append(",s=");
|
|
||||||
buff.Append(type.ToString());
|
|
||||||
buff.Append(",k=");
|
|
||||||
buff.Append(shapeKey.ToString("X"));
|
|
||||||
buff.Append(",n=");
|
|
||||||
buff.Append(isNativeShape.ToString());
|
|
||||||
buff.Append(">");
|
|
||||||
return buff.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constraint type values as defined by Bullet
|
// Constraint type values as defined by Bullet
|
||||||
public enum ConstraintType : int
|
public enum ConstraintType : int
|
||||||
{
|
{
|
||||||
|
@ -132,44 +46,6 @@ public enum ConstraintType : int
|
||||||
MAX_CONSTRAINT_TYPE
|
MAX_CONSTRAINT_TYPE
|
||||||
}
|
}
|
||||||
|
|
||||||
// An allocated Bullet btConstraint
|
|
||||||
public struct BulletConstraint
|
|
||||||
{
|
|
||||||
public BulletConstraint(IntPtr xx)
|
|
||||||
{
|
|
||||||
ptr = xx;
|
|
||||||
}
|
|
||||||
public IntPtr ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// An allocated HeightMapThing which holds various heightmap info.
|
|
||||||
// Made a class rather than a struct so there would be only one
|
|
||||||
// instance of this and C# will pass around pointers rather
|
|
||||||
// than making copies.
|
|
||||||
public class BulletHeightMapInfo
|
|
||||||
{
|
|
||||||
public BulletHeightMapInfo(uint id, float[] hm, IntPtr xx) {
|
|
||||||
ID = id;
|
|
||||||
Ptr = xx;
|
|
||||||
heightMap = hm;
|
|
||||||
terrainRegionBase = Vector3.Zero;
|
|
||||||
minCoords = new Vector3(100f, 100f, 25f);
|
|
||||||
maxCoords = new Vector3(101f, 101f, 26f);
|
|
||||||
minZ = maxZ = 0f;
|
|
||||||
sizeX = sizeY = 256f;
|
|
||||||
}
|
|
||||||
public uint ID;
|
|
||||||
public IntPtr Ptr;
|
|
||||||
public float[] heightMap;
|
|
||||||
public Vector3 terrainRegionBase;
|
|
||||||
public Vector3 minCoords;
|
|
||||||
public Vector3 maxCoords;
|
|
||||||
public float sizeX, sizeY;
|
|
||||||
public float minZ, maxZ;
|
|
||||||
public BulletShape terrainShape;
|
|
||||||
public BulletBody terrainBody;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===============================================================================
|
// ===============================================================================
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct ConvexHull
|
public struct ConvexHull
|
||||||
|
@ -362,21 +238,15 @@ public enum CollisionFlags : uint
|
||||||
BS_FLOATS_ON_WATER = 1 << 11,
|
BS_FLOATS_ON_WATER = 1 << 11,
|
||||||
BS_VEHICLE_COLLISIONS = 1 << 12,
|
BS_VEHICLE_COLLISIONS = 1 << 12,
|
||||||
BS_NONE = 0,
|
BS_NONE = 0,
|
||||||
BS_ALL = 0xFFFFFFFF,
|
BS_ALL = 0xFFFFFFFF
|
||||||
|
|
||||||
// These are the collision flags switched depending on physical state.
|
|
||||||
// The other flags are used for other things and should not be fooled with.
|
|
||||||
BS_ACTIVE = CF_STATIC_OBJECT
|
|
||||||
| CF_KINEMATIC_OBJECT
|
|
||||||
| CF_NO_CONTACT_RESPONSE
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Values for collisions groups and masks
|
// Values f collisions groups and masks
|
||||||
public enum CollisionFilterGroups : uint
|
public enum CollisionFilterGroups : uint
|
||||||
{
|
{
|
||||||
// Don't use the bit definitions!! Define the use in a
|
// Don't use the bit definitions!! Define the use in a
|
||||||
// filter/mask definition below. This way collision interactions
|
// filter/mask definition below. This way collision interactions
|
||||||
// are more easily debugged.
|
// are more easily found and debugged.
|
||||||
BNoneGroup = 0,
|
BNoneGroup = 0,
|
||||||
BDefaultGroup = 1 << 0,
|
BDefaultGroup = 1 << 0,
|
||||||
BStaticGroup = 1 << 1,
|
BStaticGroup = 1 << 1,
|
||||||
|
@ -390,24 +260,8 @@ public enum CollisionFilterGroups : uint
|
||||||
BTerrainGroup = 1 << 11,
|
BTerrainGroup = 1 << 11,
|
||||||
BRaycastGroup = 1 << 12,
|
BRaycastGroup = 1 << 12,
|
||||||
BSolidGroup = 1 << 13,
|
BSolidGroup = 1 << 13,
|
||||||
BLinksetGroup = 1 << 14,
|
// BLinksetGroup = xx // a linkset proper is either static or dynamic
|
||||||
|
BLinksetChildGroup = 1 << 14,
|
||||||
// The collsion filters and masked are defined in one place -- don't want them scattered
|
|
||||||
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,
|
|
||||||
TerrainGroup = BTerrainGroup,
|
|
||||||
TerrainMask = BAllGroup & ~BStaticGroup, // static objects on the ground don't collide
|
|
||||||
GroundPlaneGroup = BGroundPlaneGroup,
|
|
||||||
GroundPlaneMask = BAllGroup
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0
|
// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0
|
||||||
|
@ -434,7 +288,7 @@ public enum ConstraintParamAxis : int
|
||||||
|
|
||||||
// ===============================================================================
|
// ===============================================================================
|
||||||
static class BulletSimAPI {
|
static class BulletSimAPI {
|
||||||
|
// ===============================================================================
|
||||||
// Link back to the managed code for outputting log messages
|
// Link back to the managed code for outputting log messages
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
|
public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
|
||||||
|
|
|
@ -0,0 +1,278 @@
|
||||||
|
/*
|
||||||
|
* 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 copyrightD
|
||||||
|
* 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;
|
||||||
|
using OMV = OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
|
{
|
||||||
|
// Classes to allow some type checking for the API
|
||||||
|
// These hold pointers to allocated objects in the unmanaged space.
|
||||||
|
|
||||||
|
// The physics engine controller class created at initialization
|
||||||
|
public struct BulletSim
|
||||||
|
{
|
||||||
|
public BulletSim(uint worldId, BSScene bss, IntPtr xx)
|
||||||
|
{
|
||||||
|
ptr = xx;
|
||||||
|
worldID = worldId;
|
||||||
|
physicsScene = bss;
|
||||||
|
}
|
||||||
|
public IntPtr ptr;
|
||||||
|
public uint worldID;
|
||||||
|
// The scene is only in here so very low level routines have a handle to print debug/error messages
|
||||||
|
public BSScene physicsScene;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An allocated Bullet btRigidBody
|
||||||
|
public struct BulletBody
|
||||||
|
{
|
||||||
|
public BulletBody(uint id) : this(id, IntPtr.Zero)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public BulletBody(uint id, IntPtr xx)
|
||||||
|
{
|
||||||
|
ID = id;
|
||||||
|
ptr = xx;
|
||||||
|
collisionType = CollisionType.Static;
|
||||||
|
}
|
||||||
|
public IntPtr ptr;
|
||||||
|
public uint ID;
|
||||||
|
public CollisionType collisionType;
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
ptr = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
public bool HasPhysicalBody { get { return ptr != IntPtr.Zero; } }
|
||||||
|
|
||||||
|
// Apply the specificed collision mask into the physical world
|
||||||
|
public void ApplyCollisionMask()
|
||||||
|
{
|
||||||
|
// Should assert the body has been added to the physical world.
|
||||||
|
// (The collision masks are stored in the collision proxy cache which only exists for
|
||||||
|
// a collision body that is in the world.)
|
||||||
|
BulletSimAPI.SetCollisionGroupMask2(ptr,
|
||||||
|
BulletSimData.CollisionTypeMasks[collisionType].group,
|
||||||
|
BulletSimData.CollisionTypeMasks[collisionType].mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
StringBuilder buff = new StringBuilder();
|
||||||
|
buff.Append("<id=");
|
||||||
|
buff.Append(ID.ToString());
|
||||||
|
buff.Append(",p=");
|
||||||
|
buff.Append(ptr.ToString("X"));
|
||||||
|
buff.Append(",c=");
|
||||||
|
buff.Append(collisionType);
|
||||||
|
buff.Append(">");
|
||||||
|
return buff.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct BulletShape
|
||||||
|
{
|
||||||
|
public BulletShape(IntPtr xx) : this(xx, BSPhysicsShapeType.SHAPE_UNKNOWN)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public BulletShape(IntPtr xx, BSPhysicsShapeType typ)
|
||||||
|
{
|
||||||
|
ptr = xx;
|
||||||
|
type = typ;
|
||||||
|
shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE;
|
||||||
|
isNativeShape = false;
|
||||||
|
}
|
||||||
|
public IntPtr ptr;
|
||||||
|
public BSPhysicsShapeType type;
|
||||||
|
public System.UInt64 shapeKey;
|
||||||
|
public bool isNativeShape;
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
ptr = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
public bool HasPhysicalShape { get { return ptr != IntPtr.Zero; } }
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
StringBuilder buff = new StringBuilder();
|
||||||
|
buff.Append("<p=");
|
||||||
|
buff.Append(ptr.ToString("X"));
|
||||||
|
buff.Append(",s=");
|
||||||
|
buff.Append(type.ToString());
|
||||||
|
buff.Append(",k=");
|
||||||
|
buff.Append(shapeKey.ToString("X"));
|
||||||
|
buff.Append(",n=");
|
||||||
|
buff.Append(isNativeShape.ToString());
|
||||||
|
buff.Append(">");
|
||||||
|
return buff.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// An allocated Bullet btConstraint
|
||||||
|
public struct BulletConstraint
|
||||||
|
{
|
||||||
|
public BulletConstraint(IntPtr xx)
|
||||||
|
{
|
||||||
|
ptr = xx;
|
||||||
|
}
|
||||||
|
public IntPtr ptr;
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
ptr = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
public bool HasPhysicalConstraint { get { return ptr != IntPtr.Zero; } }
|
||||||
|
}
|
||||||
|
|
||||||
|
// An allocated HeightMapThing which holds various heightmap info.
|
||||||
|
// Made a class rather than a struct so there would be only one
|
||||||
|
// instance of this and C# will pass around pointers rather
|
||||||
|
// than making copies.
|
||||||
|
public class BulletHeightMapInfo
|
||||||
|
{
|
||||||
|
public BulletHeightMapInfo(uint id, float[] hm, IntPtr xx) {
|
||||||
|
ID = id;
|
||||||
|
Ptr = xx;
|
||||||
|
heightMap = hm;
|
||||||
|
terrainRegionBase = OMV.Vector3.Zero;
|
||||||
|
minCoords = new OMV.Vector3(100f, 100f, 25f);
|
||||||
|
maxCoords = new OMV.Vector3(101f, 101f, 26f);
|
||||||
|
minZ = maxZ = 0f;
|
||||||
|
sizeX = sizeY = 256f;
|
||||||
|
}
|
||||||
|
public uint ID;
|
||||||
|
public IntPtr Ptr;
|
||||||
|
public float[] heightMap;
|
||||||
|
public OMV.Vector3 terrainRegionBase;
|
||||||
|
public OMV.Vector3 minCoords;
|
||||||
|
public OMV.Vector3 maxCoords;
|
||||||
|
public float sizeX, sizeY;
|
||||||
|
public float minZ, maxZ;
|
||||||
|
public BulletShape terrainShape;
|
||||||
|
public BulletBody terrainBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The general class of collsion object.
|
||||||
|
public enum CollisionType
|
||||||
|
{
|
||||||
|
Avatar,
|
||||||
|
Groundplane,
|
||||||
|
Terrain,
|
||||||
|
Static,
|
||||||
|
Dynamic,
|
||||||
|
VolumeDetect,
|
||||||
|
// Linkset, // A linkset should be either Static or Dynamic
|
||||||
|
LinksetChild,
|
||||||
|
Unknown
|
||||||
|
};
|
||||||
|
|
||||||
|
// Hold specification of group and mask collision flags for a CollisionType
|
||||||
|
public struct CollisionTypeFilterGroup
|
||||||
|
{
|
||||||
|
public CollisionTypeFilterGroup(CollisionType t, uint g, uint m)
|
||||||
|
{
|
||||||
|
type = t;
|
||||||
|
group = g;
|
||||||
|
mask = m;
|
||||||
|
}
|
||||||
|
public CollisionType type;
|
||||||
|
public uint group;
|
||||||
|
public uint mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* NOTE: old definitions kept for reference. Delete when things are working.
|
||||||
|
// The collsion filters and masked are defined in one place -- don't want them scattered
|
||||||
|
AvatarGroup = BCharacterGroup,
|
||||||
|
AvatarMask = BAllGroup,
|
||||||
|
ObjectGroup = BSolidGroup,
|
||||||
|
ObjectMask = BAllGroup,
|
||||||
|
StaticObjectGroup = BStaticGroup,
|
||||||
|
StaticObjectMask = AvatarGroup | ObjectGroup, // static things don't interact with much
|
||||||
|
LinksetGroup = BLinksetGroup,
|
||||||
|
LinksetMask = BAllGroup,
|
||||||
|
LinksetChildGroup = BLinksetChildGroup,
|
||||||
|
LinksetChildMask = BNoneGroup, // Linkset children disappear from the world
|
||||||
|
VolumeDetectGroup = BSensorTrigger,
|
||||||
|
VolumeDetectMask = ~BSensorTrigger,
|
||||||
|
TerrainGroup = BTerrainGroup,
|
||||||
|
TerrainMask = BAllGroup & ~BStaticGroup, // static objects on the ground don't collide
|
||||||
|
GroundPlaneGroup = BGroundPlaneGroup,
|
||||||
|
GroundPlaneMask = BAllGroup
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static class BulletSimData
|
||||||
|
{
|
||||||
|
|
||||||
|
// Map of collisionTypes to flags for collision groups and masks.
|
||||||
|
// As mentioned above, don't use the CollisionFilterGroups definitions directly in the code
|
||||||
|
// but, instead, use references to this dictionary. Finding and debugging
|
||||||
|
// collision flag problems will be made easier.
|
||||||
|
public static Dictionary<CollisionType, CollisionTypeFilterGroup> CollisionTypeMasks
|
||||||
|
= new Dictionary<CollisionType, CollisionTypeFilterGroup>()
|
||||||
|
{
|
||||||
|
{ CollisionType.Avatar,
|
||||||
|
new CollisionTypeFilterGroup(CollisionType.Avatar,
|
||||||
|
(uint)CollisionFilterGroups.BCharacterGroup,
|
||||||
|
(uint)CollisionFilterGroups.BAllGroup)
|
||||||
|
},
|
||||||
|
{ CollisionType.Groundplane,
|
||||||
|
new CollisionTypeFilterGroup(CollisionType.Groundplane,
|
||||||
|
(uint)CollisionFilterGroups.BGroundPlaneGroup,
|
||||||
|
(uint)CollisionFilterGroups.BAllGroup)
|
||||||
|
},
|
||||||
|
{ CollisionType.Terrain,
|
||||||
|
new CollisionTypeFilterGroup(CollisionType.Terrain,
|
||||||
|
(uint)CollisionFilterGroups.BTerrainGroup,
|
||||||
|
(uint)(CollisionFilterGroups.BAllGroup & ~CollisionFilterGroups.BStaticGroup))
|
||||||
|
},
|
||||||
|
{ CollisionType.Static,
|
||||||
|
new CollisionTypeFilterGroup(CollisionType.Static,
|
||||||
|
(uint)CollisionFilterGroups.BStaticGroup,
|
||||||
|
(uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup))
|
||||||
|
},
|
||||||
|
{ CollisionType.Dynamic,
|
||||||
|
new CollisionTypeFilterGroup(CollisionType.Dynamic,
|
||||||
|
(uint)CollisionFilterGroups.BSolidGroup,
|
||||||
|
(uint)(CollisionFilterGroups.BAllGroup))
|
||||||
|
},
|
||||||
|
{ CollisionType.VolumeDetect,
|
||||||
|
new CollisionTypeFilterGroup(CollisionType.VolumeDetect,
|
||||||
|
(uint)CollisionFilterGroups.BSensorTrigger,
|
||||||
|
(uint)(~CollisionFilterGroups.BSensorTrigger))
|
||||||
|
},
|
||||||
|
{ CollisionType.LinksetChild,
|
||||||
|
new CollisionTypeFilterGroup(CollisionType.LinksetChild,
|
||||||
|
(uint)CollisionFilterGroups.BTerrainGroup,
|
||||||
|
(uint)(CollisionFilterGroups.BNoneGroup))
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,13 +11,20 @@ CRASHES
|
||||||
|
|
||||||
VEHICLES TODO LIST:
|
VEHICLES TODO LIST:
|
||||||
=================================================
|
=================================================
|
||||||
Neb car jiggling left and right
|
Neb vehicle taking > 25ms of physics time!!
|
||||||
Happens on terrain and any other mesh object. Flat cubes are much smoother.
|
|
||||||
Vehicles (Move smoothly)
|
Vehicles (Move smoothly)
|
||||||
Add vehicle collisions so IsColliding is properly reported.
|
Add vehicle collisions so IsColliding is properly reported.
|
||||||
Needed for banking, limitMotorUp, movementLimiting, ...
|
Needed for banking, limitMotorUp, movementLimiting, ...
|
||||||
Some vehicles should not be able to turn if no speed or off ground.
|
Some vehicles should not be able to turn if no speed or off ground.
|
||||||
|
Neb car jiggling left and right
|
||||||
|
Happens on terrain and any other mesh object. Flat cubes are much smoother.
|
||||||
|
This has been reduced but not eliminated.
|
||||||
|
Light cycle falling over when driving
|
||||||
For limitMotorUp, use raycast down to find if vehicle is in the air.
|
For limitMotorUp, use raycast down to find if vehicle is in the air.
|
||||||
|
Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE.
|
||||||
|
Verify that angular motion specified around Z moves in the vehicle coordinates.
|
||||||
|
Verify llGetVel() is returning a smooth and good value for vehicle movement.
|
||||||
|
llGetVel() should return the root's velocity if requested in a child prim.
|
||||||
Implement function efficiency for lineaar and angular motion.
|
Implement function efficiency for lineaar and angular motion.
|
||||||
Should vehicle angular/linear movement friction happen after all the components
|
Should vehicle angular/linear movement friction happen after all the components
|
||||||
or does it only apply to the basic movement?
|
or does it only apply to the basic movement?
|
||||||
|
@ -30,15 +37,14 @@ Border crossing with linked vehicle causes crash
|
||||||
|
|
||||||
BULLETSIM TODO LIST:
|
BULLETSIM TODO LIST:
|
||||||
=================================================
|
=================================================
|
||||||
|
Avatar height off after unsitting (floats off ground)
|
||||||
|
Editting appearance then moving restores.
|
||||||
|
Must not be initializing height when recreating capsule after unsit.
|
||||||
Duplicating a physical prim causes old prim to jump away
|
Duplicating a physical prim causes old prim to jump away
|
||||||
Dup a phys prim and the original become unselected and thus interacts w/ selected prim.
|
Dup a phys prim and the original become unselected and thus interacts w/ selected prim.
|
||||||
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.
|
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
|
BSPrim.Force should set a continious force on the prim. The force should be
|
||||||
applied each tick. Some limits?
|
applied each tick. Some limits?
|
||||||
Single prim vehicles don't seem to properly vehiclize.
|
|
||||||
Gun sending shooter flying.
|
Gun sending shooter flying.
|
||||||
Collision margin (gap between physical objects lying on each other)
|
Collision margin (gap between physical objects lying on each other)
|
||||||
Boundry checking (crashes related to crossing boundry)
|
Boundry checking (crashes related to crossing boundry)
|
||||||
|
@ -51,14 +57,34 @@ Small physical objects do not interact correctly
|
||||||
The chain will fall apart and pairs will dance around on ground
|
The chain will fall apart and pairs will dance around on ground
|
||||||
Chains of 1x1x.2 will stay connected but will dance.
|
Chains of 1x1x.2 will stay connected but will dance.
|
||||||
Chains above 2x2x.4 are move stable and get stablier as torui get larger.
|
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, ...)
|
Add PID motor for avatar movement (slow to stop, ...)
|
||||||
setForce should set a constant force. Different than AddImpulse.
|
setForce should set a constant force. Different than AddImpulse.
|
||||||
Implement raycast.
|
Implement raycast.
|
||||||
Implement ShapeCollection.Dispose()
|
Implement ShapeCollection.Dispose()
|
||||||
Implement water as a plain so raycasting and collisions can happen with same.
|
Implement water as a plain so raycasting and collisions can happen with same.
|
||||||
|
Add osGetPhysicsEngineName() so scripters can tell whether BulletSim or ODE
|
||||||
|
Also osGetPhysicsEngineVerion() maybe.
|
||||||
|
|
||||||
|
LINKSETS
|
||||||
|
======================================================
|
||||||
|
Linksets should allow collisions to individual children
|
||||||
|
Add LocalID to children shapes in LinksetCompound and create events for individuals
|
||||||
|
Verify/think through scripts in children of linksets. What do they reference
|
||||||
|
and return when getting position, velocity, ...
|
||||||
|
Confirm constraint linksets still work after making all the changes for compound linksets.
|
||||||
|
Add 'changed' flag or similar to reduce the number of times a linkset is rebuilt.
|
||||||
|
For compound linksets, add ability to remove or reposition individual child shapes.
|
||||||
|
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, ...
|
||||||
|
Speed up creation of large physical linksets
|
||||||
|
For instance, sitting in Neb's car (130 prims) takes several seconds to become physical
|
||||||
|
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?
|
||||||
|
|
||||||
|
MORE
|
||||||
|
======================================================
|
||||||
Find/remove avatar collision with ID=0.
|
Find/remove avatar collision with ID=0.
|
||||||
Test avatar walking up stairs. How does compare with SL.
|
Test avatar walking up stairs. How does compare with SL.
|
||||||
Radius of the capsule affects ability to climb edges.
|
Radius of the capsule affects ability to climb edges.
|
||||||
|
@ -67,8 +93,6 @@ Debounce avatar contact so legs don't keep folding up when standing.
|
||||||
Implement LSL physics controls. Like STATUS_ROTATE_X.
|
Implement LSL physics controls. Like STATUS_ROTATE_X.
|
||||||
Add border extensions to terrain to help region crossings and objects leaving region.
|
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?
|
Performance test with lots of avatars. Can BulletSim support a thousand?
|
||||||
Optimize collisions in C++: only send up to the object subscribed to collisions.
|
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)
|
Use collision subscription and remove the collsion(A,B) and collision(B,A)
|
||||||
|
@ -79,10 +103,6 @@ Avatar jump
|
||||||
Performance measurement and changes to make quicker.
|
Performance measurement and changes to make quicker.
|
||||||
Implement detailed physics stats (GetStats()).
|
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
|
Measure performance improvement from hulls
|
||||||
Test not using ghost objects for volume detect implementation.
|
Test not using ghost objects for volume detect implementation.
|
||||||
Performance of closures and delegates for taint processing
|
Performance of closures and delegates for taint processing
|
||||||
|
@ -95,10 +115,16 @@ Physics Arena central pyramid: why is one side permiable?
|
||||||
|
|
||||||
INTERNAL IMPROVEMENT/CLEANUP
|
INTERNAL IMPROVEMENT/CLEANUP
|
||||||
=================================================
|
=================================================
|
||||||
|
Consider moving prim/character body and shape destruction in destroy()
|
||||||
|
to postTimeTime rather than protecting all the potential sets that
|
||||||
|
might have been queued up.
|
||||||
Remove unused fields from ShapeData (not used in API2)
|
Remove unused fields from ShapeData (not used in API2)
|
||||||
Breakout code for mesh/hull/compound/native into separate BSShape* classes
|
Breakout code for mesh/hull/compound/native into separate BSShape* classes
|
||||||
Standardize access to building and reference code.
|
Standardize access to building and reference code.
|
||||||
The skeleton classes are in the sources but are not complete or linked in.
|
The skeleton classes are in the sources but are not complete or linked in.
|
||||||
|
Make BSBody and BSShape real classes to centralize creation/changin/destruction
|
||||||
|
Convert state and parameter calls from BulletSimAPI direct calls to
|
||||||
|
calls on BSBody and BSShape
|
||||||
Generalize Dynamics and PID with standardized motors.
|
Generalize Dynamics and PID with standardized motors.
|
||||||
Generalize Linkset and vehicles into PropertyManagers
|
Generalize Linkset and vehicles into PropertyManagers
|
||||||
Methods for Refresh, RemoveBodyDependencies, RestoreBodyDependencies
|
Methods for Refresh, RemoveBodyDependencies, RestoreBodyDependencies
|
||||||
|
@ -110,7 +136,7 @@ Implement linkset by setting position of children when root updated. (LinksetMan
|
||||||
Linkset implementation using manual prim movement.
|
Linkset implementation using manual prim movement.
|
||||||
LinkablePrim class? Would that simplify/centralize the linkset logic?
|
LinkablePrim class? Would that simplify/centralize the linkset logic?
|
||||||
BSScene.UpdateParameterSet() is broken. How to set params on objects?
|
BSScene.UpdateParameterSet() is broken. How to set params on objects?
|
||||||
Remove HeightmapInfo from terrain specification.
|
Remove HeightmapInfo from terrain specification
|
||||||
Since C++ code does not need terrain height, this structure et al are not needed.
|
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
|
Add floating motor for BS_FLOATS_ON_WATER so prim and avatar will
|
||||||
bob at the water level. BSPrim.PositionSanityCheck().
|
bob at the water level. BSPrim.PositionSanityCheck().
|
||||||
|
@ -142,7 +168,11 @@ Do prim hash codes work for sculpties and meshes? (Resolution: yes)
|
||||||
Linkset implementation using compound shapes. (Resolution: implemented LinksetCompound)
|
Linkset implementation using compound shapes. (Resolution: implemented LinksetCompound)
|
||||||
Compound shapes will need the LocalID in the shapes and collision
|
Compound shapes will need the LocalID in the shapes and collision
|
||||||
processing to get it from there.
|
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.)
|
Light cycle not banking (Resolution: It doesn't. Banking is roll adding yaw.)
|
||||||
Package Bullet source mods for Bullet internal stats output
|
Package Bullet source mods for Bullet internal stats output
|
||||||
(Resolution: move code into WorldData.h rather than relying on patches)
|
(Resolution: move code into WorldData.h rather than relying on patches)
|
||||||
|
Single prim vehicles don't seem to properly vehiclize.
|
||||||
|
(Resolution: mass was not getting set properly for single prim linksets)
|
||||||
|
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.
|
||||||
|
(Resolution:
|
||||||
|
|
|
@ -333,17 +333,20 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Velocity of this actor.
|
/// The desired velocity of this actor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Setting this provides a target velocity for physics scene updates.
|
/// Setting this provides a target velocity for physics scene updates.
|
||||||
/// Getting this returns the velocity calculated by physics scene updates, using factors such as target velocity,
|
/// Getting this returns the last set target. Fetch Velocity to get the current velocity.
|
||||||
/// time to accelerate and collisions.
|
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
protected Vector3 m_targetVelocity;
|
||||||
public virtual Vector3 TargetVelocity
|
public virtual Vector3 TargetVelocity
|
||||||
{
|
{
|
||||||
get { return Velocity; }
|
get { return m_targetVelocity; }
|
||||||
set { Velocity = value; }
|
set {
|
||||||
|
m_targetVelocity = value;
|
||||||
|
Velocity = m_targetVelocity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract Vector3 Velocity { get; set; }
|
public abstract Vector3 Velocity { get; set; }
|
||||||
|
|
|
@ -58,6 +58,18 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IScriptInstance
|
public interface IScriptInstance
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Debug level for this script instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Level == 0, no extra data is logged.
|
||||||
|
/// Level >= 1, state changes are logged.
|
||||||
|
/// Level >= 2, event firing is logged.
|
||||||
|
/// <value>
|
||||||
|
/// The debug level.
|
||||||
|
/// </value>
|
||||||
|
int DebugLevel { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is the script currently running?
|
/// Is the script currently running?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -94,6 +94,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||||
private UUID m_CurrentStateHash;
|
private UUID m_CurrentStateHash;
|
||||||
private UUID m_RegionID;
|
private UUID m_RegionID;
|
||||||
|
|
||||||
|
public int DebugLevel { get; set; }
|
||||||
|
|
||||||
public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> LineMap { get; set; }
|
public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> LineMap { get; set; }
|
||||||
|
|
||||||
private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>();
|
private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>();
|
||||||
|
@ -549,9 +551,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||||
// forcibly abort the work item (this aborts the underlying thread).
|
// forcibly abort the work item (this aborts the underlying thread).
|
||||||
if (!m_InSelfDelete)
|
if (!m_InSelfDelete)
|
||||||
{
|
{
|
||||||
// m_log.ErrorFormat(
|
m_log.DebugFormat(
|
||||||
// "[SCRIPT INSTANCE]: Aborting script {0} {1} in prim {2} {3} {4} {5}",
|
"[SCRIPT INSTANCE]: Aborting unstopped script {0} {1} in prim {2}, localID {3}, timeout was {4} ms",
|
||||||
// ScriptName, ItemID, PrimName, ObjectID, m_InSelfDelete, DateTime.Now.Ticks);
|
ScriptName, ItemID, PrimName, LocalID, timeout);
|
||||||
|
|
||||||
workItem.Abort();
|
workItem.Abort();
|
||||||
}
|
}
|
||||||
|
@ -707,19 +709,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||||
{
|
{
|
||||||
|
|
||||||
// m_log.DebugFormat("[XEngine]: Processing event {0} for {1}", data.EventName, this);
|
// m_log.DebugFormat("[XEngine]: Processing event {0} for {1}", data.EventName, this);
|
||||||
|
SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID);
|
||||||
|
|
||||||
|
if (DebugLevel >= 2)
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[SCRIPT INSTANCE]: Processing event {0} for {1}/{2}({3})/{4}({5}) @ {6}/{7}",
|
||||||
|
data.EventName,
|
||||||
|
ScriptName,
|
||||||
|
part.Name,
|
||||||
|
part.LocalId,
|
||||||
|
part.ParentGroup.Name,
|
||||||
|
part.ParentGroup.UUID,
|
||||||
|
part.AbsolutePosition,
|
||||||
|
part.ParentGroup.Scene.Name);
|
||||||
|
|
||||||
m_DetectParams = data.DetectParams;
|
m_DetectParams = data.DetectParams;
|
||||||
|
|
||||||
if (data.EventName == "state") // Hardcoded state change
|
if (data.EventName == "state") // Hardcoded state change
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[Script] Script {0}.{1} state set to {2}",
|
|
||||||
// PrimName, ScriptName, data.Params[0].ToString());
|
|
||||||
State = data.Params[0].ToString();
|
State = data.Params[0].ToString();
|
||||||
|
|
||||||
|
if (DebugLevel >= 1)
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[SCRIPT INSTANCE]: Changing state to {0} for {1}/{2}({3})/{4}({5}) @ {6}/{7}",
|
||||||
|
State,
|
||||||
|
ScriptName,
|
||||||
|
part.Name,
|
||||||
|
part.LocalId,
|
||||||
|
part.ParentGroup.Name,
|
||||||
|
part.ParentGroup.UUID,
|
||||||
|
part.AbsolutePosition,
|
||||||
|
part.ParentGroup.Scene.Name);
|
||||||
|
|
||||||
AsyncCommandManager.RemoveScript(Engine,
|
AsyncCommandManager.RemoveScript(Engine,
|
||||||
LocalID, ItemID);
|
LocalID, ItemID);
|
||||||
|
|
||||||
SceneObjectPart part = Engine.World.GetSceneObjectPart(
|
|
||||||
LocalID);
|
|
||||||
if (part != null)
|
if (part != null)
|
||||||
{
|
{
|
||||||
part.SetScriptEvents(ItemID,
|
part.SetScriptEvents(ItemID,
|
||||||
|
@ -731,8 +755,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||||
if (Engine.World.PipeEventsForScript(LocalID) ||
|
if (Engine.World.PipeEventsForScript(LocalID) ||
|
||||||
data.EventName == "control") // Don't freeze avies!
|
data.EventName == "control") // Don't freeze avies!
|
||||||
{
|
{
|
||||||
SceneObjectPart part = Engine.World.GetSceneObjectPart(
|
|
||||||
LocalID);
|
|
||||||
// m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}",
|
// m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}",
|
||||||
// PrimName, ScriptName, data.EventName, State);
|
// PrimName, ScriptName, data.EventName, State);
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,24 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
private IXmlRpcRouter m_XmlRpcRouter;
|
private IXmlRpcRouter m_XmlRpcRouter;
|
||||||
private int m_EventLimit;
|
private int m_EventLimit;
|
||||||
private bool m_KillTimedOutScripts;
|
private bool m_KillTimedOutScripts;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of milliseconds we will wait for a script event to complete on script stop before we forcibly abort
|
||||||
|
/// its thread.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// It appears that if a script thread is aborted whilst it is holding ReaderWriterLockSlim (possibly the write
|
||||||
|
/// lock) then the lock is not properly released. This causes mono 2.6, 2.10 and possibly
|
||||||
|
/// later to crash, sometimes with symptoms such as a leap to 100% script usage and a vm thead dump showing
|
||||||
|
/// all threads waiting on release of ReaderWriterLockSlim write thread which none of the threads listed
|
||||||
|
/// actually hold.
|
||||||
|
///
|
||||||
|
/// Pausing for event completion reduces the risk of this happening. However, it may be that aborting threads
|
||||||
|
/// is not a mono issue per se but rather a risky activity in itself in an AppDomain that is not immediately
|
||||||
|
/// shutting down.
|
||||||
|
/// </remarks>
|
||||||
|
private int m_WaitForEventCompletionOnScriptStop = 1000;
|
||||||
|
|
||||||
private string m_ScriptEnginesPath = null;
|
private string m_ScriptEnginesPath = null;
|
||||||
|
|
||||||
private ExpiringCache<UUID, bool> m_runFlags = new ExpiringCache<UUID, bool>();
|
private ExpiringCache<UUID, bool> m_runFlags = new ExpiringCache<UUID, bool>();
|
||||||
|
@ -317,6 +335,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30);
|
m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30);
|
||||||
m_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false);
|
m_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false);
|
||||||
m_SaveTime = m_ScriptConfig.GetInt("SaveInterval", 120) * 1000;
|
m_SaveTime = m_ScriptConfig.GetInt("SaveInterval", 120) * 1000;
|
||||||
|
m_WaitForEventCompletionOnScriptStop
|
||||||
|
= m_ScriptConfig.GetInt("WaitForEventCompletionOnScriptStop", m_WaitForEventCompletionOnScriptStop);
|
||||||
|
|
||||||
m_ScriptEnginesPath = m_ScriptConfig.GetString("ScriptEnginesPath", "ScriptEngines");
|
m_ScriptEnginesPath = m_ScriptConfig.GetString("ScriptEnginesPath", "ScriptEngines");
|
||||||
|
|
||||||
m_Prio = ThreadPriority.BelowNormal;
|
m_Prio = ThreadPriority.BelowNormal;
|
||||||
|
@ -372,7 +393,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
|
|
||||||
MainConsole.Instance.Commands.AddCommand(
|
MainConsole.Instance.Commands.AddCommand(
|
||||||
"Scripts", false, "scripts show", "scripts show [<script-item-uuid>]", "Show script information",
|
"Scripts", false, "scripts show", "scripts show [<script-item-uuid>]", "Show script information",
|
||||||
"Show information on all scripts known to the script engine."
|
"Show information on all scripts known to the script engine.\n"
|
||||||
+ "If a <script-item-uuid> is given then only information on that script will be shown.",
|
+ "If a <script-item-uuid> is given then only information on that script will be shown.",
|
||||||
HandleShowScripts);
|
HandleShowScripts);
|
||||||
|
|
||||||
|
@ -391,22 +412,30 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
MainConsole.Instance.Commands.AddCommand(
|
MainConsole.Instance.Commands.AddCommand(
|
||||||
"Scripts", false, "scripts resume", "scripts resume [<script-item-uuid>]", "Resumes all suspended scripts",
|
"Scripts", false, "scripts resume", "scripts resume [<script-item-uuid>]", "Resumes all suspended scripts",
|
||||||
"Resumes all currently suspended scripts.\n"
|
"Resumes all currently suspended scripts.\n"
|
||||||
+ "Resumed scripts will process all events accumulated whilst suspended."
|
+ "Resumed scripts will process all events accumulated whilst suspended.\n"
|
||||||
+ "If a <script-item-uuid> is given then only that script will be resumed. Otherwise, all suitable scripts are resumed.",
|
+ "If a <script-item-uuid> is given then only that script will be resumed. Otherwise, all suitable scripts are resumed.",
|
||||||
(module, cmdparams) => HandleScriptsAction(cmdparams, HandleResumeScript));
|
(module, cmdparams) => HandleScriptsAction(cmdparams, HandleResumeScript));
|
||||||
|
|
||||||
MainConsole.Instance.Commands.AddCommand(
|
MainConsole.Instance.Commands.AddCommand(
|
||||||
"Scripts", false, "scripts stop", "scripts stop [<script-item-uuid>]", "Stops all running scripts",
|
"Scripts", false, "scripts stop", "scripts stop [<script-item-uuid>]", "Stops all running scripts",
|
||||||
"Stops all running scripts."
|
"Stops all running scripts.\n"
|
||||||
+ "If a <script-item-uuid> is given then only that script will be stopped. Otherwise, all suitable scripts are stopped.",
|
+ "If a <script-item-uuid> is given then only that script will be stopped. Otherwise, all suitable scripts are stopped.",
|
||||||
(module, cmdparams) => HandleScriptsAction(cmdparams, HandleStopScript));
|
(module, cmdparams) => HandleScriptsAction(cmdparams, HandleStopScript));
|
||||||
|
|
||||||
MainConsole.Instance.Commands.AddCommand(
|
MainConsole.Instance.Commands.AddCommand(
|
||||||
"Scripts", false, "scripts start", "scripts start [<script-item-uuid>]", "Starts all stopped scripts",
|
"Scripts", false, "scripts start", "scripts start [<script-item-uuid>]", "Starts all stopped scripts",
|
||||||
"Starts all stopped scripts."
|
"Starts all stopped scripts.\n"
|
||||||
+ "If a <script-item-uuid> is given then only that script will be started. Otherwise, all suitable scripts are started.",
|
+ "If a <script-item-uuid> is given then only that script will be started. Otherwise, all suitable scripts are started.",
|
||||||
(module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript));
|
(module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript));
|
||||||
|
|
||||||
|
MainConsole.Instance.Commands.AddCommand(
|
||||||
|
"Scripts", false, "debug script log", "debug scripts log <item-id> <log-level>", "Extra debug logging for a script",
|
||||||
|
"Activates or deactivates extra debug logging for the given script.\n"
|
||||||
|
+ "Level == 0, deactivate extra debug logging.\n"
|
||||||
|
+ "Level >= 1, log state changes.\n"
|
||||||
|
+ "Level >= 2, log event invocations.\n",
|
||||||
|
HandleDebugScriptLogCommand);
|
||||||
|
|
||||||
// MainConsole.Instance.Commands.AddCommand(
|
// MainConsole.Instance.Commands.AddCommand(
|
||||||
// "Debug", false, "debug xengine", "debug xengine [<level>]",
|
// "Debug", false, "debug xengine", "debug xengine [<level>]",
|
||||||
// "Turn on detailed xengine debugging.",
|
// "Turn on detailed xengine debugging.",
|
||||||
|
@ -415,6 +444,41 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
// HandleDebugLevelCommand);
|
// HandleDebugLevelCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HandleDebugScriptLogCommand(string module, string[] args)
|
||||||
|
{
|
||||||
|
if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (args.Length != 5)
|
||||||
|
{
|
||||||
|
MainConsole.Instance.Output("Usage: debug script log <item-id> <log-level>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UUID itemId;
|
||||||
|
|
||||||
|
if (!ConsoleUtil.TryParseConsoleUuid(MainConsole.Instance, args[3], out itemId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
int newLevel;
|
||||||
|
|
||||||
|
if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[4], out newLevel))
|
||||||
|
return;
|
||||||
|
|
||||||
|
IScriptInstance si;
|
||||||
|
|
||||||
|
lock (m_Scripts)
|
||||||
|
{
|
||||||
|
// XXX: We can't give the user feedback on a bad item id because this may apply to a different script
|
||||||
|
// engine
|
||||||
|
if (!m_Scripts.TryGetValue(itemId, out si))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
si.DebugLevel = newLevel;
|
||||||
|
MainConsole.Instance.OutputFormat("Set debug level of {0} {1} to {2}", si.ScriptName, si.ItemID, newLevel);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Change debug level
|
/// Change debug level
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -486,7 +550,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
|
|
||||||
if (!UUID.TryParse(rawItemId, out itemId))
|
if (!UUID.TryParse(rawItemId, out itemId))
|
||||||
{
|
{
|
||||||
MainConsole.Instance.OutputFormat("Error - {0} is not a valid UUID", rawItemId);
|
MainConsole.Instance.OutputFormat("ERROR: {0} is not a valid UUID", rawItemId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -610,6 +674,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
sb.AppendFormat("Queued events : {0}\n", instance.EventsQueued);
|
sb.AppendFormat("Queued events : {0}\n", instance.EventsQueued);
|
||||||
sb.AppendFormat("Processed events : {0}\n", instance.EventsProcessed);
|
sb.AppendFormat("Processed events : {0}\n", instance.EventsProcessed);
|
||||||
sb.AppendFormat("Item UUID : {0}\n", instance.ItemID);
|
sb.AppendFormat("Item UUID : {0}\n", instance.ItemID);
|
||||||
|
sb.AppendFormat("Asset UUID : {0}\n", instance.AssetID);
|
||||||
sb.AppendFormat("Containing part name: {0}\n", instance.PrimName);
|
sb.AppendFormat("Containing part name: {0}\n", instance.PrimName);
|
||||||
sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID);
|
sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID);
|
||||||
sb.AppendFormat("Position : {0}\n", sop.AbsolutePosition);
|
sb.AppendFormat("Position : {0}\n", sop.AbsolutePosition);
|
||||||
|
@ -1375,9 +1440,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
lockScriptsForWrite(false);
|
lockScriptsForWrite(false);
|
||||||
instance.ClearQueue();
|
instance.ClearQueue();
|
||||||
|
|
||||||
// Give the script some time to finish processing its last event. Simply aborting the script thread can
|
instance.Stop(m_WaitForEventCompletionOnScriptStop);
|
||||||
// cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort.
|
|
||||||
instance.Stop(1000);
|
|
||||||
|
|
||||||
// bool objectRemoved = false;
|
// bool objectRemoved = false;
|
||||||
|
|
||||||
|
@ -1735,17 +1798,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
public void StopScript(UUID itemID)
|
public void StopScript(UUID itemID)
|
||||||
{
|
{
|
||||||
IScriptInstance instance = GetInstance(itemID);
|
IScriptInstance instance = GetInstance(itemID);
|
||||||
|
|
||||||
if (instance != null)
|
if (instance != null)
|
||||||
{
|
instance.Stop(m_WaitForEventCompletionOnScriptStop);
|
||||||
// Give the script some time to finish processing its last event. Simply aborting the script thread can
|
|
||||||
// cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort.
|
|
||||||
instance.Stop(1000);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
m_runFlags.AddOrUpdate(itemID, false, 240);
|
m_runFlags.AddOrUpdate(itemID, false, 240);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public DetectParams GetDetectParams(UUID itemID, int idx)
|
public DetectParams GetDetectParams(UUID itemID, int idx)
|
||||||
{
|
{
|
||||||
|
|
|
@ -94,8 +94,6 @@ namespace OpenSim.Region.UserStatistics
|
||||||
if (!enabled)
|
if (!enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
AddEventHandlers();
|
|
||||||
|
|
||||||
if (Util.IsWindows())
|
if (Util.IsWindows())
|
||||||
Util.LoadArchSpecificWindowsDll("sqlite3.dll");
|
Util.LoadArchSpecificWindowsDll("sqlite3.dll");
|
||||||
|
|
||||||
|
@ -143,10 +141,14 @@ namespace OpenSim.Region.UserStatistics
|
||||||
lock (m_scenes)
|
lock (m_scenes)
|
||||||
{
|
{
|
||||||
m_scenes.Add(scene);
|
m_scenes.Add(scene);
|
||||||
if (m_simstatsCounters.ContainsKey(scene.RegionInfo.RegionID))
|
updateLogMod = m_scenes.Count * 2;
|
||||||
m_simstatsCounters.Remove(scene.RegionInfo.RegionID);
|
|
||||||
|
|
||||||
m_simstatsCounters.Add(scene.RegionInfo.RegionID, new USimStatsData(scene.RegionInfo.RegionID));
|
m_simstatsCounters.Add(scene.RegionInfo.RegionID, new USimStatsData(scene.RegionInfo.RegionID));
|
||||||
|
|
||||||
|
scene.EventManager.OnRegisterCaps += OnRegisterCaps;
|
||||||
|
scene.EventManager.OnDeregisterCaps += OnDeRegisterCaps;
|
||||||
|
scene.EventManager.OnClientClosed += OnClientClosed;
|
||||||
|
scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
|
||||||
scene.StatsReporter.OnSendStatsResult += ReceiveClassicSimStatsPacket;
|
scene.StatsReporter.OnSendStatsResult += ReceiveClassicSimStatsPacket;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,6 +159,15 @@ namespace OpenSim.Region.UserStatistics
|
||||||
|
|
||||||
public void RemoveRegion(Scene scene)
|
public void RemoveRegion(Scene scene)
|
||||||
{
|
{
|
||||||
|
if (!enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
lock (m_scenes)
|
||||||
|
{
|
||||||
|
m_scenes.Remove(scene);
|
||||||
|
updateLogMod = m_scenes.Count * 2;
|
||||||
|
m_simstatsCounters.Remove(scene.RegionInfo.RegionID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Close()
|
public virtual void Close()
|
||||||
|
@ -187,9 +198,7 @@ namespace OpenSim.Region.UserStatistics
|
||||||
private void ReceiveClassicSimStatsPacket(SimStats stats)
|
private void ReceiveClassicSimStatsPacket(SimStats stats)
|
||||||
{
|
{
|
||||||
if (!enabled)
|
if (!enabled)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -198,10 +207,17 @@ namespace OpenSim.Region.UserStatistics
|
||||||
if (concurrencyCounter > 0 || System.Environment.TickCount - lastHit > 30000)
|
if (concurrencyCounter > 0 || System.Environment.TickCount - lastHit > 30000)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((updateLogCounter++ % updateLogMod) == 0)
|
// We will conduct this under lock so that fields such as updateLogCounter do not potentially get
|
||||||
|
// confused if a scene is removed.
|
||||||
|
// XXX: Possibly the scope of this lock could be reduced though it's not critical.
|
||||||
|
lock (m_scenes)
|
||||||
|
{
|
||||||
|
if (updateLogMod != 0 && updateLogCounter++ % updateLogMod == 0)
|
||||||
{
|
{
|
||||||
m_loglines = readLogLines(10);
|
m_loglines = readLogLines(10);
|
||||||
if (updateLogCounter > 10000) updateLogCounter = 1;
|
|
||||||
|
if (updateLogCounter > 10000)
|
||||||
|
updateLogCounter = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
USimStatsData ss = m_simstatsCounters[stats.RegionUUID];
|
USimStatsData ss = m_simstatsCounters[stats.RegionUUID];
|
||||||
|
@ -211,6 +227,7 @@ namespace OpenSim.Region.UserStatistics
|
||||||
ss.ConsumeSimStats(stats);
|
ss.ConsumeSimStats(stats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
catch (KeyNotFoundException)
|
catch (KeyNotFoundException)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,12 +89,39 @@ namespace OpenSim.Server.Base
|
||||||
Config = config;
|
Config = config;
|
||||||
|
|
||||||
Registry = new AddinRegistry(registryPath, ".");
|
Registry = new AddinRegistry(registryPath, ".");
|
||||||
|
suppress_console_output_(true);
|
||||||
AddinManager.Initialize(registryPath);
|
AddinManager.Initialize(registryPath);
|
||||||
|
suppress_console_output_(false);
|
||||||
AddinManager.Registry.Update();
|
AddinManager.Registry.Update();
|
||||||
CommandManager commandmanager = new CommandManager(Registry);
|
CommandManager commandmanager = new CommandManager(Registry);
|
||||||
AddinManager.AddExtensionNodeHandler("/Robust/Connector", OnExtensionChanged);
|
AddinManager.AddExtensionNodeHandler("/Robust/Connector", OnExtensionChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static TextWriter prev_console_;
|
||||||
|
// Temporarily masking the errors reported on start
|
||||||
|
// This is caused by a non-managed dll in the ./bin dir
|
||||||
|
// when the registry is initialized. The dll belongs to
|
||||||
|
// libomv, which has a hard-coded path to "." for pinvoke
|
||||||
|
// to load the openjpeg dll
|
||||||
|
//
|
||||||
|
// Will look for a way to fix, but for now this keeps the
|
||||||
|
// confusion to a minimum. this was copied from our region
|
||||||
|
// plugin loader, we have been doing this in there for a long time.
|
||||||
|
//
|
||||||
|
public void suppress_console_output_(bool save)
|
||||||
|
{
|
||||||
|
if (save)
|
||||||
|
{
|
||||||
|
prev_console_ = System.Console.Out;
|
||||||
|
System.Console.SetOut(new StreamWriter(Stream.Null));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (prev_console_ != null)
|
||||||
|
System.Console.SetOut(prev_console_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void OnExtensionChanged(object s, ExtensionNodeEventArgs args)
|
private void OnExtensionChanged(object s, ExtensionNodeEventArgs args)
|
||||||
{
|
{
|
||||||
IRobustConnector connector = (IRobustConnector)args.ExtensionObject;
|
IRobustConnector connector = (IRobustConnector)args.ExtensionObject;
|
||||||
|
@ -112,8 +139,7 @@ namespace OpenSim.Server.Base
|
||||||
if (a.AddinFile.Contains(Registry.DefaultAddinsFolder))
|
if (a.AddinFile.Contains(Registry.DefaultAddinsFolder))
|
||||||
{
|
{
|
||||||
m_log.InfoFormat("[SERVER]: Adding {0} from registry", a.Name);
|
m_log.InfoFormat("[SERVER]: Adding {0} from registry", a.Name);
|
||||||
connector.PluginPath = String.Format("{0}/{1}", Registry.DefaultAddinsFolder, a.Name.Replace(',', '.'));
|
connector.PluginPath = System.IO.Path.Combine(Registry.DefaultAddinsFolder,a.Name.Replace(',', '.')); }
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_log.InfoFormat("[SERVER]: Adding {0} from ./bin", a.Name);
|
m_log.InfoFormat("[SERVER]: Adding {0} from ./bin", a.Name);
|
||||||
|
@ -195,14 +221,24 @@ namespace OpenSim.Server.Base
|
||||||
//if (dllName == string.Empty)
|
//if (dllName == string.Empty)
|
||||||
// Util.PrintCallStack();
|
// Util.PrintCallStack();
|
||||||
|
|
||||||
string[] parts = dllName.Split(new char[] {':'});
|
|
||||||
|
|
||||||
dllName = parts[0];
|
|
||||||
|
|
||||||
string className = String.Empty;
|
string className = String.Empty;
|
||||||
|
|
||||||
|
// The path for a dynamic plugin will contain ":" on Windows
|
||||||
|
string[] parts = dllName.Split (new char[] {':'});
|
||||||
|
|
||||||
|
if (parts [0].Length > 1)
|
||||||
|
{
|
||||||
|
dllName = parts [0];
|
||||||
if (parts.Length > 1)
|
if (parts.Length > 1)
|
||||||
className = parts[1];
|
className = parts[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This is Windows - we must replace the ":" in the path
|
||||||
|
dllName = String.Format ("{0}:{1}", parts [0], parts [1]);
|
||||||
|
if (parts.Length > 2)
|
||||||
|
className = parts[2];
|
||||||
|
}
|
||||||
|
|
||||||
return LoadPlugin<T>(dllName, className, args);
|
return LoadPlugin<T>(dllName, className, args);
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -32,9 +32,15 @@
|
||||||
<appender-ref ref="LogFileAppender" />
|
<appender-ref ref="LogFileAppender" />
|
||||||
</root>
|
</root>
|
||||||
|
|
||||||
|
<!-- Independently control logging level for XEngine -->
|
||||||
<logger name="OpenSim.Region.ScriptEngine.XEngine">
|
<logger name="OpenSim.Region.ScriptEngine.XEngine">
|
||||||
<level value="INFO"/>
|
<level value="INFO"/>
|
||||||
</logger>
|
</logger>
|
||||||
|
|
||||||
|
<!-- Independently control logging level for per region module loading -->
|
||||||
|
<logger name="OpenSim.ApplicationPlugins.RegionModulesController.RegionModulesControllerPlugin">
|
||||||
|
<level value="INFO"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
</log4net>
|
</log4net>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -1364,6 +1364,10 @@
|
||||||
; If a script overruns it's event limit, kill the script?
|
; If a script overruns it's event limit, kill the script?
|
||||||
KillTimedOutScripts = false
|
KillTimedOutScripts = false
|
||||||
|
|
||||||
|
; Amount of time in milliseconds we will wait for an event to completely normally when a script stop is requested
|
||||||
|
; before aborting the thread (such as when an object containing scripts is taken into inventory).
|
||||||
|
WaitForEventCompletionOnScriptStop = 1000;
|
||||||
|
|
||||||
; Sets the multiplier for the scripting delays
|
; Sets the multiplier for the scripting delays
|
||||||
ScriptDelayFactor = 1.0
|
ScriptDelayFactor = 1.0
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,18 @@
|
||||||
; *
|
; *
|
||||||
[Startup]
|
[Startup]
|
||||||
|
|
||||||
|
; Plugin Registry Location
|
||||||
|
; Set path to directory for plugin registry. Information
|
||||||
|
; about the registered repositories and installed plugins
|
||||||
|
; will be stored here
|
||||||
|
; The Robust.exe process must hvae R/W access to the location
|
||||||
|
RegistryLocation = "."
|
||||||
|
|
||||||
|
; Modular configurations
|
||||||
|
; Set path to directory for modular ini files...
|
||||||
|
; The Robust.exe process must hvae R/W access to the location
|
||||||
|
ConfigDirectory = "/home/opensim/etc/Configs"
|
||||||
|
|
||||||
[ServiceList]
|
[ServiceList]
|
||||||
|
|
||||||
AssetServiceConnector = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector"
|
AssetServiceConnector = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector"
|
||||||
|
@ -53,19 +65,6 @@ HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:Asset
|
||||||
;; Additions for other add-on modules. For example:
|
;; Additions for other add-on modules. For example:
|
||||||
;; WifiServerConnector = "8002/Diva.Wifi.dll:WifiServerConnector"
|
;; WifiServerConnector = "8002/Diva.Wifi.dll:WifiServerConnector"
|
||||||
|
|
||||||
|
|
||||||
; Plugin Registry Location
|
|
||||||
; Set path to directory for plugin registry. Information
|
|
||||||
; about the registered repositories and installed plugins
|
|
||||||
; will be stored here
|
|
||||||
; The Robust.exe process must hvae R/W access to the location
|
|
||||||
RegistryLocation = "."
|
|
||||||
|
|
||||||
; Modular configurations
|
|
||||||
; Set path to directory for modular ini files...
|
|
||||||
; The Robust.exe process must hvae R/W access to the location
|
|
||||||
ConfigDirectory = "/home/opensim/etc/Configs"
|
|
||||||
|
|
||||||
; * This is common for all services, it's the network setup for the entire
|
; * This is common for all services, it's the network setup for the entire
|
||||||
; * server instance, if none is specified above
|
; * server instance, if none is specified above
|
||||||
; *
|
; *
|
||||||
|
|
|
@ -14,6 +14,19 @@
|
||||||
; *
|
; *
|
||||||
[Startup]
|
[Startup]
|
||||||
|
|
||||||
|
; Plugin Registry Location
|
||||||
|
; Set path to directory for plugin registry. Information
|
||||||
|
; about the registered repositories and installed plugins
|
||||||
|
; will be stored here
|
||||||
|
; The Robust.exe process must hvae R/W access to the location
|
||||||
|
RegistryLocation = "."
|
||||||
|
|
||||||
|
|
||||||
|
; Modular configurations
|
||||||
|
; Set path to directory for modular ini files...
|
||||||
|
; The Robust.exe process must hvae R/W access to the location
|
||||||
|
ConfigDirectory = "/home/opensim/etc/Configs"
|
||||||
|
|
||||||
[ServiceList]
|
[ServiceList]
|
||||||
AssetServiceConnector = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector"
|
AssetServiceConnector = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector"
|
||||||
InventoryInConnector = "8003/OpenSim.Server.Handlers.dll:XInventoryInConnector"
|
InventoryInConnector = "8003/OpenSim.Server.Handlers.dll:XInventoryInConnector"
|
||||||
|
@ -31,19 +44,6 @@ FriendsServiceConnector = "8003/OpenSim.Server.Handlers.dll:FriendsServiceConnec
|
||||||
MapAddServiceConnector = "8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector"
|
MapAddServiceConnector = "8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector"
|
||||||
MapGetServiceConnector = "8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector"
|
MapGetServiceConnector = "8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector"
|
||||||
|
|
||||||
; Plugin Registry Location
|
|
||||||
; Set path to directory for plugin registry. Information
|
|
||||||
; about the registered repositories and installed plugins
|
|
||||||
; will be stored here
|
|
||||||
; The Robust.exe process must hvae R/W access to the location
|
|
||||||
RegistryLocation = "."
|
|
||||||
|
|
||||||
|
|
||||||
; Modular configurations
|
|
||||||
; Set path to directory for modular ini files...
|
|
||||||
; The Robust.exe process must hvae R/W access to the location
|
|
||||||
ConfigDirectory = "/home/opensim/etc/Configs"
|
|
||||||
|
|
||||||
; * This is common for all services, it's the network setup for the entire
|
; * This is common for all services, it's the network setup for the entire
|
||||||
; * server instance, if none is specified above
|
; * server instance, if none is specified above
|
||||||
; *
|
; *
|
||||||
|
|
Loading…
Reference in New Issue