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 (console != null)
|
||||
console.OutputFormat("{0} is not a valid uuid", rawUuid);
|
||||
console.OutputFormat("ERROR: {0} is not a valid uuid", rawUuid);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ namespace OpenSim.Framework.Console
|
|||
if (!uint.TryParse(rawLocalId, out localId))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ namespace OpenSim.Framework.Console
|
|||
if (localId == 0)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -150,11 +150,31 @@ namespace OpenSim.Framework.Console
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// Convert a minimum vector input from the console to an OpenMetaverse.Vector3
|
||||
/// </summary>
|
||||
|
|
|
@ -92,6 +92,7 @@ namespace OpenSim.Framework
|
|||
// Attempt to install the plugin disabled
|
||||
if (Install(ps, pack) == true)
|
||||
{
|
||||
MainConsole.Instance.Output("Ignore the following error...");
|
||||
PluginRegistry.Update(ps);
|
||||
Addin addin = PluginRegistry.GetAddin(aentry.Addin.Id);
|
||||
PluginRegistry.DisableAddin(addin.Id);
|
||||
|
@ -479,6 +480,7 @@ namespace OpenSim.Framework
|
|||
ConsoleProgressStatus ps = new ConsoleProgressStatus(false);
|
||||
if (!AddinManager.AddinEngine.IsAddinLoaded(addin.Id))
|
||||
{
|
||||
MainConsole.Instance.Output("Ignore the following error...");
|
||||
AddinManager.Registry.Rebuild(ps);
|
||||
AddinManager.AddinEngine.LoadAddin(ps, addin.Id);
|
||||
}
|
||||
|
|
|
@ -12077,11 +12077,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
if (logPacket)
|
||||
m_log.DebugFormat(
|
||||
"[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))
|
||||
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)
|
||||
|
|
|
@ -71,7 +71,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
|||
|
||||
#region Internal functions
|
||||
|
||||
public AssetMetadata FetchMetadata(string url, UUID assetID)
|
||||
private AssetMetadata FetchMetadata(string url, UUID assetID)
|
||||
{
|
||||
if (!url.EndsWith("/") && !url.EndsWith("="))
|
||||
url = url + "/";
|
||||
|
@ -86,6 +86,27 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
|||
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)
|
||||
{
|
||||
if (asset != null)
|
||||
|
@ -228,11 +249,22 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
|||
if (meta == null)
|
||||
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>();
|
||||
HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL);
|
||||
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);
|
||||
|
||||
// searhc the user accounts service
|
||||
List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query);
|
||||
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
//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);
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ namespace OpenSim.Region.CoreModules.World.Sound
|
|||
|
||||
public void RemoveRegion(Scene scene)
|
||||
{
|
||||
m_scene.EventManager.OnClientLogin -= OnNewClient;
|
||||
m_scene.EventManager.OnNewClient -= OnNewClient;
|
||||
}
|
||||
|
||||
public void RegionLoaded(Scene scene)
|
||||
|
@ -85,7 +85,7 @@ namespace OpenSim.Region.CoreModules.World.Sound
|
|||
return;
|
||||
|
||||
m_scene = scene;
|
||||
m_scene.EventManager.OnClientLogin += OnNewClient;
|
||||
m_scene.EventManager.OnNewClient += OnNewClient;
|
||||
|
||||
m_scene.RegisterModuleInterface<ISoundModule>(this);
|
||||
}
|
||||
|
|
|
@ -26,9 +26,10 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
|
@ -113,6 +114,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation
|
|||
if (m_scenePresence.IsChildAgent)
|
||||
return;
|
||||
|
||||
// m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Removing animation {0} for {1}", animID, m_scenePresence.Name);
|
||||
|
||||
if (m_animations.Remove(animID))
|
||||
SendAnimPack();
|
||||
}
|
||||
|
@ -519,6 +522,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation
|
|||
if (m_scenePresence.IsChildAgent)
|
||||
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(
|
||||
delegate(IClientAPI client)
|
||||
{
|
||||
|
|
|
@ -683,12 +683,10 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
itemCopy.SalePrice = item.SalePrice;
|
||||
itemCopy.SaleType = item.SaleType;
|
||||
|
||||
if (AddInventoryItem(itemCopy))
|
||||
{
|
||||
IInventoryAccessModule invAccess = RequestModuleInterface<IInventoryAccessModule>();
|
||||
if (invAccess != null)
|
||||
Util.FireAndForget(delegate { invAccess.TransferInventoryAssets(itemCopy, senderId, recipient); });
|
||||
}
|
||||
invAccess.TransferInventoryAssets(itemCopy, senderId, recipient);
|
||||
AddInventoryItem(itemCopy);
|
||||
|
||||
if (!Permissions.BypassPermissions())
|
||||
{
|
||||
|
|
|
@ -2895,11 +2895,14 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
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);
|
||||
DoPhysicsPropertyUpdate(false, true);
|
||||
//ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
|
||||
}
|
||||
|
||||
public void PhysicsRequestingTerseUpdate()
|
||||
|
@ -4549,7 +4552,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
if (ParentGroup.RootPart == this)
|
||||
AngularVelocity = new Vector3(0, 0, 0);
|
||||
}
|
||||
else
|
||||
else if (SetVD != wasVD)
|
||||
{
|
||||
if (ParentGroup.Scene.CollidablePrims)
|
||||
{
|
||||
|
|
|
@ -214,8 +214,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
private Quaternion m_headrotation = Quaternion.Identity;
|
||||
|
||||
private string m_nextSitAnimation = String.Empty;
|
||||
|
||||
//PauPaw:Proper PID Controler for autopilot************
|
||||
public bool MovingToTarget { get; private set; }
|
||||
public Vector3 MoveToPositionTarget { get; private set; }
|
||||
|
@ -2120,25 +2118,10 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
StandUp();
|
||||
}
|
||||
|
||||
// if (!String.IsNullOrEmpty(sitAnimation))
|
||||
// {
|
||||
// m_nextSitAnimation = sitAnimation;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
m_nextSitAnimation = "SIT";
|
||||
// }
|
||||
|
||||
//SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
|
||||
SceneObjectPart part = FindNextAvailableSitTarget(targetID);
|
||||
|
||||
if (part != null)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(part.SitAnimation))
|
||||
{
|
||||
m_nextSitAnimation = part.SitAnimation;
|
||||
}
|
||||
|
||||
m_requestedSitTargetID = part.LocalId;
|
||||
m_requestedSitTargetUUID = targetID;
|
||||
|
||||
|
@ -2352,18 +2335,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
*/
|
||||
|
||||
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);
|
||||
|
||||
|
@ -2437,6 +2408,11 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
Velocity = Vector3.Zero;
|
||||
RemoveFromPhysicalScene();
|
||||
|
||||
String sitAnimation = "SIT";
|
||||
if (!String.IsNullOrEmpty(part.SitAnimation))
|
||||
{
|
||||
sitAnimation = part.SitAnimation;
|
||||
}
|
||||
Animator.TrySetMovementAnimation(sitAnimation);
|
||||
SendAvatarDataToAllAgents();
|
||||
}
|
||||
|
|
|
@ -77,6 +77,26 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
|||
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]
|
||||
public void TestSetPhysicsSinglePrim()
|
||||
{
|
||||
|
@ -89,7 +109,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
|||
|
||||
m_so1.ScriptSetPhysicsStatus(true);
|
||||
|
||||
// Console.WriteLine("so.RootPart.Flags [{0}]", so.RootPart.Flags);
|
||||
Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Physics));
|
||||
|
||||
m_so1.ScriptSetPhysicsStatus(false);
|
||||
|
@ -97,6 +116,26 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
|||
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]
|
||||
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}",
|
||||
LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass);
|
||||
|
||||
// do actual create at taint time
|
||||
// do actual creation in taint time
|
||||
PhysicsScene.TaintedObject("BSCharacter.create", delegate()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.create,taint", LocalID);
|
||||
// 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();
|
||||
});
|
||||
|
@ -124,7 +124,9 @@ public sealed class BSCharacter : BSPhysObject
|
|||
PhysicsScene.TaintedObject("BSCharacter.destroy", delegate()
|
||||
{
|
||||
PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null);
|
||||
PhysBody.Clear();
|
||||
PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null);
|
||||
PhysShape.Clear();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -165,9 +167,8 @@ public sealed class BSCharacter : BSPhysObject
|
|||
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
|
||||
|
||||
// Do this after the object has been added to the world
|
||||
BulletSimAPI.SetCollisionGroupMask2(PhysBody.ptr,
|
||||
(uint)CollisionFilterGroups.AvatarGroup,
|
||||
(uint)CollisionFilterGroups.AvatarMask);
|
||||
PhysBody.collisionType = CollisionType.Avatar;
|
||||
PhysBody.ApplyCollisionMask();
|
||||
}
|
||||
|
||||
public override void RequestPhysicsterseUpdate()
|
||||
|
@ -187,22 +188,30 @@ public sealed class BSCharacter : BSPhysObject
|
|||
set {
|
||||
// When an avatar's size is set, only the height is changed.
|
||||
_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);
|
||||
ComputeAvatarVolumeAndMass();
|
||||
DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}",
|
||||
LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass);
|
||||
|
||||
PhysicsScene.TaintedObject("BSCharacter.setSize", delegate()
|
||||
{
|
||||
if (PhysBody.HasPhysicalBody && PhysShape.HasPhysicalShape)
|
||||
{
|
||||
BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale);
|
||||
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
|
||||
{
|
||||
set { BaseShape = value; }
|
||||
|
@ -236,6 +245,7 @@ public sealed class BSCharacter : BSPhysObject
|
|||
// Zero some other properties directly into the physics engine
|
||||
PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate()
|
||||
{
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
BulletSimAPI.ClearAllForces2(PhysBody.ptr);
|
||||
});
|
||||
}
|
||||
|
@ -244,11 +254,14 @@ public sealed class BSCharacter : BSPhysObject
|
|||
_rotationalVelocity = OMV.Vector3.Zero;
|
||||
|
||||
PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate()
|
||||
{
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
{
|
||||
BulletSimAPI.SetInterpolationAngularVelocity2(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.
|
||||
BulletSimAPI.ClearForces2(PhysBody.ptr);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -273,6 +286,7 @@ public sealed class BSCharacter : BSPhysObject
|
|||
PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
|
||||
});
|
||||
}
|
||||
|
@ -332,6 +346,7 @@ public sealed class BSCharacter : BSPhysObject
|
|||
PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
|
||||
});
|
||||
ret = true;
|
||||
|
@ -359,6 +374,7 @@ public sealed class BSCharacter : BSPhysObject
|
|||
PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force);
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force);
|
||||
});
|
||||
}
|
||||
|
@ -398,6 +414,7 @@ public sealed class BSCharacter : BSPhysObject
|
|||
if (_currentFriction != PhysicsScene.Params.avatarStandingFriction)
|
||||
{
|
||||
_currentFriction = PhysicsScene.Params.avatarStandingFriction;
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction);
|
||||
}
|
||||
}
|
||||
|
@ -406,6 +423,7 @@ public sealed class BSCharacter : BSPhysObject
|
|||
if (_currentFriction != PhysicsScene.Params.avatarFriction)
|
||||
{
|
||||
_currentFriction = PhysicsScene.Params.avatarFriction;
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction);
|
||||
}
|
||||
}
|
||||
|
@ -442,9 +460,12 @@ public sealed class BSCharacter : BSPhysObject
|
|||
_orientation = value;
|
||||
// m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation);
|
||||
PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate()
|
||||
{
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
{
|
||||
// _position = BulletSimAPI.GetPosition2(BSBody.ptr);
|
||||
BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -516,11 +537,14 @@ public sealed class BSCharacter : BSPhysObject
|
|||
set {
|
||||
_floatOnWater = value;
|
||||
PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate()
|
||||
{
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
{
|
||||
if (_floatOnWater)
|
||||
CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
|
||||
else
|
||||
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);
|
||||
// Buoyancy is faked by changing the gravity applied to the object
|
||||
float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav));
|
||||
}
|
||||
}
|
||||
|
@ -599,6 +624,7 @@ public sealed class BSCharacter : BSPhysObject
|
|||
PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force);
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force);
|
||||
});
|
||||
}
|
||||
|
@ -616,9 +642,6 @@ public sealed class BSCharacter : BSPhysObject
|
|||
|
||||
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;
|
||||
// newScale.X = PhysicsScene.Params.avatarCapsuleWidth;
|
||||
// newScale.Y = PhysicsScene.Params.avatarCapsuleDepth;
|
||||
|
|
|
@ -57,7 +57,7 @@ public abstract class BSConstraint : IDisposable
|
|||
if (m_enabled)
|
||||
{
|
||||
m_enabled = false;
|
||||
if (m_constraint.ptr != IntPtr.Zero)
|
||||
if (m_constraint.HasPhysicalConstraint)
|
||||
{
|
||||
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}",
|
||||
|
@ -65,7 +65,7 @@ public abstract class BSConstraint : IDisposable
|
|||
m_body1.ID, m_body1.ptr.ToString("X"),
|
||||
m_body2.ID, m_body2.ptr.ToString("X"),
|
||||
success);
|
||||
m_constraint.ptr = System.IntPtr.Zero;
|
||||
m_constraint.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ public sealed class BSConstraint6Dof : BSConstraint
|
|||
m_world = world;
|
||||
m_body1 = obj1;
|
||||
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}",
|
||||
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}",
|
||||
BSScene.DetailLogZero, world.worldID, m_constraint.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}",
|
||||
LogHeader, obj1.ID, obj2.ID);
|
||||
|
|
|
@ -570,8 +570,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia);
|
||||
BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr);
|
||||
|
||||
VDetailLog("{0},BSDynamics.Refresh,frict={1},inert={2},aDamp={3}",
|
||||
Prim.LocalID, friction, localInertia, angularDamping);
|
||||
VDetailLog("{0},BSDynamics.Refresh,mass={1},frict={2},inert={3},aDamp={4}",
|
||||
Prim.LocalID, m_vehicleMass, friction, localInertia, angularDamping);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -818,6 +818,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
+ hoverContribution
|
||||
+ limitMotorUpContribution;
|
||||
|
||||
Vector3 newForce = buoyancyContribution;
|
||||
|
||||
// If not changing some axis, reduce out velocity
|
||||
if ((m_flags & (VehicleFlag.NO_X)) != 0)
|
||||
newVelocity.X = 0;
|
||||
|
@ -845,7 +847,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
VehicleVelocity = newVelocity;
|
||||
|
||||
// Other linear forces are applied as forces.
|
||||
Vector3 totalDownForce = buoyancyContribution * m_vehicleMass;
|
||||
Vector3 totalDownForce = newForce * m_vehicleMass;
|
||||
if (!totalDownForce.ApproxEquals(Vector3.Zero, 0.01f))
|
||||
{
|
||||
VehicleAddForce(totalDownForce);
|
||||
|
@ -991,8 +993,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
|
||||
if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
|
||||
{
|
||||
// If the vehicle is motoring into the sky, get it going back down.
|
||||
float distanceAboveGround = VehiclePosition.Z - GetTerrainHeight(VehiclePosition);
|
||||
float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition);
|
||||
float distanceAboveGround = VehiclePosition.Z - targetHeight;
|
||||
// Not colliding if the vehicle is off the ground
|
||||
if (!Prim.IsColliding)
|
||||
{
|
||||
|
@ -1005,8 +1007,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
// has a decay factor. This says this force should
|
||||
// be computed with a motor.
|
||||
// TODO: add interaction with banking.
|
||||
VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},downForce={2}",
|
||||
Prim.LocalID, distanceAboveGround, ret);
|
||||
VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}",
|
||||
Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -1055,7 +1057,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
// TODO: Should this be applied as an angular force (torque)?
|
||||
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;
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
// 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
|
||||
{
|
||||
// private static string LogHeader = "[BULLETSIM LINKSET]";
|
||||
|
@ -116,7 +124,7 @@ public abstract class BSLinkset
|
|||
get { return ComputeLinksetGeometricCenter(); }
|
||||
}
|
||||
|
||||
protected void Initialize(BSScene scene, BSPhysObject parent)
|
||||
protected BSLinkset(BSScene scene, BSPhysObject parent)
|
||||
{
|
||||
// A simple linkset of one (no children)
|
||||
LinksetID = m_nextLinksetID++;
|
||||
|
@ -127,6 +135,7 @@ public abstract class BSLinkset
|
|||
LinksetRoot = parent;
|
||||
m_children = new HashSet<BSPhysObject>();
|
||||
m_mass = parent.RawMass;
|
||||
Rebuilding = false;
|
||||
}
|
||||
|
||||
// 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.
|
||||
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
|
||||
// for a dynamic 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
|
||||
{
|
||||
|
||||
// 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
|
||||
{
|
||||
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.
|
||||
public override BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
|
||||
{
|
||||
// Returning 'unknown' means we don't have a preference.
|
||||
BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
if (IsRoot(requestor) && HasAnyChildren)
|
||||
{
|
||||
|
@ -55,24 +80,28 @@ public sealed class BSLinksetCompound : BSLinkset
|
|||
|
||||
// When physical properties are changed the linkset needs to recalculate
|
||||
// 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)
|
||||
{
|
||||
// External request for Refresh (from BSPrim) doesn't need to do anything
|
||||
// InternalRefresh(requestor);
|
||||
}
|
||||
|
||||
// Schedule a refresh to happen after all the other taint processing.
|
||||
private void InternalRefresh(BSPhysObject requestor)
|
||||
{
|
||||
DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID);
|
||||
// Queue to happen after all the other taint processing
|
||||
DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1},rebuilding={2}",
|
||||
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()
|
||||
{
|
||||
if (IsRoot(requestor) && HasAnyChildren)
|
||||
RecomputeLinksetCompound();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// The object is going dynamic (physical). Do any setup necessary
|
||||
// for a dynamic linkset.
|
||||
|
@ -84,12 +113,24 @@ public sealed class BSLinksetCompound : BSLinkset
|
|||
{
|
||||
bool ret = false;
|
||||
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
|
||||
// shape takes over.
|
||||
BulletSimAPI.AddToCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
|
||||
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;
|
||||
}
|
||||
return ret;
|
||||
|
@ -104,11 +145,19 @@ public sealed class BSLinksetCompound : BSLinkset
|
|||
{
|
||||
bool ret = false;
|
||||
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.
|
||||
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);
|
||||
ret = true;
|
||||
}
|
||||
|
@ -146,11 +195,15 @@ public sealed class BSLinksetCompound : BSLinkset
|
|||
|
||||
if (!IsRoot(child))
|
||||
{
|
||||
// Cause the current shape to be freed and the new one to be built.
|
||||
InternalRefresh(LinksetRoot);
|
||||
ret = true;
|
||||
// Because it is a convenient time, recompute child world position and rotation based on
|
||||
// its position in the linkset.
|
||||
RecomputeChildWorldPosition(child, true);
|
||||
}
|
||||
|
||||
// Cannot schedule a refresh/rebuild here because this routine is called when
|
||||
// the linkset is being rebuilt.
|
||||
// InternalRefresh(LinksetRoot);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -159,7 +212,41 @@ public sealed class BSLinksetCompound : BSLinkset
|
|||
// Called at taint-time!!
|
||||
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.
|
||||
// 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)
|
||||
{
|
||||
if (m_children.Remove(child))
|
||||
|
@ -192,6 +279,7 @@ public sealed class BSLinksetCompound : BSLinkset
|
|||
child.LocalID, child.PhysBody.ptr.ToString("X"));
|
||||
|
||||
// Cause the child's body to be rebuilt and thus restored to normal operation
|
||||
RecomputeChildWorldPosition(child, false);
|
||||
child.ForceBodyShapeRebuild(false);
|
||||
|
||||
if (!HasAnyChildren)
|
||||
|
@ -215,6 +303,11 @@ public sealed class BSLinksetCompound : BSLinkset
|
|||
// Called at taint time!!
|
||||
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
|
||||
LinksetRoot.ForceBodyShapeRebuild(true);
|
||||
|
||||
|
@ -225,49 +318,68 @@ public sealed class BSLinksetCompound : BSLinkset
|
|||
ForEachMember(delegate(BSPhysObject 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.
|
||||
OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation);
|
||||
OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * 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}",
|
||||
LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, displacementPos, displacementRot);
|
||||
LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot);
|
||||
|
||||
if (cPrim.PhysShape.isNativeShape)
|
||||
{
|
||||
// Native shapes are not shared so we need to create a new one.
|
||||
// A mesh or hull is created because scale is not available on a native shape.
|
||||
// (TODO: Bullet does have a btScaledCollisionShape. Can that be used?)
|
||||
// A native shape is turning into a hull collision shape because native
|
||||
// shapes are not shared so we have to hullify it so it will be tracked
|
||||
// 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;
|
||||
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);
|
||||
BulletShape newShape = cPrim.PhysShape;
|
||||
cPrim.PhysShape = saveShape;
|
||||
BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, displacementPos, displacementRot);
|
||||
BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, lci.OffsetPos, lci.OffsetRot);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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))
|
||||
{
|
||||
PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
|
||||
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
|
||||
});
|
||||
|
||||
// With all of the linkset packed into the root prim, it has the mass of everyone.
|
||||
float linksetMass = LinksetMass;
|
||||
LinksetRoot.UpdatePhysicalMassProperties(linksetMass);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Rebuilding = false;
|
||||
}
|
||||
|
||||
BulletSimAPI.RecalculateCompoundShapeLocalAabb2(LinksetRoot.PhysShape.ptr);
|
||||
|
||||
|
|
|
@ -36,9 +36,8 @@ public sealed class BSLinksetConstraints : BSLinkset
|
|||
{
|
||||
// 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
|
||||
|
|
|
@ -50,10 +50,11 @@ public struct MaterialAttributes
|
|||
Avatar,
|
||||
NumberOfTypes // the count of types in the enum.
|
||||
}
|
||||
|
||||
// Names must be in the order of the above enum.
|
||||
public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood",
|
||||
"Flesh", "Plastic", "Rubber", "Light", "Avatar" };
|
||||
public static string[] MaterialAttribs = { "Density", "Friction", "Restitution"};
|
||||
// These names must coorespond to the lower case field names in the MaterialAttributes
|
||||
// structure as reflection is used to select the field to put the value in.
|
||||
public static readonly string[] MaterialAttribs = { "Density", "Friction", "Restitution"};
|
||||
|
||||
public MaterialAttributes(string t, float d, float f, float r)
|
||||
{
|
||||
|
@ -70,23 +71,37 @@ public struct MaterialAttributes
|
|||
|
||||
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()
|
||||
{
|
||||
// Attribute sets for both the non-physical and physical instances of materials.
|
||||
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.
|
||||
public static void InitializeFromDefaults(ConfigurationParameters parms)
|
||||
{
|
||||
// Values from http://wiki.secondlife.com/wiki/PRIM_MATERIAL
|
||||
// public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood",
|
||||
// "Flesh", "Plastic", "Rubber", "Light", "Avatar" };
|
||||
float dDensity = parms.defaultDensity;
|
||||
float dFriction = parms.defaultFriction;
|
||||
float dRestitution = parms.defaultRestitution;
|
||||
float dDensity = parms.defaultDensity;
|
||||
Attributes[(int)MaterialAttributes.Material.Stone] =
|
||||
new MaterialAttributes("stone",dDensity, 0.8f, 0.4f);
|
||||
Attributes[(int)MaterialAttributes.Material.Metal] =
|
||||
|
@ -139,34 +154,34 @@ public static class BSMaterials
|
|||
// the physical value.
|
||||
public static void InitializefromParameters(IConfig pConfig)
|
||||
{
|
||||
int matType = 0;
|
||||
foreach (string matName in MaterialAttributes.MaterialNames)
|
||||
foreach (KeyValuePair<string, MaterialAttributes.Material> kvp in MaterialMap)
|
||||
{
|
||||
string matName = kvp.Key;
|
||||
foreach (string attribName in MaterialAttributes.MaterialAttribs)
|
||||
{
|
||||
string paramName = matName + attribName;
|
||||
if (pConfig.Contains(paramName))
|
||||
{
|
||||
float paramValue = pConfig.GetFloat(paramName);
|
||||
SetAttributeValue(matType, attribName, paramValue);
|
||||
SetAttributeValue((int)kvp.Value, attribName, paramValue);
|
||||
// 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";
|
||||
if (pConfig.Contains(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)
|
||||
{
|
||||
MaterialAttributes thisAttrib = Attributes[matType];
|
||||
FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName);
|
||||
FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName.ToLower());
|
||||
if (fieldInfo != null)
|
||||
{
|
||||
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)
|
||||
{
|
||||
int ind = (int)type;
|
||||
if (isPhysical) ind += (int)MaterialAttributes.Material.NumberOfTypes;
|
||||
return Attributes[ind];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ public abstract class BSMotor
|
|||
// Can all the incremental stepping be replaced with motor classes?
|
||||
|
||||
// Motor which moves CurrentValue to TargetValue over TimeScale seconds.
|
||||
// The TargetValue is decays in TargetValueDecayTimeScale and
|
||||
// The TargetValue decays in TargetValueDecayTimeScale and
|
||||
// the CurrentValue will be held back by FrictionTimeScale.
|
||||
// TimeScale and TargetDelayTimeScale may be 'infinite' which means go decay.
|
||||
|
||||
|
|
|
@ -60,6 +60,9 @@ public abstract class BSPhysObject : PhysicsActor
|
|||
Linkset = BSLinkset.Factory(PhysicsScene, this);
|
||||
LastAssetBuildFailed = false;
|
||||
|
||||
// Default material type
|
||||
Material = MaterialAttributes.Material.Wood;
|
||||
|
||||
CollisionCollection = new CollisionEventUpdate();
|
||||
SubscribedEventsMs = 0;
|
||||
CollidingStep = 0;
|
||||
|
@ -72,6 +75,7 @@ public abstract class BSPhysObject : PhysicsActor
|
|||
public string TypeName { get; protected set; }
|
||||
|
||||
public BSLinkset Linkset { get; set; }
|
||||
public BSLinksetInfo LinksetInfo { get; set; }
|
||||
|
||||
// Return the object mass without calculating it or having side effects
|
||||
public abstract float RawMass { get; }
|
||||
|
@ -105,10 +109,17 @@ public abstract class BSPhysObject : PhysicsActor
|
|||
public EntityProperties CurrentEntityProperties { 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 IsStatic { get; }
|
||||
|
||||
// Materialness
|
||||
public MaterialAttributes.Material Material { get; private set; }
|
||||
public override void SetMaterial(int material)
|
||||
{
|
||||
Material = (MaterialAttributes.Material)material;
|
||||
}
|
||||
|
||||
// Stop all physical motion.
|
||||
public abstract void ZeroMotion(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 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 ForceRotationalVelocity { get; set; }
|
||||
|
@ -243,6 +265,8 @@ public abstract class BSPhysObject : PhysicsActor
|
|||
SubscribedEventsMs = 0;
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -45,7 +45,6 @@ public sealed class BSPrim : BSPhysObject
|
|||
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.
|
||||
// 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 bool _grabbed;
|
||||
|
@ -93,7 +92,7 @@ public sealed class BSPrim : BSPhysObject
|
|||
_physicsActorType = (int)ActorTypes.Prim;
|
||||
_position = pos;
|
||||
_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;
|
||||
_buoyancy = 1f;
|
||||
_velocity = OMV.Vector3.Zero;
|
||||
|
@ -108,8 +107,8 @@ public sealed class BSPrim : BSPhysObject
|
|||
_mass = CalculateMass();
|
||||
|
||||
// No body or shape yet
|
||||
PhysBody = new BulletBody(LocalID, IntPtr.Zero);
|
||||
PhysShape = new BulletShape(IntPtr.Zero);
|
||||
PhysBody = new BulletBody(LocalID);
|
||||
PhysShape = new BulletShape();
|
||||
|
||||
DetailLog("{0},BSPrim.constructor,call", LocalID);
|
||||
// do the actual object creation at taint time
|
||||
|
@ -143,7 +142,9 @@ public sealed class BSPrim : BSPhysObject
|
|||
DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
|
||||
// If there are physical body and shape, release my use of same.
|
||||
PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null);
|
||||
PhysBody.Clear();
|
||||
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
|
||||
// the physical shape, that is done when the geometry is built.
|
||||
_size = value;
|
||||
Scale = _size;
|
||||
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 {
|
||||
set {
|
||||
|
@ -189,7 +188,8 @@ public sealed class BSPrim : BSPhysObject
|
|||
}
|
||||
}
|
||||
public override bool Selected {
|
||||
set {
|
||||
set
|
||||
{
|
||||
if (value != _isSelected)
|
||||
{
|
||||
_isSelected = value;
|
||||
|
@ -247,6 +247,7 @@ public sealed class BSPrim : BSPhysObject
|
|||
// Zero some other properties in the physics engine
|
||||
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
|
||||
{
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
BulletSimAPI.ClearAllForces2(PhysBody.ptr);
|
||||
});
|
||||
}
|
||||
|
@ -257,8 +258,11 @@ public sealed class BSPrim : BSPhysObject
|
|||
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
|
||||
{
|
||||
// DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity);
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
{
|
||||
BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
|
||||
BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -295,8 +299,11 @@ public sealed class BSPrim : BSPhysObject
|
|||
PhysicsScene.TaintedObject("BSPrim.setPosition", delegate()
|
||||
{
|
||||
// DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
{
|
||||
BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
|
||||
ActivateIfPhysical(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -322,12 +329,12 @@ public sealed class BSPrim : BSPhysObject
|
|||
|
||||
float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position);
|
||||
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);
|
||||
float targetHeight = terrainHeight + (Size.Z / 2f);
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -335,10 +342,10 @@ public sealed class BSPrim : BSPhysObject
|
|||
{
|
||||
float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position);
|
||||
// TODO: a floating motor so object will bob in the water
|
||||
if (Math.Abs(Position.Z - waterHeight) > 0.1f)
|
||||
if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
@ -413,6 +420,7 @@ public sealed class BSPrim : BSPhysObject
|
|||
PhysicsScene.TaintedObject("BSPrim.setForce", delegate()
|
||||
{
|
||||
// DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force);
|
||||
});
|
||||
}
|
||||
|
@ -507,6 +515,7 @@ public sealed class BSPrim : BSPhysObject
|
|||
PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate()
|
||||
{
|
||||
// DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity);
|
||||
});
|
||||
}
|
||||
|
@ -555,10 +564,13 @@ public sealed class BSPrim : BSPhysObject
|
|||
_orientation = value;
|
||||
// TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
|
||||
PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
|
||||
{
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
{
|
||||
// _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr);
|
||||
// DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||
BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -649,14 +661,7 @@ public sealed class BSPrim : BSPhysObject
|
|||
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
|
||||
|
||||
// Collision filter can be set only when the object is in the world
|
||||
if (PhysBody.collisionGroup != 0 || PhysBody.collisionMask != 0)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
PhysBody.ApplyCollisionMask();
|
||||
|
||||
// Recompute any linkset parameters.
|
||||
// When going from non-physical to physical, this re-enables the constraints that
|
||||
|
@ -683,8 +688,9 @@ public sealed class BSPrim : BSPhysObject
|
|||
ZeroMotion(true);
|
||||
|
||||
// Set various physical properties so other object interact properly
|
||||
BulletSimAPI.SetFriction2(PhysBody.ptr, PhysicsScene.Params.defaultFriction);
|
||||
BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.defaultRestitution);
|
||||
MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false);
|
||||
BulletSimAPI.SetFriction2(PhysBody.ptr, matAttrib.friction);
|
||||
BulletSimAPI.SetRestitution2(PhysBody.ptr, matAttrib.restitution);
|
||||
|
||||
// Mass is zero which disables a bunch of physics stuff in Bullet
|
||||
UpdatePhysicalMassProperties(0f);
|
||||
|
@ -700,20 +706,21 @@ public sealed class BSPrim : BSPhysObject
|
|||
// Start it out sleeping and physical actions could wake it up.
|
||||
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
|
||||
Linkset.MakeStatic(this);
|
||||
|
||||
PhysBody.collisionGroup = CollisionFilterGroups.StaticObjectGroup;
|
||||
PhysBody.collisionMask = CollisionFilterGroups.StaticObjectMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not a Bullet 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
|
||||
BulletSimAPI.SetFriction2(PhysBody.ptr, PhysicsScene.Params.defaultFriction);
|
||||
BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.defaultRestitution);
|
||||
// Set various physical properties so other object interact properly
|
||||
MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, true);
|
||||
BulletSimAPI.SetFriction2(PhysBody.ptr, matAttrib.friction);
|
||||
BulletSimAPI.SetRestitution2(PhysBody.ptr, matAttrib.restitution);
|
||||
|
||||
// per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
|
||||
// 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.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold);
|
||||
|
||||
// There might be special things needed for implementing linksets.
|
||||
Linkset.MakeDynamic(this);
|
||||
// This collides like an object.
|
||||
PhysBody.collisionType = CollisionType.Dynamic;
|
||||
|
||||
// Force activation of the object so Bullet will act on it.
|
||||
// Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
|
||||
BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG);
|
||||
// BulletSimAPI.Activate2(BSBody.ptr, true);
|
||||
|
||||
PhysBody.collisionGroup = CollisionFilterGroups.ObjectGroup;
|
||||
PhysBody.collisionMask = CollisionFilterGroups.ObjectMask;
|
||||
// There might be special things needed for implementing linksets.
|
||||
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);
|
||||
}
|
||||
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()
|
||||
{
|
||||
DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
|
||||
});
|
||||
}
|
||||
|
@ -896,10 +904,13 @@ public sealed class BSPrim : BSPhysObject
|
|||
_buoyancy = value;
|
||||
// DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
|
||||
// Buoyancy is faked by changing the gravity applied to the object
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
{
|
||||
float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
|
||||
BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Used for MoveTo
|
||||
public override OMV.Vector3 PIDTarget {
|
||||
|
@ -965,6 +976,7 @@ public sealed class BSPrim : BSPhysObject
|
|||
}
|
||||
DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum);
|
||||
if (fSum != OMV.Vector3.Zero)
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum);
|
||||
});
|
||||
}
|
||||
|
@ -976,6 +988,7 @@ public sealed class BSPrim : BSPhysObject
|
|||
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyForceImpulse", delegate()
|
||||
{
|
||||
DetailLog("{0},BSPrim.ApplyForceImpulse,taint,tImpulse={1}", LocalID, applyImpulse);
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
BulletSimAPI.ApplyCentralImpulse2(PhysBody.ptr, applyImpulse);
|
||||
});
|
||||
}
|
||||
|
@ -1012,6 +1025,7 @@ public sealed class BSPrim : BSPhysObject
|
|||
DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum);
|
||||
if (fSum != OMV.Vector3.Zero)
|
||||
{
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum);
|
||||
_torque = fSum;
|
||||
}
|
||||
|
@ -1026,6 +1040,7 @@ public sealed class BSPrim : BSPhysObject
|
|||
OMV.Vector3 applyImpulse = impulse;
|
||||
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate()
|
||||
{
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse);
|
||||
});
|
||||
}
|
||||
|
@ -1344,7 +1359,6 @@ public sealed class BSPrim : BSPhysObject
|
|||
// Create the correct physical representation for this type of object.
|
||||
// Updates PhysBody and PhysShape with the new information.
|
||||
// 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)
|
||||
{
|
||||
// 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;
|
||||
// 'true' of the vehicle code is to log lots of details
|
||||
public bool VehicleLoggingEnabled { get; private set; }
|
||||
public bool VehiclePhysicalLoggingEnabled { get; private set; }
|
||||
public bool VehicleScaleAngularVelocityByTimestep { get; private set; }
|
||||
|
||||
#region Construction and Initialization
|
||||
public BSScene(string identifier)
|
||||
|
@ -297,6 +299,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
|||
m_physicsLoggingDoFlush = pConfig.GetBoolean("PhysicsLoggingDoFlush", false);
|
||||
// Very detailed logging for vehicle debugging
|
||||
VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
|
||||
VehiclePhysicalLoggingEnabled = pConfig.GetBoolean("VehiclePhysicalLoggingEnabled", false);
|
||||
|
||||
// Do any replacements in the parameters
|
||||
m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
|
||||
|
@ -306,6 +309,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
|||
BSMaterials.InitializeFromDefaults(Params);
|
||||
if (pConfig != null)
|
||||
{
|
||||
// Let the user add new and interesting material property values.
|
||||
BSMaterials.InitializefromParameters(pConfig);
|
||||
}
|
||||
}
|
||||
|
@ -501,7 +505,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
|||
|
||||
try
|
||||
{
|
||||
if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG
|
||||
if (VehiclePhysicalLoggingEnabled) DumpVehicles(); // DEBUG
|
||||
if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
|
||||
|
||||
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);
|
||||
DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}",
|
||||
DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount);
|
||||
if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG
|
||||
if (VehiclePhysicalLoggingEnabled) DumpVehicles(); // DEBUG
|
||||
}
|
||||
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) => { return s.m_params[0].vehicleAngularDamping; },
|
||||
(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)",
|
||||
0f,
|
||||
|
|
|
@ -126,6 +126,11 @@ public sealed class BSShapeCollection : IDisposable
|
|||
return ret;
|
||||
}
|
||||
|
||||
public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim)
|
||||
{
|
||||
return GetBodyAndShape(forceRebuild, sim, prim, null, null);
|
||||
}
|
||||
|
||||
// Track another user of a 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.
|
||||
|
@ -149,7 +154,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
// Called when releasing use of a BSBody. BSShape is handled separately.
|
||||
public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback )
|
||||
{
|
||||
if (body.ptr == IntPtr.Zero)
|
||||
if (!body.HasPhysicalBody)
|
||||
return;
|
||||
|
||||
lock (m_collectionActivityLock)
|
||||
|
@ -243,12 +248,12 @@ public sealed class BSShapeCollection : IDisposable
|
|||
// Release the usage of a shape.
|
||||
public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback)
|
||||
{
|
||||
if (shape.ptr == IntPtr.Zero)
|
||||
if (!shape.HasPhysicalShape)
|
||||
return;
|
||||
|
||||
PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate()
|
||||
{
|
||||
if (shape.ptr != IntPtr.Zero)
|
||||
if (shape.HasPhysicalShape)
|
||||
{
|
||||
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'.
|
||||
private bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
|
||||
public bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
|
||||
{
|
||||
bool ret = false;
|
||||
bool haveShape = false;
|
||||
|
@ -460,6 +465,11 @@ public sealed class BSShapeCollection : IDisposable
|
|||
&& pbs.PathScaleX == 100 && pbs.PathScaleY == 100
|
||||
&& 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}",
|
||||
prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.type);
|
||||
|
||||
|
@ -469,7 +479,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
{
|
||||
haveShape = true;
|
||||
if (forceRebuild
|
||||
|| prim.Scale != prim.Size
|
||||
|| prim.Scale != scaleOfExistingShape
|
||||
|| prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE
|
||||
)
|
||||
{
|
||||
|
@ -483,7 +493,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
{
|
||||
haveShape = true;
|
||||
if (forceRebuild
|
||||
|| prim.Scale != prim.Size
|
||||
|| prim.Scale != scaleOfExistingShape
|
||||
|| prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX
|
||||
)
|
||||
{
|
||||
|
@ -542,7 +552,6 @@ public sealed class BSShapeCollection : IDisposable
|
|||
prim.LocalID, newShape, prim.Scale);
|
||||
|
||||
// native shapes are scaled by Bullet
|
||||
prim.Scale = prim.Size;
|
||||
prim.PhysShape = newShape;
|
||||
return true;
|
||||
}
|
||||
|
@ -555,8 +564,8 @@ public sealed class BSShapeCollection : IDisposable
|
|||
ShapeData nativeShapeData = new ShapeData();
|
||||
nativeShapeData.Type = shapeType;
|
||||
nativeShapeData.ID = prim.LocalID;
|
||||
nativeShapeData.Scale = prim.Size;
|
||||
nativeShapeData.Size = prim.Size; // unneeded, I think.
|
||||
nativeShapeData.Scale = prim.Scale;
|
||||
nativeShapeData.Size = prim.Scale; // unneeded, I think.
|
||||
nativeShapeData.MeshKey = (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
|
||||
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}",
|
||||
LogHeader, prim.LocalID, shapeType);
|
||||
|
@ -590,7 +599,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
// Called at taint-time!
|
||||
private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
|
||||
{
|
||||
BulletShape newShape = new BulletShape(IntPtr.Zero);
|
||||
BulletShape newShape = new BulletShape();
|
||||
|
||||
float lod;
|
||||
System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
|
||||
|
@ -611,8 +620,6 @@ public sealed class BSShapeCollection : IDisposable
|
|||
|
||||
ReferenceShape(newShape);
|
||||
|
||||
// meshes are already scaled by the meshmerizer
|
||||
prim.Scale = new OMV.Vector3(1f, 1f, 1f);
|
||||
prim.PhysShape = newShape;
|
||||
|
||||
return true; // 'true' means a new shape has been added to this prim
|
||||
|
@ -683,8 +690,6 @@ public sealed class BSShapeCollection : IDisposable
|
|||
|
||||
ReferenceShape(newShape);
|
||||
|
||||
// hulls are already scaled by the meshmerizer
|
||||
prim.Scale = new OMV.Vector3(1f, 1f, 1f);
|
||||
prim.PhysShape = newShape;
|
||||
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);
|
||||
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.
|
||||
|
@ -860,7 +865,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim)
|
||||
{
|
||||
// If the shape was successfully created, nothing more to do
|
||||
if (newShape.ptr != IntPtr.Zero)
|
||||
if (newShape.HasPhysicalShape)
|
||||
return newShape;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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 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
|
||||
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr);
|
||||
|
||||
BulletSimAPI.SetCollisionGroupMask2(m_mapInfo.terrainBody.ptr,
|
||||
(uint)CollisionFilterGroups.TerrainGroup,
|
||||
(uint)CollisionFilterGroups.TerrainMask);
|
||||
m_mapInfo.terrainBody.collisionType = CollisionType.Terrain;
|
||||
m_mapInfo.terrainBody.ApplyCollisionMask();
|
||||
|
||||
// Make it so the terrain will not move or be considered for movement.
|
||||
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.terrainBody.ptr != IntPtr.Zero)
|
||||
if (m_mapInfo.terrainBody.HasPhysicalBody)
|
||||
{
|
||||
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr);
|
||||
// Frees both the body and the shape.
|
||||
|
|
|
@ -140,8 +140,8 @@ public sealed class BSTerrainManager
|
|||
// Ground plane does not move
|
||||
BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION);
|
||||
// Everything collides with the ground plane.
|
||||
BulletSimAPI.SetCollisionGroupMask2(m_groundPlane.ptr,
|
||||
(uint)CollisionFilterGroups.GroundPlaneGroup, (uint)CollisionFilterGroups.GroundPlaneMask);
|
||||
m_groundPlane.collisionType = CollisionType.Groundplane;
|
||||
m_groundPlane.ApplyCollisionMask();
|
||||
|
||||
// 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);
|
||||
|
@ -151,13 +151,13 @@ public sealed class BSTerrainManager
|
|||
// Release all the terrain structures we might have allocated
|
||||
public void ReleaseGroundPlaneAndTerrain()
|
||||
{
|
||||
if (m_groundPlane.ptr != IntPtr.Zero)
|
||||
if (m_groundPlane.HasPhysicalBody)
|
||||
{
|
||||
if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr))
|
||||
{
|
||||
BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_groundPlane.ptr);
|
||||
}
|
||||
m_groundPlane.ptr = IntPtr.Zero;
|
||||
m_groundPlane.Clear();
|
||||
}
|
||||
|
||||
ReleaseTerrain();
|
||||
|
|
|
@ -94,7 +94,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
|||
m_terrainShape = new BulletShape(BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr,
|
||||
indicesCount, indices, verticesCount, vertices),
|
||||
BSPhysicsShapeType.SHAPE_MESH);
|
||||
if (m_terrainShape.ptr == IntPtr.Zero)
|
||||
if (!m_terrainShape.HasPhysicalShape)
|
||||
{
|
||||
// DISASTER!!
|
||||
PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID);
|
||||
|
@ -107,7 +107,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
|||
Quaternion rot = Quaternion.Identity;
|
||||
|
||||
m_terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2( m_terrainShape.ptr, ID, pos, rot));
|
||||
if (m_terrainBody.ptr == IntPtr.Zero)
|
||||
if (!m_terrainBody.HasPhysicalBody)
|
||||
{
|
||||
// DISASTER!!
|
||||
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
|
||||
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_terrainBody.ptr);
|
||||
|
||||
BulletSimAPI.SetCollisionGroupMask2(m_terrainBody.ptr,
|
||||
(uint)CollisionFilterGroups.TerrainGroup,
|
||||
(uint)CollisionFilterGroups.TerrainMask);
|
||||
m_terrainBody.collisionType = CollisionType.Terrain;
|
||||
m_terrainBody.ApplyCollisionMask();
|
||||
|
||||
// Make it so the terrain will not move or be considered for movement.
|
||||
BulletSimAPI.ForceActivationState2(m_terrainBody.ptr, ActivationState.DISABLE_SIMULATION);
|
||||
|
@ -140,7 +139,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
|||
|
||||
public override void Dispose()
|
||||
{
|
||||
if (m_terrainBody.ptr != IntPtr.Zero)
|
||||
if (m_terrainBody.HasPhysicalBody)
|
||||
{
|
||||
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr);
|
||||
// Frees both the body and the shape.
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
|
@ -32,93 +33,6 @@ using 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, 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
|
||||
public enum ConstraintType : int
|
||||
{
|
||||
|
@ -132,44 +46,6 @@ public enum ConstraintType : int
|
|||
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)]
|
||||
public struct ConvexHull
|
||||
|
@ -362,21 +238,15 @@ public enum CollisionFlags : uint
|
|||
BS_FLOATS_ON_WATER = 1 << 11,
|
||||
BS_VEHICLE_COLLISIONS = 1 << 12,
|
||||
BS_NONE = 0,
|
||||
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
|
||||
BS_ALL = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
// Values for collisions groups and masks
|
||||
// Values f collisions groups and masks
|
||||
public enum CollisionFilterGroups : uint
|
||||
{
|
||||
// Don't use the bit definitions!! Define the use in a
|
||||
// filter/mask definition below. This way collision interactions
|
||||
// are more easily debugged.
|
||||
// are more easily found and debugged.
|
||||
BNoneGroup = 0,
|
||||
BDefaultGroup = 1 << 0,
|
||||
BStaticGroup = 1 << 1,
|
||||
|
@ -390,24 +260,8 @@ public enum CollisionFilterGroups : uint
|
|||
BTerrainGroup = 1 << 11,
|
||||
BRaycastGroup = 1 << 12,
|
||||
BSolidGroup = 1 << 13,
|
||||
BLinksetGroup = 1 << 14,
|
||||
|
||||
// The collsion filters and masked are defined in one place -- don't want them scattered
|
||||
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
|
||||
|
||||
// BLinksetGroup = xx // a linkset proper is either static or dynamic
|
||||
BLinksetChildGroup = 1 << 14,
|
||||
};
|
||||
|
||||
// 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 {
|
||||
|
||||
// ===============================================================================
|
||||
// Link back to the managed code for outputting log messages
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
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:
|
||||
=================================================
|
||||
Neb car jiggling left and right
|
||||
Happens on terrain and any other mesh object. Flat cubes are much smoother.
|
||||
Neb vehicle taking > 25ms of physics time!!
|
||||
Vehicles (Move smoothly)
|
||||
Add vehicle collisions so IsColliding is properly reported.
|
||||
Needed for banking, limitMotorUp, movementLimiting, ...
|
||||
Some vehicles should not be able to turn if no speed or off ground.
|
||||
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.
|
||||
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.
|
||||
Should vehicle angular/linear movement friction happen after all the components
|
||||
or does it only apply to the basic movement?
|
||||
|
@ -30,15 +37,14 @@ Border crossing with linked vehicle causes crash
|
|||
|
||||
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
|
||||
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.
|
||||
BSPrim.Force should set a continious force on the prim. The force should be
|
||||
applied each tick. Some limits?
|
||||
Single prim vehicles don't seem to properly vehiclize.
|
||||
Gun sending shooter flying.
|
||||
Collision margin (gap between physical objects lying on each other)
|
||||
Boundry checking (crashes related to crossing boundry)
|
||||
|
@ -51,14 +57,34 @@ Small physical objects do not interact correctly
|
|||
The chain will fall apart and pairs will dance around on ground
|
||||
Chains of 1x1x.2 will stay connected but will dance.
|
||||
Chains above 2x2x.4 are move stable and get stablier as torui get larger.
|
||||
Add material type linkage and input all the material property definitions.
|
||||
Skeleton classes and table are in the sources but are not filled or used.
|
||||
Add PID motor for avatar movement (slow to stop, ...)
|
||||
setForce should set a constant force. Different than AddImpulse.
|
||||
Implement raycast.
|
||||
Implement ShapeCollection.Dispose()
|
||||
Implement water as a plain so raycasting and collisions can happen with same.
|
||||
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.
|
||||
Test avatar walking up stairs. How does compare with SL.
|
||||
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.
|
||||
Add border extensions to terrain to help region crossings and objects leaving region.
|
||||
|
||||
Speed up creation of large physical linksets
|
||||
For instance, sitting in Neb's car (130 prims) takes several seconds to become physical
|
||||
Performance test with lots of avatars. Can BulletSim support a thousand?
|
||||
Optimize collisions in C++: only send up to the object subscribed to collisions.
|
||||
Use collision subscription and remove the collsion(A,B) and collision(B,A)
|
||||
|
@ -79,10 +103,6 @@ Avatar jump
|
|||
Performance measurement and changes to make quicker.
|
||||
Implement detailed physics stats (GetStats()).
|
||||
|
||||
Eliminate collisions between objects in a linkset. (LinksetConstraint)
|
||||
Have UserPointer point to struct with localID and linksetID?
|
||||
Objects in original linkset still collide with each other?
|
||||
|
||||
Measure performance improvement from hulls
|
||||
Test not using ghost objects for volume detect implementation.
|
||||
Performance of closures and delegates for taint processing
|
||||
|
@ -95,10 +115,16 @@ Physics Arena central pyramid: why is one side permiable?
|
|||
|
||||
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)
|
||||
Breakout code for mesh/hull/compound/native into separate BSShape* classes
|
||||
Standardize access to building and reference code.
|
||||
The skeleton classes are in the sources but are not complete or linked in.
|
||||
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 Linkset and vehicles into PropertyManagers
|
||||
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.
|
||||
LinkablePrim class? Would that simplify/centralize the linkset logic?
|
||||
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.
|
||||
Add floating motor for BS_FLOATS_ON_WATER so prim and avatar will
|
||||
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)
|
||||
Compound shapes will need the LocalID in the shapes and collision
|
||||
processing to get it from there.
|
||||
Light cycle falling over when driving (Resolution: implemented VerticalAttractor)
|
||||
Light cycle not banking (Resolution: It doesn't. Banking is roll adding yaw.)
|
||||
Package Bullet source mods for Bullet internal stats output
|
||||
(Resolution: move code into WorldData.h rather than relying on patches)
|
||||
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>
|
||||
/// Velocity of this actor.
|
||||
/// The desired velocity of this actor.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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,
|
||||
/// time to accelerate and collisions.
|
||||
/// Getting this returns the last set target. Fetch Velocity to get the current velocity.
|
||||
/// </remarks>
|
||||
protected Vector3 m_targetVelocity;
|
||||
public virtual Vector3 TargetVelocity
|
||||
{
|
||||
get { return Velocity; }
|
||||
set { Velocity = value; }
|
||||
get { return m_targetVelocity; }
|
||||
set {
|
||||
m_targetVelocity = value;
|
||||
Velocity = m_targetVelocity;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Vector3 Velocity { get; set; }
|
||||
|
|
|
@ -58,6 +58,18 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
|
|||
/// </summary>
|
||||
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>
|
||||
/// Is the script currently running?
|
||||
/// </summary>
|
||||
|
|
|
@ -94,6 +94,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
|||
private UUID m_CurrentStateHash;
|
||||
private UUID m_RegionID;
|
||||
|
||||
public int DebugLevel { get; set; }
|
||||
|
||||
public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> LineMap { get; set; }
|
||||
|
||||
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).
|
||||
if (!m_InSelfDelete)
|
||||
{
|
||||
// m_log.ErrorFormat(
|
||||
// "[SCRIPT INSTANCE]: Aborting script {0} {1} in prim {2} {3} {4} {5}",
|
||||
// ScriptName, ItemID, PrimName, ObjectID, m_InSelfDelete, DateTime.Now.Ticks);
|
||||
m_log.DebugFormat(
|
||||
"[SCRIPT INSTANCE]: Aborting unstopped script {0} {1} in prim {2}, localID {3}, timeout was {4} ms",
|
||||
ScriptName, ItemID, PrimName, LocalID, timeout);
|
||||
|
||||
workItem.Abort();
|
||||
}
|
||||
|
@ -707,19 +709,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
|||
{
|
||||
|
||||
// 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;
|
||||
|
||||
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();
|
||||
|
||||
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,
|
||||
LocalID, ItemID);
|
||||
|
||||
SceneObjectPart part = Engine.World.GetSceneObjectPart(
|
||||
LocalID);
|
||||
if (part != null)
|
||||
{
|
||||
part.SetScriptEvents(ItemID,
|
||||
|
@ -731,8 +755,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
|||
if (Engine.World.PipeEventsForScript(LocalID) ||
|
||||
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}",
|
||||
// PrimName, ScriptName, data.EventName, State);
|
||||
|
||||
|
|
|
@ -108,6 +108,24 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
private IXmlRpcRouter m_XmlRpcRouter;
|
||||
private int m_EventLimit;
|
||||
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 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_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false);
|
||||
m_SaveTime = m_ScriptConfig.GetInt("SaveInterval", 120) * 1000;
|
||||
m_WaitForEventCompletionOnScriptStop
|
||||
= m_ScriptConfig.GetInt("WaitForEventCompletionOnScriptStop", m_WaitForEventCompletionOnScriptStop);
|
||||
|
||||
m_ScriptEnginesPath = m_ScriptConfig.GetString("ScriptEnginesPath", "ScriptEngines");
|
||||
|
||||
m_Prio = ThreadPriority.BelowNormal;
|
||||
|
@ -372,7 +393,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
|
||||
MainConsole.Instance.Commands.AddCommand(
|
||||
"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.",
|
||||
HandleShowScripts);
|
||||
|
||||
|
@ -391,22 +412,30 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
MainConsole.Instance.Commands.AddCommand(
|
||||
"Scripts", false, "scripts resume", "scripts resume [<script-item-uuid>]", "Resumes all suspended scripts",
|
||||
"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.",
|
||||
(module, cmdparams) => HandleScriptsAction(cmdparams, HandleResumeScript));
|
||||
|
||||
MainConsole.Instance.Commands.AddCommand(
|
||||
"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.",
|
||||
(module, cmdparams) => HandleScriptsAction(cmdparams, HandleStopScript));
|
||||
|
||||
MainConsole.Instance.Commands.AddCommand(
|
||||
"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.",
|
||||
(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(
|
||||
// "Debug", false, "debug xengine", "debug xengine [<level>]",
|
||||
// "Turn on detailed xengine debugging.",
|
||||
|
@ -415,6 +444,41 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
// 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>
|
||||
/// Change debug level
|
||||
/// </summary>
|
||||
|
@ -486,7 +550,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -610,6 +674,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
sb.AppendFormat("Queued events : {0}\n", instance.EventsQueued);
|
||||
sb.AppendFormat("Processed events : {0}\n", instance.EventsProcessed);
|
||||
sb.AppendFormat("Item UUID : {0}\n", instance.ItemID);
|
||||
sb.AppendFormat("Asset UUID : {0}\n", instance.AssetID);
|
||||
sb.AppendFormat("Containing part name: {0}\n", instance.PrimName);
|
||||
sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID);
|
||||
sb.AppendFormat("Position : {0}\n", sop.AbsolutePosition);
|
||||
|
@ -1375,9 +1440,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
lockScriptsForWrite(false);
|
||||
instance.ClearQueue();
|
||||
|
||||
// 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);
|
||||
instance.Stop(m_WaitForEventCompletionOnScriptStop);
|
||||
|
||||
// bool objectRemoved = false;
|
||||
|
||||
|
@ -1735,17 +1798,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
public void StopScript(UUID itemID)
|
||||
{
|
||||
IScriptInstance instance = GetInstance(itemID);
|
||||
|
||||
if (instance != null)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
instance.Stop(m_WaitForEventCompletionOnScriptStop);
|
||||
else
|
||||
{
|
||||
m_runFlags.AddOrUpdate(itemID, false, 240);
|
||||
}
|
||||
}
|
||||
|
||||
public DetectParams GetDetectParams(UUID itemID, int idx)
|
||||
{
|
||||
|
|
|
@ -94,8 +94,6 @@ namespace OpenSim.Region.UserStatistics
|
|||
if (!enabled)
|
||||
return;
|
||||
|
||||
AddEventHandlers();
|
||||
|
||||
if (Util.IsWindows())
|
||||
Util.LoadArchSpecificWindowsDll("sqlite3.dll");
|
||||
|
||||
|
@ -143,10 +141,14 @@ namespace OpenSim.Region.UserStatistics
|
|||
lock (m_scenes)
|
||||
{
|
||||
m_scenes.Add(scene);
|
||||
if (m_simstatsCounters.ContainsKey(scene.RegionInfo.RegionID))
|
||||
m_simstatsCounters.Remove(scene.RegionInfo.RegionID);
|
||||
updateLogMod = m_scenes.Count * 2;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -157,6 +159,15 @@ namespace OpenSim.Region.UserStatistics
|
|||
|
||||
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()
|
||||
|
@ -187,9 +198,7 @@ namespace OpenSim.Region.UserStatistics
|
|||
private void ReceiveClassicSimStatsPacket(SimStats stats)
|
||||
{
|
||||
if (!enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -198,10 +207,17 @@ namespace OpenSim.Region.UserStatistics
|
|||
if (concurrencyCounter > 0 || System.Environment.TickCount - lastHit > 30000)
|
||||
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);
|
||||
if (updateLogCounter > 10000) updateLogCounter = 1;
|
||||
|
||||
if (updateLogCounter > 10000)
|
||||
updateLogCounter = 1;
|
||||
}
|
||||
|
||||
USimStatsData ss = m_simstatsCounters[stats.RegionUUID];
|
||||
|
@ -211,6 +227,7 @@ namespace OpenSim.Region.UserStatistics
|
|||
ss.ConsumeSimStats(stats);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -89,12 +89,39 @@ namespace OpenSim.Server.Base
|
|||
Config = config;
|
||||
|
||||
Registry = new AddinRegistry(registryPath, ".");
|
||||
suppress_console_output_(true);
|
||||
AddinManager.Initialize(registryPath);
|
||||
suppress_console_output_(false);
|
||||
AddinManager.Registry.Update();
|
||||
CommandManager commandmanager = new CommandManager(Registry);
|
||||
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)
|
||||
{
|
||||
IRobustConnector connector = (IRobustConnector)args.ExtensionObject;
|
||||
|
@ -112,8 +139,7 @@ namespace OpenSim.Server.Base
|
|||
if (a.AddinFile.Contains(Registry.DefaultAddinsFolder))
|
||||
{
|
||||
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
|
||||
{
|
||||
m_log.InfoFormat("[SERVER]: Adding {0} from ./bin", a.Name);
|
||||
|
@ -195,14 +221,24 @@ namespace OpenSim.Server.Base
|
|||
//if (dllName == string.Empty)
|
||||
// Util.PrintCallStack();
|
||||
|
||||
string[] parts = dllName.Split(new char[] {':'});
|
||||
|
||||
dllName = parts[0];
|
||||
|
||||
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)
|
||||
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);
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -32,9 +32,15 @@
|
|||
<appender-ref ref="LogFileAppender" />
|
||||
</root>
|
||||
|
||||
<!-- Independently control logging level for XEngine -->
|
||||
<logger name="OpenSim.Region.ScriptEngine.XEngine">
|
||||
<level value="INFO"/>
|
||||
</logger>
|
||||
|
||||
<!-- Independently control logging level for per region module loading -->
|
||||
<logger name="OpenSim.ApplicationPlugins.RegionModulesController.RegionModulesControllerPlugin">
|
||||
<level value="INFO"/>
|
||||
</logger>
|
||||
|
||||
</log4net>
|
||||
</configuration>
|
||||
|
|
|
@ -1364,6 +1364,10 @@
|
|||
; If a script overruns it's event limit, kill the script?
|
||||
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
|
||||
ScriptDelayFactor = 1.0
|
||||
|
||||
|
|
|
@ -22,6 +22,18 @@
|
|||
; *
|
||||
[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]
|
||||
|
||||
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:
|
||||
;; 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
|
||||
; * server instance, if none is specified above
|
||||
; *
|
||||
|
|
|
@ -14,6 +14,19 @@
|
|||
; *
|
||||
[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]
|
||||
AssetServiceConnector = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector"
|
||||
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"
|
||||
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
|
||||
; * server instance, if none is specified above
|
||||
; *
|
||||
|
|
Loading…
Reference in New Issue