Merge branch 'master' into careminster
Conflicts: OpenSim/Data/MySQL/MySQLAssetData.cs OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.csavinationmerge
commit
7cf377fff0
|
@ -101,6 +101,7 @@ what it is today.
|
||||||
* jhurliman
|
* jhurliman
|
||||||
* John R Sohn (XenReborn)
|
* John R Sohn (XenReborn)
|
||||||
* jonc
|
* jonc
|
||||||
|
* Jon Cundill
|
||||||
* Junta Kohime
|
* Junta Kohime
|
||||||
* Kayne
|
* Kayne
|
||||||
* Kevin Cozens
|
* Kevin Cozens
|
||||||
|
|
|
@ -142,7 +142,8 @@ namespace OpenSim.Data.MySQL
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
m_log.Error("[ASSETS DB]: MySql failure fetching asset " + assetID + ": " + e.Message);
|
m_log.Error(
|
||||||
|
string.Format("[ASSETS DB]: MySql failure fetching asset {0}. Exception ", assetID), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -243,10 +244,11 @@ namespace OpenSim.Data.MySQL
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
m_log.ErrorFormat(
|
m_log.Error(
|
||||||
"[ASSETS DB]: " +
|
string.Format(
|
||||||
"MySql failure updating access_time for asset {0} with name {1}" + Environment.NewLine + e.ToString()
|
"[ASSETS DB]: Failure updating access_time for asset {0} with name {1}. Exception ",
|
||||||
+ Environment.NewLine + "Attempting reconnection", asset.FullID, asset.Name);
|
asset.FullID, asset.Name),
|
||||||
|
e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -286,8 +288,8 @@ namespace OpenSim.Data.MySQL
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
m_log.ErrorFormat(
|
m_log.Error(
|
||||||
"[ASSETS DB]: MySql failure fetching asset {0}" + Environment.NewLine + e.ToString(), uuid);
|
string.Format("[ASSETS DB]: MySql failure fetching asset {0}. Exception ", uuid), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,7 +348,11 @@ namespace OpenSim.Data.MySQL
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
m_log.Error("[ASSETS DB]: MySql failure fetching asset set" + Environment.NewLine + e.ToString());
|
m_log.Error(
|
||||||
|
string.Format(
|
||||||
|
"[ASSETS DB]: MySql failure fetching asset set from {0}, count {1}. Exception ",
|
||||||
|
start, count),
|
||||||
|
e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,11 @@ namespace OpenSim.Framework.Servers
|
||||||
|
|
||||||
protected void CreatePIDFile(string path)
|
protected void CreatePIDFile(string path)
|
||||||
{
|
{
|
||||||
|
if (File.Exists(path))
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[SERVER BASE]: Previous pid file {0} still exists on startup. Possibly previously unclean shutdown.",
|
||||||
|
path);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
|
string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
|
||||||
|
|
|
@ -358,7 +358,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
bool asAttachment)
|
bool asAttachment)
|
||||||
{
|
{
|
||||||
CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero);
|
CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero);
|
||||||
Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>();
|
// Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>();
|
||||||
|
|
||||||
foreach (SceneObjectGroup objectGroup in objlist)
|
foreach (SceneObjectGroup objectGroup in objlist)
|
||||||
{
|
{
|
||||||
|
@ -379,7 +379,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
objectGroup.AbsolutePosition.Z);
|
objectGroup.AbsolutePosition.Z);
|
||||||
|
|
||||||
Quaternion inventoryStoredRotation = objectGroup.GroupRotation;
|
Quaternion inventoryStoredRotation = objectGroup.GroupRotation;
|
||||||
originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition;
|
//originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition;
|
||||||
|
|
||||||
// Restore attachment data after trip through the sim
|
// Restore attachment data after trip through the sim
|
||||||
if (objectGroup.RootPart.AttachPoint > 0)
|
if (objectGroup.RootPart.AttachPoint > 0)
|
||||||
|
@ -418,9 +418,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
else
|
else
|
||||||
itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment);
|
itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment);
|
||||||
|
|
||||||
// Restore the position of each group now that it has been stored to inventory.
|
// // Restore the position of each group now that it has been stored to inventory.
|
||||||
foreach (SceneObjectGroup objectGroup in objlist)
|
// foreach (SceneObjectGroup objectGroup in objlist)
|
||||||
objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID];
|
// objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID];
|
||||||
|
|
||||||
InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID);
|
InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID);
|
||||||
|
|
||||||
|
@ -866,7 +866,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, attachment))
|
if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
for (int i = 0; i < objlist.Count; i++)
|
for (int i = 0; i < objlist.Count; i++)
|
||||||
|
@ -965,10 +965,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
/// <param name="item"></param>
|
/// <param name="item"></param>
|
||||||
/// <param name="objlist"></param>
|
/// <param name="objlist"></param>
|
||||||
/// <param name="pos"></param>
|
/// <param name="pos"></param>
|
||||||
|
/// <param name="veclist">
|
||||||
|
/// List of vector position adjustments for a coalesced objects. For ordinary objects
|
||||||
|
/// this list will contain just Vector3.Zero. The order of adjustments must match the order of objlist
|
||||||
|
/// </param>
|
||||||
/// <param name="isAttachment"></param>
|
/// <param name="isAttachment"></param>
|
||||||
/// <returns>true if we can processed with rezzing, false if we need to abort</returns>
|
/// <returns>true if we can processed with rezzing, false if we need to abort</returns>
|
||||||
private bool DoPreRezWhenFromItem(
|
private bool DoPreRezWhenFromItem(
|
||||||
IClientAPI remoteClient, InventoryItemBase item, List<SceneObjectGroup> objlist, Vector3 pos, bool isAttachment)
|
IClientAPI remoteClient, InventoryItemBase item, List<SceneObjectGroup> objlist,
|
||||||
|
Vector3 pos, List<Vector3> veclist, bool isAttachment)
|
||||||
{
|
{
|
||||||
UUID fromUserInventoryItemId = UUID.Zero;
|
UUID fromUserInventoryItemId = UUID.Zero;
|
||||||
|
|
||||||
|
@ -991,28 +996,29 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int primcount = 0;
|
for (int i = 0; i < objlist.Count; i++)
|
||||||
foreach (SceneObjectGroup g in objlist)
|
|
||||||
primcount += g.PrimCount;
|
|
||||||
|
|
||||||
if (!m_Scene.Permissions.CanRezObject(
|
|
||||||
primcount, remoteClient.AgentId, pos)
|
|
||||||
&& !isAttachment)
|
|
||||||
{
|
{
|
||||||
// The client operates in no fail mode. It will
|
SceneObjectGroup g = objlist[i];
|
||||||
// have already removed the item from the folder
|
|
||||||
// if it's no copy.
|
|
||||||
// Put it back if it's not an attachment
|
|
||||||
//
|
|
||||||
if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment))
|
|
||||||
remoteClient.SendBulkUpdateInventory(item);
|
|
||||||
|
|
||||||
ILandObject land = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y);
|
if (!m_Scene.Permissions.CanRezObject(
|
||||||
remoteClient.SendAlertMessage(string.Format(
|
g.PrimCount, remoteClient.AgentId, pos + veclist[i])
|
||||||
"Can't rez object '{0}' at <{1:F3}, {2:F3}, {3:F3}> on parcel '{4}' in region {5}.",
|
&& !isAttachment)
|
||||||
item.Name, pos.X, pos.Y, pos.Z, land != null ? land.LandData.Name : "Unknown", m_Scene.RegionInfo.RegionName));
|
{
|
||||||
|
// The client operates in no fail mode. It will
|
||||||
|
// have already removed the item from the folder
|
||||||
|
// if it's no copy.
|
||||||
|
// Put it back if it's not an attachment
|
||||||
|
//
|
||||||
|
if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment))
|
||||||
|
remoteClient.SendBulkUpdateInventory(item);
|
||||||
|
|
||||||
return false;
|
ILandObject land = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y);
|
||||||
|
remoteClient.SendAlertMessage(string.Format(
|
||||||
|
"Can't rez object '{0}' at <{1:F3}, {2:F3}, {3:F3}> on parcel '{4}' in region {5}.",
|
||||||
|
item.Name, pos.X, pos.Y, pos.Z, land != null ? land.LandData.Name : "Unknown", m_Scene.Name));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < objlist.Count; i++)
|
for (int i = 0; i < objlist.Count; i++)
|
||||||
|
|
|
@ -412,7 +412,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
//public bool HttpVerboseThrottle = true; // not implemented
|
//public bool HttpVerboseThrottle = true; // not implemented
|
||||||
public List<string> HttpCustomHeaders = null;
|
public List<string> HttpCustomHeaders = null;
|
||||||
public bool HttpPragmaNoCache = true;
|
public bool HttpPragmaNoCache = true;
|
||||||
private Thread httpThread;
|
|
||||||
|
|
||||||
// Request info
|
// Request info
|
||||||
private UUID _itemID;
|
private UUID _itemID;
|
||||||
|
|
|
@ -1453,6 +1453,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions
|
||||||
|
|
||||||
bool permission = false;
|
bool permission = false;
|
||||||
|
|
||||||
|
// m_log.DebugFormat("[PERMISSIONS MODULE]: Checking rez object at {0} in {1}", objectPosition, m_scene.Name);
|
||||||
|
|
||||||
ILandObject land = m_scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y);
|
ILandObject land = m_scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y);
|
||||||
if (land == null) return false;
|
if (land == null) return false;
|
||||||
|
|
||||||
|
|
|
@ -5647,12 +5647,12 @@ Environment.Exit(1);
|
||||||
List<SceneObjectGroup> objects,
|
List<SceneObjectGroup> objects,
|
||||||
out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
|
out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
|
||||||
{
|
{
|
||||||
minX = 256;
|
minX = float.MaxValue;
|
||||||
maxX = -256;
|
maxX = float.MinValue;
|
||||||
minY = 256;
|
minY = float.MaxValue;
|
||||||
maxY = -256;
|
maxY = float.MinValue;
|
||||||
minZ = 8192;
|
minZ = float.MaxValue;
|
||||||
maxZ = -256;
|
maxZ = float.MinValue;
|
||||||
|
|
||||||
List<Vector3> offsets = new List<Vector3>();
|
List<Vector3> offsets = new List<Vector3>();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,285 @@
|
||||||
|
/*
|
||||||
|
* 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.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
|
||||||
|
using OMV = OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
|
{
|
||||||
|
public class BSActorAvatarMove : BSActor
|
||||||
|
{
|
||||||
|
BSVMotor m_velocityMotor;
|
||||||
|
|
||||||
|
public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName)
|
||||||
|
: base(physicsScene, pObj, actorName)
|
||||||
|
{
|
||||||
|
m_velocityMotor = null;
|
||||||
|
m_physicsScene.DetailLog("{0},BSActorAvatarMove,constructor", m_controllingPrim.LocalID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// BSActor.isActive
|
||||||
|
public override bool isActive
|
||||||
|
{
|
||||||
|
get { return Enabled && m_controllingPrim.IsPhysicallyActive; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release any connections and resources used by the actor.
|
||||||
|
// BSActor.Dispose()
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
Enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when physical parameters (properties set in Bullet) need to be re-applied.
|
||||||
|
// Called at taint-time.
|
||||||
|
// BSActor.Refresh()
|
||||||
|
public override void Refresh()
|
||||||
|
{
|
||||||
|
m_physicsScene.DetailLog("{0},BSActorAvatarMove,refresh", m_controllingPrim.LocalID);
|
||||||
|
|
||||||
|
// If the object is physically active, add the hoverer prestep action
|
||||||
|
if (isActive)
|
||||||
|
{
|
||||||
|
ActivateAvatarMove();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DeactivateAvatarMove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
|
||||||
|
// Register a prestep action to restore physical requirements before the next simulation step.
|
||||||
|
// Called at taint-time.
|
||||||
|
// BSActor.RemoveBodyDependencies()
|
||||||
|
public override void RemoveBodyDependencies()
|
||||||
|
{
|
||||||
|
// Nothing to do for the hoverer since it is all software at pre-step action time.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usually called when target velocity changes to set the current velocity and the target
|
||||||
|
// into the movement motor.
|
||||||
|
public void SetVelocityAndTarget(OMV.Vector3 vel, OMV.Vector3 targ, bool inTaintTime)
|
||||||
|
{
|
||||||
|
m_physicsScene.TaintedObject(inTaintTime, "BSActorAvatarMove.setVelocityAndTarget", delegate()
|
||||||
|
{
|
||||||
|
if (m_velocityMotor != null)
|
||||||
|
{
|
||||||
|
m_velocityMotor.Reset();
|
||||||
|
m_velocityMotor.SetTarget(targ);
|
||||||
|
m_velocityMotor.SetCurrent(vel);
|
||||||
|
m_velocityMotor.Enabled = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a hover motor has not been created, create one and start the hovering.
|
||||||
|
private void ActivateAvatarMove()
|
||||||
|
{
|
||||||
|
if (m_velocityMotor == null)
|
||||||
|
{
|
||||||
|
// Infinite decay and timescale values so motor only changes current to target values.
|
||||||
|
m_velocityMotor = new BSVMotor("BSCharacter.Velocity",
|
||||||
|
0.2f, // time scale
|
||||||
|
BSMotor.Infinite, // decay time scale
|
||||||
|
BSMotor.InfiniteVector, // friction timescale
|
||||||
|
1f // efficiency
|
||||||
|
);
|
||||||
|
// _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
|
||||||
|
SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity, true /* inTaintTime */);
|
||||||
|
|
||||||
|
m_physicsScene.BeforeStep += Mover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DeactivateAvatarMove()
|
||||||
|
{
|
||||||
|
if (m_velocityMotor != null)
|
||||||
|
{
|
||||||
|
m_physicsScene.BeforeStep -= Mover;
|
||||||
|
m_velocityMotor = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called just before the simulation step. Update the vertical position for hoverness.
|
||||||
|
private void Mover(float timeStep)
|
||||||
|
{
|
||||||
|
// Don't do movement while the object is selected.
|
||||||
|
if (!isActive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// TODO: Decide if the step parameters should be changed depending on the avatar's
|
||||||
|
// state (flying, colliding, ...). There is code in ODE to do this.
|
||||||
|
|
||||||
|
// COMMENTARY: when the user is making the avatar walk, except for falling, the velocity
|
||||||
|
// specified for the avatar is the one that should be used. For falling, if the avatar
|
||||||
|
// is not flying and is not colliding then it is presumed to be falling and the Z
|
||||||
|
// component is not fooled with (thus allowing gravity to do its thing).
|
||||||
|
// When the avatar is standing, though, the user has specified a velocity of zero and
|
||||||
|
// the avatar should be standing. But if the avatar is pushed by something in the world
|
||||||
|
// (raising elevator platform, moving vehicle, ...) the avatar should be allowed to
|
||||||
|
// move. Thus, the velocity cannot be forced to zero. The problem is that small velocity
|
||||||
|
// errors can creap in and the avatar will slowly float off in some direction.
|
||||||
|
// So, the problem is that, when an avatar is standing, we cannot tell creaping error
|
||||||
|
// from real pushing.
|
||||||
|
// The code below uses whether the collider is static or moving to decide whether to zero motion.
|
||||||
|
|
||||||
|
m_velocityMotor.Step(timeStep);
|
||||||
|
m_controllingPrim.IsStationary = false;
|
||||||
|
|
||||||
|
// If we're not supposed to be moving, make sure things are zero.
|
||||||
|
if (m_velocityMotor.ErrorIsZero() && m_velocityMotor.TargetValue == OMV.Vector3.Zero)
|
||||||
|
{
|
||||||
|
// The avatar shouldn't be moving
|
||||||
|
m_velocityMotor.Zero();
|
||||||
|
|
||||||
|
if (m_controllingPrim.IsColliding)
|
||||||
|
{
|
||||||
|
// If we are colliding with a stationary object, presume we're standing and don't move around
|
||||||
|
if (!m_controllingPrim.ColliderIsMoving)
|
||||||
|
{
|
||||||
|
m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", m_controllingPrim.LocalID);
|
||||||
|
m_controllingPrim.IsStationary = true;
|
||||||
|
m_controllingPrim.ZeroMotion(true /* inTaintTime */);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Standing has more friction on the ground
|
||||||
|
if (m_controllingPrim.Friction != BSParam.AvatarStandingFriction)
|
||||||
|
{
|
||||||
|
m_controllingPrim.Friction = BSParam.AvatarStandingFriction;
|
||||||
|
m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_controllingPrim.Flying)
|
||||||
|
{
|
||||||
|
// Flying and not collising and velocity nearly zero.
|
||||||
|
m_controllingPrim.ZeroMotion(true /* inTaintTime */);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}",
|
||||||
|
m_controllingPrim.LocalID, m_velocityMotor.TargetValue, m_controllingPrim.IsColliding);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Supposed to be moving.
|
||||||
|
OMV.Vector3 stepVelocity = m_velocityMotor.CurrentValue;
|
||||||
|
|
||||||
|
if (m_controllingPrim.Friction != BSParam.AvatarFriction)
|
||||||
|
{
|
||||||
|
// Probably starting up walking. Set friction to moving friction.
|
||||||
|
m_controllingPrim.Friction = BSParam.AvatarFriction;
|
||||||
|
m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If falling, we keep the world's downward vector no matter what the other axis specify.
|
||||||
|
// The check for RawVelocity.Z < 0 makes jumping work (temporary upward force).
|
||||||
|
if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding)
|
||||||
|
{
|
||||||
|
if (m_controllingPrim.RawVelocity.Z < 0)
|
||||||
|
stepVelocity.Z = m_controllingPrim.RawVelocity.Z;
|
||||||
|
// DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force.
|
||||||
|
OMV.Vector3 moveForce = (stepVelocity - m_controllingPrim.RawVelocity) * m_controllingPrim.Mass;
|
||||||
|
|
||||||
|
// Should we check for move force being small and forcing velocity to zero?
|
||||||
|
|
||||||
|
// Add special movement force to allow avatars to walk up stepped surfaces.
|
||||||
|
moveForce += WalkUpStairs();
|
||||||
|
|
||||||
|
m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}",
|
||||||
|
m_controllingPrim.LocalID, stepVelocity, m_controllingPrim.RawVelocity, m_controllingPrim.Mass, moveForce);
|
||||||
|
m_physicsScene.PE.ApplyCentralImpulse(m_controllingPrim.PhysBody, moveForce);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decide if the character is colliding with a low object and compute a force to pop the
|
||||||
|
// avatar up so it can walk up and over the low objects.
|
||||||
|
private OMV.Vector3 WalkUpStairs()
|
||||||
|
{
|
||||||
|
OMV.Vector3 ret = OMV.Vector3.Zero;
|
||||||
|
|
||||||
|
// This test is done if moving forward, not flying and is colliding with something.
|
||||||
|
// DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}",
|
||||||
|
// LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count);
|
||||||
|
if (m_controllingPrim.IsColliding && !m_controllingPrim.Flying && m_controllingPrim.TargetVelocitySpeed > 0.1f /* && ForwardSpeed < 0.1f */)
|
||||||
|
{
|
||||||
|
// The range near the character's feet where we will consider stairs
|
||||||
|
float nearFeetHeightMin = m_controllingPrim.RawPosition.Z - (m_controllingPrim.Size.Z / 2f) + 0.05f;
|
||||||
|
float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight;
|
||||||
|
|
||||||
|
// Look for a collision point that is near the character's feet and is oriented the same as the charactor is
|
||||||
|
foreach (KeyValuePair<uint, ContactPoint> kvp in m_controllingPrim.CollisionsLastTick.m_objCollisionList)
|
||||||
|
{
|
||||||
|
// Don't care about collisions with the terrain
|
||||||
|
if (kvp.Key > m_physicsScene.TerrainManager.HighestTerrainID)
|
||||||
|
{
|
||||||
|
OMV.Vector3 touchPosition = kvp.Value.Position;
|
||||||
|
// DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}",
|
||||||
|
// LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition);
|
||||||
|
if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax)
|
||||||
|
{
|
||||||
|
// This contact is within the 'near the feet' range.
|
||||||
|
// The normal should be our contact point to the object so it is pointing away
|
||||||
|
// thus the difference between our facing orientation and the normal should be small.
|
||||||
|
OMV.Vector3 directionFacing = OMV.Vector3.UnitX * m_controllingPrim.RawOrientation;
|
||||||
|
OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal);
|
||||||
|
float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal));
|
||||||
|
if (diff < BSParam.AvatarStepApproachFactor)
|
||||||
|
{
|
||||||
|
// Found the stairs contact point. Push up a little to raise the character.
|
||||||
|
float upForce = (touchPosition.Z - nearFeetHeightMin) * m_controllingPrim.Mass * BSParam.AvatarStepForceFactor;
|
||||||
|
ret = new OMV.Vector3(0f, 0f, upForce);
|
||||||
|
|
||||||
|
// Also move the avatar up for the new height
|
||||||
|
OMV.Vector3 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight / 2f);
|
||||||
|
m_controllingPrim.ForcePosition = m_controllingPrim.RawPosition + displacement;
|
||||||
|
}
|
||||||
|
m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},faceDir={3},norm={4},diff={5},ret={6}",
|
||||||
|
m_controllingPrim.LocalID, touchPosition, nearFeetHeightMin, directionFacing, touchNormal, diff, ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,174 @@
|
||||||
|
/*
|
||||||
|
* 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.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
|
||||||
|
using OMV = OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
|
{
|
||||||
|
public class BSActorHover : BSActor
|
||||||
|
{
|
||||||
|
private BSFMotor m_hoverMotor;
|
||||||
|
|
||||||
|
public BSActorHover(BSScene physicsScene, BSPhysObject pObj, string actorName)
|
||||||
|
: base(physicsScene, pObj, actorName)
|
||||||
|
{
|
||||||
|
m_hoverMotor = null;
|
||||||
|
m_physicsScene.DetailLog("{0},BSActorHover,constructor", m_controllingPrim.LocalID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// BSActor.isActive
|
||||||
|
public override bool isActive
|
||||||
|
{
|
||||||
|
get { return Enabled; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release any connections and resources used by the actor.
|
||||||
|
// BSActor.Dispose()
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
Enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when physical parameters (properties set in Bullet) need to be re-applied.
|
||||||
|
// Called at taint-time.
|
||||||
|
// BSActor.Refresh()
|
||||||
|
public override void Refresh()
|
||||||
|
{
|
||||||
|
m_physicsScene.DetailLog("{0},BSActorHover,refresh", m_controllingPrim.LocalID);
|
||||||
|
|
||||||
|
// If not active any more, turn me off
|
||||||
|
if (!m_controllingPrim.HoverActive)
|
||||||
|
{
|
||||||
|
SetEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the object is physically active, add the hoverer prestep action
|
||||||
|
if (isActive)
|
||||||
|
{
|
||||||
|
ActivateHover();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DeactivateHover();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
|
||||||
|
// Register a prestep action to restore physical requirements before the next simulation step.
|
||||||
|
// Called at taint-time.
|
||||||
|
// BSActor.RemoveBodyDependencies()
|
||||||
|
public override void RemoveBodyDependencies()
|
||||||
|
{
|
||||||
|
// Nothing to do for the hoverer since it is all software at pre-step action time.
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a hover motor has not been created, create one and start the hovering.
|
||||||
|
private void ActivateHover()
|
||||||
|
{
|
||||||
|
if (m_hoverMotor == null)
|
||||||
|
{
|
||||||
|
// Turning the target on
|
||||||
|
m_hoverMotor = new BSFMotor("BSActorHover",
|
||||||
|
m_controllingPrim.HoverTau, // timeScale
|
||||||
|
BSMotor.Infinite, // decay time scale
|
||||||
|
BSMotor.Infinite, // friction timescale
|
||||||
|
1f // efficiency
|
||||||
|
);
|
||||||
|
m_hoverMotor.SetTarget(ComputeCurrentHoverHeight());
|
||||||
|
m_hoverMotor.SetCurrent(m_controllingPrim.RawPosition.Z);
|
||||||
|
m_hoverMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG so motor will output detail log messages.
|
||||||
|
|
||||||
|
m_physicsScene.BeforeStep += Hoverer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DeactivateHover()
|
||||||
|
{
|
||||||
|
if (m_hoverMotor != null)
|
||||||
|
{
|
||||||
|
m_physicsScene.BeforeStep -= Hoverer;
|
||||||
|
m_hoverMotor = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called just before the simulation step. Update the vertical position for hoverness.
|
||||||
|
private void Hoverer(float timeStep)
|
||||||
|
{
|
||||||
|
// Don't do hovering while the object is selected.
|
||||||
|
if (!isActive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_hoverMotor.SetCurrent(m_controllingPrim.RawPosition.Z);
|
||||||
|
m_hoverMotor.SetTarget(ComputeCurrentHoverHeight());
|
||||||
|
float targetHeight = m_hoverMotor.Step(timeStep);
|
||||||
|
|
||||||
|
// 'targetHeight' is where we'd like the Z of the prim to be at this moment.
|
||||||
|
// Compute the amount of force to push us there.
|
||||||
|
float moveForce = (targetHeight - m_controllingPrim.RawPosition.Z) * m_controllingPrim.RawMass;
|
||||||
|
// Undo anything the object thinks it's doing at the moment
|
||||||
|
moveForce = -m_controllingPrim.RawVelocity.Z * m_controllingPrim.Mass;
|
||||||
|
|
||||||
|
m_physicsScene.PE.ApplyCentralImpulse(m_controllingPrim.PhysBody, new OMV.Vector3(0f, 0f, moveForce));
|
||||||
|
m_physicsScene.DetailLog("{0},BSPrim.Hover,move,targHt={1},moveForce={2},mass={3}",
|
||||||
|
m_controllingPrim.LocalID, targetHeight, moveForce, m_controllingPrim.RawMass);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Based on current position, determine what we should be hovering at now.
|
||||||
|
// Must recompute often. What if we walked offa cliff>
|
||||||
|
private float ComputeCurrentHoverHeight()
|
||||||
|
{
|
||||||
|
float ret = m_controllingPrim.HoverHeight;
|
||||||
|
float groundHeight = m_physicsScene.TerrainManager.GetTerrainHeightAtXYZ(m_controllingPrim.RawPosition);
|
||||||
|
|
||||||
|
switch (m_controllingPrim.HoverType)
|
||||||
|
{
|
||||||
|
case PIDHoverType.Ground:
|
||||||
|
ret = groundHeight + m_controllingPrim.HoverHeight;
|
||||||
|
break;
|
||||||
|
case PIDHoverType.GroundAndWater:
|
||||||
|
float waterHeight = m_physicsScene.TerrainManager.GetWaterLevelAtXYZ(m_controllingPrim.RawPosition);
|
||||||
|
if (groundHeight > waterHeight)
|
||||||
|
{
|
||||||
|
ret = groundHeight + m_controllingPrim.HoverHeight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = waterHeight + m_controllingPrim.HoverHeight;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,11 +36,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
{
|
{
|
||||||
public class BSActorLockAxis : BSActor
|
public class BSActorLockAxis : BSActor
|
||||||
{
|
{
|
||||||
bool TryExperimentalLockAxisCode = true;
|
|
||||||
BSConstraint LockAxisConstraint = null;
|
BSConstraint LockAxisConstraint = null;
|
||||||
|
|
||||||
public BSActorLockAxis(BSScene physicsScene, BSPhysObject pObj, string actorName)
|
public BSActorLockAxis(BSScene physicsScene, BSPhysObject pObj, string actorName)
|
||||||
: base(physicsScene, pObj,actorName)
|
: base(physicsScene, pObj, actorName)
|
||||||
{
|
{
|
||||||
m_physicsScene.DetailLog("{0},BSActorLockAxis,constructor", m_controllingPrim.LocalID);
|
m_physicsScene.DetailLog("{0},BSActorLockAxis,constructor", m_controllingPrim.LocalID);
|
||||||
LockAxisConstraint = null;
|
LockAxisConstraint = null;
|
||||||
|
@ -69,18 +68,13 @@ public class BSActorLockAxis : BSActor
|
||||||
// If all the axis are free, we don't need to exist
|
// If all the axis are free, we don't need to exist
|
||||||
if (m_controllingPrim.LockedAxis == m_controllingPrim.LockedAxisFree)
|
if (m_controllingPrim.LockedAxis == m_controllingPrim.LockedAxisFree)
|
||||||
{
|
{
|
||||||
m_physicsScene.DetailLog("{0},BSActorLockAxis,refresh,allAxisFree,removing={1}", m_controllingPrim.LocalID, ActorName);
|
Enabled = false;
|
||||||
m_controllingPrim.PhysicalActors.RemoveAndRelease(ActorName);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the object is physically active, add the axis locking constraint
|
// If the object is physically active, add the axis locking constraint
|
||||||
if (Enabled
|
if (isActive)
|
||||||
&& m_controllingPrim.IsPhysicallyActive
|
|
||||||
&& TryExperimentalLockAxisCode
|
|
||||||
&& m_controllingPrim.LockedAxis != m_controllingPrim.LockedAxisFree)
|
|
||||||
{
|
{
|
||||||
if (LockAxisConstraint == null)
|
AddAxisLockConstraint();
|
||||||
AddAxisLockConstraint();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -99,7 +93,7 @@ public class BSActorLockAxis : BSActor
|
||||||
// If a constraint is set up, remove it from the physical scene
|
// If a constraint is set up, remove it from the physical scene
|
||||||
RemoveAxisLockConstraint();
|
RemoveAxisLockConstraint();
|
||||||
// Schedule a call before the next simulation step to restore the constraint.
|
// Schedule a call before the next simulation step to restore the constraint.
|
||||||
m_physicsScene.PostTaintObject(m_controllingPrim.LockedAxisActorName, m_controllingPrim.LocalID, delegate()
|
m_physicsScene.PostTaintObject("BSActorLockAxis:" + ActorName, m_controllingPrim.LocalID, delegate()
|
||||||
{
|
{
|
||||||
Refresh();
|
Refresh();
|
||||||
});
|
});
|
||||||
|
@ -108,58 +102,61 @@ public class BSActorLockAxis : BSActor
|
||||||
|
|
||||||
private void AddAxisLockConstraint()
|
private void AddAxisLockConstraint()
|
||||||
{
|
{
|
||||||
// Lock that axis by creating a 6DOF constraint that has one end in the world and
|
if (LockAxisConstraint == null)
|
||||||
// the other in the object.
|
|
||||||
// http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=20817
|
|
||||||
// http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=26380
|
|
||||||
|
|
||||||
// Remove any existing axis constraint (just to be sure)
|
|
||||||
RemoveAxisLockConstraint();
|
|
||||||
|
|
||||||
BSConstraint6Dof axisConstrainer = new BSConstraint6Dof(m_physicsScene.World, m_controllingPrim.PhysBody,
|
|
||||||
OMV.Vector3.Zero, OMV.Quaternion.Identity,
|
|
||||||
false /* useLinearReferenceFrameB */, true /* disableCollisionsBetweenLinkedBodies */);
|
|
||||||
LockAxisConstraint = axisConstrainer;
|
|
||||||
m_physicsScene.Constraints.AddConstraint(LockAxisConstraint);
|
|
||||||
|
|
||||||
// The constraint is tied to the world and oriented to the prim.
|
|
||||||
|
|
||||||
// Free to move linearly in the region
|
|
||||||
OMV.Vector3 linearLow = OMV.Vector3.Zero;
|
|
||||||
OMV.Vector3 linearHigh = m_physicsScene.TerrainManager.DefaultRegionSize;
|
|
||||||
axisConstrainer.SetLinearLimits(linearLow, linearHigh);
|
|
||||||
|
|
||||||
// Angular with some axis locked
|
|
||||||
float fPI = (float)Math.PI;
|
|
||||||
OMV.Vector3 angularLow = new OMV.Vector3(-fPI, -fPI, -fPI);
|
|
||||||
OMV.Vector3 angularHigh = new OMV.Vector3(fPI, fPI, fPI);
|
|
||||||
if (m_controllingPrim.LockedAxis.X != 1f)
|
|
||||||
{
|
{
|
||||||
angularLow.X = 0f;
|
// Lock that axis by creating a 6DOF constraint that has one end in the world and
|
||||||
angularHigh.X = 0f;
|
// the other in the object.
|
||||||
}
|
// http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=20817
|
||||||
if (m_controllingPrim.LockedAxis.Y != 1f)
|
// http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=26380
|
||||||
{
|
|
||||||
angularLow.Y = 0f;
|
|
||||||
angularHigh.Y = 0f;
|
|
||||||
}
|
|
||||||
if (m_controllingPrim.LockedAxis.Z != 1f)
|
|
||||||
{
|
|
||||||
angularLow.Z = 0f;
|
|
||||||
angularHigh.Z = 0f;
|
|
||||||
}
|
|
||||||
if (!axisConstrainer.SetAngularLimits(angularLow, angularHigh))
|
|
||||||
{
|
|
||||||
m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,failedSetAngularLimits", m_controllingPrim.LocalID);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,create,linLow={1},linHi={2},angLow={3},angHi={4}",
|
// Remove any existing axis constraint (just to be sure)
|
||||||
m_controllingPrim.LocalID, linearLow, linearHigh, angularLow, angularHigh);
|
RemoveAxisLockConstraint();
|
||||||
|
|
||||||
// Constants from one of the posts mentioned above and used in Bullet's ConstraintDemo.
|
BSConstraint6Dof axisConstrainer = new BSConstraint6Dof(m_physicsScene.World, m_controllingPrim.PhysBody,
|
||||||
axisConstrainer.TranslationalLimitMotor(true /* enable */, 5.0f, 0.1f);
|
OMV.Vector3.Zero, OMV.Quaternion.Identity,
|
||||||
|
false /* useLinearReferenceFrameB */, true /* disableCollisionsBetweenLinkedBodies */);
|
||||||
|
LockAxisConstraint = axisConstrainer;
|
||||||
|
m_physicsScene.Constraints.AddConstraint(LockAxisConstraint);
|
||||||
|
|
||||||
axisConstrainer.RecomputeConstraintVariables(m_controllingPrim.RawMass);
|
// The constraint is tied to the world and oriented to the prim.
|
||||||
|
|
||||||
|
// Free to move linearly in the region
|
||||||
|
OMV.Vector3 linearLow = OMV.Vector3.Zero;
|
||||||
|
OMV.Vector3 linearHigh = m_physicsScene.TerrainManager.DefaultRegionSize;
|
||||||
|
axisConstrainer.SetLinearLimits(linearLow, linearHigh);
|
||||||
|
|
||||||
|
// Angular with some axis locked
|
||||||
|
float fPI = (float)Math.PI;
|
||||||
|
OMV.Vector3 angularLow = new OMV.Vector3(-fPI, -fPI, -fPI);
|
||||||
|
OMV.Vector3 angularHigh = new OMV.Vector3(fPI, fPI, fPI);
|
||||||
|
if (m_controllingPrim.LockedAxis.X != 1f)
|
||||||
|
{
|
||||||
|
angularLow.X = 0f;
|
||||||
|
angularHigh.X = 0f;
|
||||||
|
}
|
||||||
|
if (m_controllingPrim.LockedAxis.Y != 1f)
|
||||||
|
{
|
||||||
|
angularLow.Y = 0f;
|
||||||
|
angularHigh.Y = 0f;
|
||||||
|
}
|
||||||
|
if (m_controllingPrim.LockedAxis.Z != 1f)
|
||||||
|
{
|
||||||
|
angularLow.Z = 0f;
|
||||||
|
angularHigh.Z = 0f;
|
||||||
|
}
|
||||||
|
if (!axisConstrainer.SetAngularLimits(angularLow, angularHigh))
|
||||||
|
{
|
||||||
|
m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,failedSetAngularLimits", m_controllingPrim.LocalID);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,create,linLow={1},linHi={2},angLow={3},angHi={4}",
|
||||||
|
m_controllingPrim.LocalID, linearLow, linearHigh, angularLow, angularHigh);
|
||||||
|
|
||||||
|
// Constants from one of the posts mentioned above and used in Bullet's ConstraintDemo.
|
||||||
|
axisConstrainer.TranslationalLimitMotor(true /* enable */, 5.0f, 0.1f);
|
||||||
|
|
||||||
|
axisConstrainer.RecomputeConstraintVariables(m_controllingPrim.RawMass);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RemoveAxisLockConstraint()
|
private void RemoveAxisLockConstraint()
|
||||||
|
|
|
@ -0,0 +1,158 @@
|
||||||
|
/*
|
||||||
|
* 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.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
|
||||||
|
using OMV = OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
|
{
|
||||||
|
public class BSActorMoveToTarget : BSActor
|
||||||
|
{
|
||||||
|
private BSVMotor m_targetMotor;
|
||||||
|
|
||||||
|
public BSActorMoveToTarget(BSScene physicsScene, BSPhysObject pObj, string actorName)
|
||||||
|
: base(physicsScene, pObj, actorName)
|
||||||
|
{
|
||||||
|
m_targetMotor = null;
|
||||||
|
m_physicsScene.DetailLog("{0},BSActorMoveToTarget,constructor", m_controllingPrim.LocalID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// BSActor.isActive
|
||||||
|
public override bool isActive
|
||||||
|
{
|
||||||
|
get { return Enabled; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release any connections and resources used by the actor.
|
||||||
|
// BSActor.Dispose()
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
Enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when physical parameters (properties set in Bullet) need to be re-applied.
|
||||||
|
// Called at taint-time.
|
||||||
|
// BSActor.Refresh()
|
||||||
|
public override void Refresh()
|
||||||
|
{
|
||||||
|
m_physicsScene.DetailLog("{0},BSActorMoveToTarget,refresh,enabled={1},active={2},target={3},tau={4}",
|
||||||
|
m_controllingPrim.LocalID, Enabled, m_controllingPrim.MoveToTargetActive,
|
||||||
|
m_controllingPrim.MoveToTargetTarget, m_controllingPrim.MoveToTargetTau );
|
||||||
|
|
||||||
|
// If not active any more...
|
||||||
|
if (!m_controllingPrim.MoveToTargetActive)
|
||||||
|
{
|
||||||
|
Enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isActive)
|
||||||
|
{
|
||||||
|
ActivateMoveToTarget();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DeactivateMoveToTarget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
|
||||||
|
// Register a prestep action to restore physical requirements before the next simulation step.
|
||||||
|
// Called at taint-time.
|
||||||
|
// BSActor.RemoveBodyDependencies()
|
||||||
|
public override void RemoveBodyDependencies()
|
||||||
|
{
|
||||||
|
// Nothing to do for the moveToTarget since it is all software at pre-step action time.
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a hover motor has not been created, create one and start the hovering.
|
||||||
|
private void ActivateMoveToTarget()
|
||||||
|
{
|
||||||
|
if (m_targetMotor == null)
|
||||||
|
{
|
||||||
|
// We're taking over after this.
|
||||||
|
m_controllingPrim.ZeroMotion(true);
|
||||||
|
|
||||||
|
m_targetMotor = new BSVMotor("BSActorMoveToTargget.Activate",
|
||||||
|
m_controllingPrim.MoveToTargetTau, // timeScale
|
||||||
|
BSMotor.Infinite, // decay time scale
|
||||||
|
BSMotor.InfiniteVector, // friction timescale
|
||||||
|
1f // efficiency
|
||||||
|
);
|
||||||
|
m_targetMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG so motor will output detail log messages.
|
||||||
|
m_targetMotor.SetTarget(m_controllingPrim.MoveToTargetTarget);
|
||||||
|
m_targetMotor.SetCurrent(m_controllingPrim.RawPosition);
|
||||||
|
|
||||||
|
m_physicsScene.BeforeStep += Mover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DeactivateMoveToTarget()
|
||||||
|
{
|
||||||
|
if (m_targetMotor != null)
|
||||||
|
{
|
||||||
|
m_physicsScene.BeforeStep -= Mover;
|
||||||
|
m_targetMotor = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called just before the simulation step. Update the vertical position for hoverness.
|
||||||
|
private void Mover(float timeStep)
|
||||||
|
{
|
||||||
|
// Don't do hovering while the object is selected.
|
||||||
|
if (!isActive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
OMV.Vector3 origPosition = m_controllingPrim.RawPosition; // DEBUG DEBUG (for printout below)
|
||||||
|
|
||||||
|
// 'movePosition' is where we'd like the prim to be at this moment.
|
||||||
|
OMV.Vector3 movePosition = m_controllingPrim.RawPosition + m_targetMotor.Step(timeStep);
|
||||||
|
|
||||||
|
// If we are very close to our target, turn off the movement motor.
|
||||||
|
if (m_targetMotor.ErrorIsZero())
|
||||||
|
{
|
||||||
|
m_physicsScene.DetailLog("{0},BSActorMoveToTarget.Mover,zeroMovement,movePos={1},pos={2},mass={3}",
|
||||||
|
m_controllingPrim.LocalID, movePosition, m_controllingPrim.RawPosition, m_controllingPrim.Mass);
|
||||||
|
m_controllingPrim.ForcePosition = m_targetMotor.TargetValue;
|
||||||
|
// Setting the position does not cause the physics engine to generate a property update. Force it.
|
||||||
|
m_physicsScene.PE.PushUpdate(m_controllingPrim.PhysBody);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_controllingPrim.ForcePosition = movePosition;
|
||||||
|
// Setting the position does not cause the physics engine to generate a property update. Force it.
|
||||||
|
m_physicsScene.PE.PushUpdate(m_controllingPrim.PhysBody);
|
||||||
|
}
|
||||||
|
m_physicsScene.DetailLog("{0},BSActorMoveToTarget.Mover,move,fromPos={1},movePos={2}", m_controllingPrim.LocalID, origPosition, movePosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,137 @@
|
||||||
|
/*
|
||||||
|
* 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.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
|
||||||
|
using OMV = OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
|
{
|
||||||
|
public class BSActorSetForce : BSActor
|
||||||
|
{
|
||||||
|
BSFMotor m_forceMotor;
|
||||||
|
|
||||||
|
public BSActorSetForce(BSScene physicsScene, BSPhysObject pObj, string actorName)
|
||||||
|
: base(physicsScene, pObj, actorName)
|
||||||
|
{
|
||||||
|
m_forceMotor = null;
|
||||||
|
m_physicsScene.DetailLog("{0},BSActorSetForce,constructor", m_controllingPrim.LocalID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// BSActor.isActive
|
||||||
|
public override bool isActive
|
||||||
|
{
|
||||||
|
get { return Enabled && m_controllingPrim.IsPhysicallyActive; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release any connections and resources used by the actor.
|
||||||
|
// BSActor.Dispose()
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
Enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when physical parameters (properties set in Bullet) need to be re-applied.
|
||||||
|
// Called at taint-time.
|
||||||
|
// BSActor.Refresh()
|
||||||
|
public override void Refresh()
|
||||||
|
{
|
||||||
|
m_physicsScene.DetailLog("{0},BSActorSetForce,refresh", m_controllingPrim.LocalID);
|
||||||
|
|
||||||
|
// If not active any more, get rid of me (shouldn't ever happen, but just to be safe)
|
||||||
|
if (m_controllingPrim.RawForce == OMV.Vector3.Zero)
|
||||||
|
{
|
||||||
|
m_physicsScene.DetailLog("{0},BSActorSetForce,refresh,notSetForce,removing={1}", m_controllingPrim.LocalID, ActorName);
|
||||||
|
Enabled = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the object is physically active, add the hoverer prestep action
|
||||||
|
if (isActive)
|
||||||
|
{
|
||||||
|
ActivateSetForce();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DeactivateSetForce();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
|
||||||
|
// Register a prestep action to restore physical requirements before the next simulation step.
|
||||||
|
// Called at taint-time.
|
||||||
|
// BSActor.RemoveBodyDependencies()
|
||||||
|
public override void RemoveBodyDependencies()
|
||||||
|
{
|
||||||
|
// Nothing to do for the hoverer since it is all software at pre-step action time.
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a hover motor has not been created, create one and start the hovering.
|
||||||
|
private void ActivateSetForce()
|
||||||
|
{
|
||||||
|
if (m_forceMotor == null)
|
||||||
|
{
|
||||||
|
// A fake motor that might be used someday
|
||||||
|
m_forceMotor = new BSFMotor("setForce", 1f, 1f, 1f, 1f);
|
||||||
|
|
||||||
|
m_physicsScene.BeforeStep += Mover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DeactivateSetForce()
|
||||||
|
{
|
||||||
|
if (m_forceMotor != null)
|
||||||
|
{
|
||||||
|
m_physicsScene.BeforeStep -= Mover;
|
||||||
|
m_forceMotor = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called just before the simulation step. Update the vertical position for hoverness.
|
||||||
|
private void Mover(float timeStep)
|
||||||
|
{
|
||||||
|
// Don't do force while the object is selected.
|
||||||
|
if (!isActive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_physicsScene.DetailLog("{0},BSActorSetForce,preStep,force={1}", m_controllingPrim.LocalID, m_controllingPrim.RawForce);
|
||||||
|
if (m_controllingPrim.PhysBody.HasPhysicalBody)
|
||||||
|
{
|
||||||
|
m_physicsScene.PE.ApplyCentralForce(m_controllingPrim.PhysBody, m_controllingPrim.RawForce);
|
||||||
|
m_controllingPrim.ActivateIfPhysical(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,138 @@
|
||||||
|
/*
|
||||||
|
* 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.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
|
||||||
|
using OMV = OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
|
{
|
||||||
|
public class BSActorSetTorque : BSActor
|
||||||
|
{
|
||||||
|
BSFMotor m_torqueMotor;
|
||||||
|
|
||||||
|
public BSActorSetTorque(BSScene physicsScene, BSPhysObject pObj, string actorName)
|
||||||
|
: base(physicsScene, pObj, actorName)
|
||||||
|
{
|
||||||
|
m_torqueMotor = null;
|
||||||
|
m_physicsScene.DetailLog("{0},BSActorSetTorque,constructor", m_controllingPrim.LocalID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// BSActor.isActive
|
||||||
|
public override bool isActive
|
||||||
|
{
|
||||||
|
get { return Enabled && m_controllingPrim.IsPhysicallyActive; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release any connections and resources used by the actor.
|
||||||
|
// BSActor.Dispose()
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
Enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when physical parameters (properties set in Bullet) need to be re-applied.
|
||||||
|
// Called at taint-time.
|
||||||
|
// BSActor.Refresh()
|
||||||
|
public override void Refresh()
|
||||||
|
{
|
||||||
|
m_physicsScene.DetailLog("{0},BSActorSetTorque,refresh,torque={1}", m_controllingPrim.LocalID, m_controllingPrim.RawTorque);
|
||||||
|
|
||||||
|
// If not active any more, get rid of me (shouldn't ever happen, but just to be safe)
|
||||||
|
if (m_controllingPrim.RawTorque == OMV.Vector3.Zero)
|
||||||
|
{
|
||||||
|
m_physicsScene.DetailLog("{0},BSActorSetTorque,refresh,notSetTorque,disabling={1}", m_controllingPrim.LocalID, ActorName);
|
||||||
|
Enabled = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the object is physically active, add the hoverer prestep action
|
||||||
|
if (isActive)
|
||||||
|
{
|
||||||
|
ActivateSetTorque();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DeactivateSetTorque();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
|
||||||
|
// Register a prestep action to restore physical requirements before the next simulation step.
|
||||||
|
// Called at taint-time.
|
||||||
|
// BSActor.RemoveBodyDependencies()
|
||||||
|
public override void RemoveBodyDependencies()
|
||||||
|
{
|
||||||
|
// Nothing to do for the hoverer since it is all software at pre-step action time.
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a hover motor has not been created, create one and start the hovering.
|
||||||
|
private void ActivateSetTorque()
|
||||||
|
{
|
||||||
|
if (m_torqueMotor == null)
|
||||||
|
{
|
||||||
|
// A fake motor that might be used someday
|
||||||
|
m_torqueMotor = new BSFMotor("setTorque", 1f, 1f, 1f, 1f);
|
||||||
|
|
||||||
|
m_physicsScene.BeforeStep += Mover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DeactivateSetTorque()
|
||||||
|
{
|
||||||
|
if (m_torqueMotor != null)
|
||||||
|
{
|
||||||
|
m_physicsScene.BeforeStep -= Mover;
|
||||||
|
m_torqueMotor = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called just before the simulation step. Update the vertical position for hoverness.
|
||||||
|
private void Mover(float timeStep)
|
||||||
|
{
|
||||||
|
// Don't do force while the object is selected.
|
||||||
|
if (!isActive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_physicsScene.DetailLog("{0},BSActorSetTorque,preStep,force={1}", m_controllingPrim.LocalID, m_controllingPrim.RawTorque);
|
||||||
|
if (m_controllingPrim.PhysBody.HasPhysicalBody)
|
||||||
|
{
|
||||||
|
m_controllingPrim.AddAngularForce(m_controllingPrim.RawTorque, false, true);
|
||||||
|
m_controllingPrim.ActivateIfPhysical(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,45 +32,72 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
{
|
{
|
||||||
public class BSActorCollection
|
public class BSActorCollection
|
||||||
{
|
{
|
||||||
private BSScene PhysicsScene { get; set; }
|
private BSScene m_physicsScene { get; set; }
|
||||||
private Dictionary<string, BSActor> m_actors;
|
private Dictionary<string, BSActor> m_actors;
|
||||||
|
|
||||||
public BSActorCollection(BSScene physicsScene)
|
public BSActorCollection(BSScene physicsScene)
|
||||||
{
|
{
|
||||||
PhysicsScene = physicsScene;
|
m_physicsScene = physicsScene;
|
||||||
m_actors = new Dictionary<string, BSActor>();
|
m_actors = new Dictionary<string, BSActor>();
|
||||||
}
|
}
|
||||||
public void Add(string name, BSActor actor)
|
public void Add(string name, BSActor actor)
|
||||||
{
|
{
|
||||||
m_actors[name] = actor;
|
lock (m_actors)
|
||||||
|
{
|
||||||
|
if (!m_actors.ContainsKey(name))
|
||||||
|
{
|
||||||
|
m_actors[name] = actor;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public bool RemoveAndRelease(string name)
|
public bool RemoveAndRelease(string name)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
if (m_actors.ContainsKey(name))
|
lock (m_actors)
|
||||||
{
|
{
|
||||||
BSActor beingRemoved = m_actors[name];
|
if (m_actors.ContainsKey(name))
|
||||||
beingRemoved.Dispose();
|
{
|
||||||
m_actors.Remove(name);
|
BSActor beingRemoved = m_actors[name];
|
||||||
ret = true;
|
m_actors.Remove(name);
|
||||||
|
beingRemoved.Dispose();
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
Release();
|
lock (m_actors)
|
||||||
m_actors.Clear();
|
{
|
||||||
|
Release();
|
||||||
|
m_actors.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
}
|
}
|
||||||
public bool HasActor(string name)
|
public bool HasActor(string name)
|
||||||
{
|
{
|
||||||
return m_actors.ContainsKey(name);
|
return m_actors.ContainsKey(name);
|
||||||
}
|
}
|
||||||
|
public bool TryGetActor(string actorName, out BSActor theActor)
|
||||||
|
{
|
||||||
|
return m_actors.TryGetValue(actorName, out theActor);
|
||||||
|
}
|
||||||
public void ForEachActor(Action<BSActor> act)
|
public void ForEachActor(Action<BSActor> act)
|
||||||
{
|
{
|
||||||
foreach (KeyValuePair<string, BSActor> kvp in m_actors)
|
lock (m_actors)
|
||||||
act(kvp.Value);
|
{
|
||||||
|
foreach (KeyValuePair<string, BSActor> kvp in m_actors)
|
||||||
|
act(kvp.Value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Enable(bool enabl)
|
||||||
|
{
|
||||||
|
ForEachActor(a => a.SetEnabled(enabl));
|
||||||
|
}
|
||||||
public void Release()
|
public void Release()
|
||||||
{
|
{
|
||||||
ForEachActor(a => a.Dispose());
|
ForEachActor(a => a.Dispose());
|
||||||
|
@ -98,7 +125,7 @@ public abstract class BSActor
|
||||||
{
|
{
|
||||||
protected BSScene m_physicsScene { get; private set; }
|
protected BSScene m_physicsScene { get; private set; }
|
||||||
protected BSPhysObject m_controllingPrim { get; private set; }
|
protected BSPhysObject m_controllingPrim { get; private set; }
|
||||||
protected bool Enabled { get; set; }
|
public virtual bool Enabled { get; set; }
|
||||||
public string ActorName { get; private set; }
|
public string ActorName { get; private set; }
|
||||||
|
|
||||||
public BSActor(BSScene physicsScene, BSPhysObject pObj, string actorName)
|
public BSActor(BSScene physicsScene, BSPhysObject pObj, string actorName)
|
||||||
|
@ -114,8 +141,10 @@ public abstract class BSActor
|
||||||
{
|
{
|
||||||
get { return Enabled; }
|
get { return Enabled; }
|
||||||
}
|
}
|
||||||
// Turn the actor on an off.
|
|
||||||
public virtual void Enable(bool setEnabled)
|
// Turn the actor on an off. Only used by ActorCollection to set all enabled/disabled.
|
||||||
|
// Anyone else should assign true/false to 'Enabled'.
|
||||||
|
public void SetEnabled(bool setEnabled)
|
||||||
{
|
{
|
||||||
Enabled = setEnabled;
|
Enabled = setEnabled;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,9 +46,6 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
private OMV.Vector3 _position;
|
private OMV.Vector3 _position;
|
||||||
private float _mass;
|
private float _mass;
|
||||||
private float _avatarVolume;
|
private float _avatarVolume;
|
||||||
private OMV.Vector3 _force;
|
|
||||||
private OMV.Vector3 _velocity;
|
|
||||||
private OMV.Vector3 _torque;
|
|
||||||
private float _collisionScore;
|
private float _collisionScore;
|
||||||
private OMV.Vector3 _acceleration;
|
private OMV.Vector3 _acceleration;
|
||||||
private OMV.Quaternion _orientation;
|
private OMV.Quaternion _orientation;
|
||||||
|
@ -61,17 +58,13 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
private OMV.Vector3 _rotationalVelocity;
|
private OMV.Vector3 _rotationalVelocity;
|
||||||
private bool _kinematic;
|
private bool _kinematic;
|
||||||
private float _buoyancy;
|
private float _buoyancy;
|
||||||
private bool _isStationaryStanding; // true is standing on a stationary object
|
|
||||||
|
|
||||||
private BSVMotor _velocityMotor;
|
private BSActorAvatarMove m_moveActor;
|
||||||
|
private const string AvatarMoveActorName = "BSCharacter.AvatarMove";
|
||||||
|
|
||||||
private OMV.Vector3 _PIDTarget;
|
private OMV.Vector3 _PIDTarget;
|
||||||
private bool _usePID;
|
private bool _usePID;
|
||||||
private float _PIDTau;
|
private float _PIDTau;
|
||||||
private bool _useHoverPID;
|
|
||||||
private float _PIDHoverHeight;
|
|
||||||
private PIDHoverType _PIDHoverType;
|
|
||||||
private float _PIDHoverTao;
|
|
||||||
|
|
||||||
public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying)
|
public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying)
|
||||||
: base(parent_scene, localID, avName, "BSCharacter")
|
: base(parent_scene, localID, avName, "BSCharacter")
|
||||||
|
@ -81,11 +74,10 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
|
|
||||||
_flying = isFlying;
|
_flying = isFlying;
|
||||||
_orientation = OMV.Quaternion.Identity;
|
_orientation = OMV.Quaternion.Identity;
|
||||||
_velocity = OMV.Vector3.Zero;
|
RawVelocity = OMV.Vector3.Zero;
|
||||||
_buoyancy = ComputeBuoyancyFromFlying(isFlying);
|
_buoyancy = ComputeBuoyancyFromFlying(isFlying);
|
||||||
Friction = BSParam.AvatarStandingFriction;
|
Friction = BSParam.AvatarStandingFriction;
|
||||||
Density = BSParam.AvatarDensity / BSParam.DensityScaleFactor;
|
Density = BSParam.AvatarDensity / BSParam.DensityScaleFactor;
|
||||||
_isStationaryStanding = false;
|
|
||||||
|
|
||||||
// Old versions of ScenePresence passed only the height. If width and/or depth are zero,
|
// Old versions of ScenePresence passed only the height. If width and/or depth are zero,
|
||||||
// replace with the default values.
|
// replace with the default values.
|
||||||
|
@ -99,7 +91,12 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
// set _avatarVolume and _mass based on capsule size, _density and Scale
|
// set _avatarVolume and _mass based on capsule size, _density and Scale
|
||||||
ComputeAvatarVolumeAndMass();
|
ComputeAvatarVolumeAndMass();
|
||||||
|
|
||||||
SetupMovementMotor();
|
// The avatar's movement is controlled by this motor that speeds up and slows down
|
||||||
|
// the avatar seeking to reach the motor's target speed.
|
||||||
|
// This motor runs as a prestep action for the avatar so it will keep the avatar
|
||||||
|
// standing as well as moving. Destruction of the avatar will destroy the pre-step action.
|
||||||
|
m_moveActor = new BSActorAvatarMove(PhysicsScene, this, AvatarMoveActorName);
|
||||||
|
PhysicalActors.Add(AvatarMoveActorName, m_moveActor);
|
||||||
|
|
||||||
DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}",
|
DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}",
|
||||||
LocalID, _size, Scale, Density, _avatarVolume, RawMass);
|
LocalID, _size, Scale, Density, _avatarVolume, RawMass);
|
||||||
|
@ -139,10 +136,10 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
ForcePosition = _position;
|
ForcePosition = _position;
|
||||||
|
|
||||||
// Set the velocity
|
// Set the velocity
|
||||||
_velocityMotor.Reset();
|
if (m_moveActor != null)
|
||||||
_velocityMotor.SetTarget(_velocity);
|
m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, false);
|
||||||
_velocityMotor.SetCurrent(_velocity);
|
|
||||||
ForceVelocity = _velocity;
|
ForceVelocity = RawVelocity;
|
||||||
|
|
||||||
// This will enable or disable the flying buoyancy of the avatar.
|
// This will enable or disable the flying buoyancy of the avatar.
|
||||||
// Needs to be reset especially when an avatar is recreated after crossing a region boundry.
|
// Needs to be reset especially when an avatar is recreated after crossing a region boundry.
|
||||||
|
@ -163,6 +160,9 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
// Make so capsule does not fall over
|
// Make so capsule does not fall over
|
||||||
PhysicsScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero);
|
PhysicsScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero);
|
||||||
|
|
||||||
|
// The avatar mover sets some parameters.
|
||||||
|
PhysicalActors.Refresh();
|
||||||
|
|
||||||
PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT);
|
PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT);
|
||||||
|
|
||||||
PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody);
|
PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody);
|
||||||
|
@ -176,162 +176,6 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
PhysBody.ApplyCollisionMask(PhysicsScene);
|
PhysBody.ApplyCollisionMask(PhysicsScene);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The avatar's movement is controlled by this motor that speeds up and slows down
|
|
||||||
// the avatar seeking to reach the motor's target speed.
|
|
||||||
// This motor runs as a prestep action for the avatar so it will keep the avatar
|
|
||||||
// standing as well as moving. Destruction of the avatar will destroy the pre-step action.
|
|
||||||
private void SetupMovementMotor()
|
|
||||||
{
|
|
||||||
// Infinite decay and timescale values so motor only changes current to target values.
|
|
||||||
_velocityMotor = new BSVMotor("BSCharacter.Velocity",
|
|
||||||
0.2f, // time scale
|
|
||||||
BSMotor.Infinite, // decay time scale
|
|
||||||
BSMotor.InfiniteVector, // friction timescale
|
|
||||||
1f // efficiency
|
|
||||||
);
|
|
||||||
// _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
|
|
||||||
|
|
||||||
RegisterPreStepAction("BSCharactor.Movement", LocalID, delegate(float timeStep)
|
|
||||||
{
|
|
||||||
// TODO: Decide if the step parameters should be changed depending on the avatar's
|
|
||||||
// state (flying, colliding, ...). There is code in ODE to do this.
|
|
||||||
|
|
||||||
// COMMENTARY: when the user is making the avatar walk, except for falling, the velocity
|
|
||||||
// specified for the avatar is the one that should be used. For falling, if the avatar
|
|
||||||
// is not flying and is not colliding then it is presumed to be falling and the Z
|
|
||||||
// component is not fooled with (thus allowing gravity to do its thing).
|
|
||||||
// When the avatar is standing, though, the user has specified a velocity of zero and
|
|
||||||
// the avatar should be standing. But if the avatar is pushed by something in the world
|
|
||||||
// (raising elevator platform, moving vehicle, ...) the avatar should be allowed to
|
|
||||||
// move. Thus, the velocity cannot be forced to zero. The problem is that small velocity
|
|
||||||
// errors can creap in and the avatar will slowly float off in some direction.
|
|
||||||
// So, the problem is that, when an avatar is standing, we cannot tell creaping error
|
|
||||||
// from real pushing.
|
|
||||||
// The code below uses whether the collider is static or moving to decide whether to zero motion.
|
|
||||||
|
|
||||||
_velocityMotor.Step(timeStep);
|
|
||||||
_isStationaryStanding = false;
|
|
||||||
|
|
||||||
// If we're not supposed to be moving, make sure things are zero.
|
|
||||||
if (_velocityMotor.ErrorIsZero() && _velocityMotor.TargetValue == OMV.Vector3.Zero)
|
|
||||||
{
|
|
||||||
// The avatar shouldn't be moving
|
|
||||||
_velocityMotor.Zero();
|
|
||||||
|
|
||||||
if (IsColliding)
|
|
||||||
{
|
|
||||||
// If we are colliding with a stationary object, presume we're standing and don't move around
|
|
||||||
if (!ColliderIsMoving)
|
|
||||||
{
|
|
||||||
DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", LocalID);
|
|
||||||
_isStationaryStanding = true;
|
|
||||||
ZeroMotion(true /* inTaintTime */);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Standing has more friction on the ground
|
|
||||||
if (Friction != BSParam.AvatarStandingFriction)
|
|
||||||
{
|
|
||||||
Friction = BSParam.AvatarStandingFriction;
|
|
||||||
PhysicsScene.PE.SetFriction(PhysBody, Friction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (Flying)
|
|
||||||
{
|
|
||||||
// Flying and not collising and velocity nearly zero.
|
|
||||||
ZeroMotion(true /* inTaintTime */);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}", LocalID, _velocityMotor.TargetValue, IsColliding);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Supposed to be moving.
|
|
||||||
OMV.Vector3 stepVelocity = _velocityMotor.CurrentValue;
|
|
||||||
|
|
||||||
if (Friction != BSParam.AvatarFriction)
|
|
||||||
{
|
|
||||||
// Probably starting up walking. Set friction to moving friction.
|
|
||||||
Friction = BSParam.AvatarFriction;
|
|
||||||
PhysicsScene.PE.SetFriction(PhysBody, Friction);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If falling, we keep the world's downward vector no matter what the other axis specify.
|
|
||||||
// The check for _velocity.Z < 0 makes jumping work (temporary upward force).
|
|
||||||
if (!Flying && !IsColliding)
|
|
||||||
{
|
|
||||||
if (_velocity.Z < 0)
|
|
||||||
stepVelocity.Z = _velocity.Z;
|
|
||||||
// DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force.
|
|
||||||
OMV.Vector3 moveForce = (stepVelocity - _velocity) * Mass;
|
|
||||||
|
|
||||||
// Should we check for move force being small and forcing velocity to zero?
|
|
||||||
|
|
||||||
// Add special movement force to allow avatars to walk up stepped surfaces.
|
|
||||||
moveForce += WalkUpStairs();
|
|
||||||
|
|
||||||
DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", LocalID, stepVelocity, _velocity, Mass, moveForce);
|
|
||||||
PhysicsScene.PE.ApplyCentralImpulse(PhysBody, moveForce);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decide if the character is colliding with a low object and compute a force to pop the
|
|
||||||
// avatar up so it can walk up and over the low objects.
|
|
||||||
private OMV.Vector3 WalkUpStairs()
|
|
||||||
{
|
|
||||||
OMV.Vector3 ret = OMV.Vector3.Zero;
|
|
||||||
|
|
||||||
// This test is done if moving forward, not flying and is colliding with something.
|
|
||||||
// DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}",
|
|
||||||
// LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count);
|
|
||||||
if (IsColliding && !Flying && TargetVelocitySpeed > 0.1f /* && ForwardSpeed < 0.1f */)
|
|
||||||
{
|
|
||||||
// The range near the character's feet where we will consider stairs
|
|
||||||
float nearFeetHeightMin = RawPosition.Z - (Size.Z / 2f) + 0.05f;
|
|
||||||
float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight;
|
|
||||||
|
|
||||||
// Look for a collision point that is near the character's feet and is oriented the same as the charactor is
|
|
||||||
foreach (KeyValuePair<uint, ContactPoint> kvp in CollisionsLastTick.m_objCollisionList)
|
|
||||||
{
|
|
||||||
// Don't care about collisions with the terrain
|
|
||||||
if (kvp.Key > PhysicsScene.TerrainManager.HighestTerrainID)
|
|
||||||
{
|
|
||||||
OMV.Vector3 touchPosition = kvp.Value.Position;
|
|
||||||
// DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}",
|
|
||||||
// LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition);
|
|
||||||
if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax)
|
|
||||||
{
|
|
||||||
// This contact is within the 'near the feet' range.
|
|
||||||
// The normal should be our contact point to the object so it is pointing away
|
|
||||||
// thus the difference between our facing orientation and the normal should be small.
|
|
||||||
OMV.Vector3 directionFacing = OMV.Vector3.UnitX * RawOrientation;
|
|
||||||
OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal);
|
|
||||||
float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal));
|
|
||||||
if (diff < BSParam.AvatarStepApproachFactor)
|
|
||||||
{
|
|
||||||
// Found the stairs contact point. Push up a little to raise the character.
|
|
||||||
float upForce = (touchPosition.Z - nearFeetHeightMin) * Mass * BSParam.AvatarStepForceFactor;
|
|
||||||
ret = new OMV.Vector3(0f, 0f, upForce);
|
|
||||||
|
|
||||||
// Also move the avatar up for the new height
|
|
||||||
OMV.Vector3 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight / 2f);
|
|
||||||
ForcePosition = RawPosition + displacement;
|
|
||||||
}
|
|
||||||
DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},faceDir={3},norm={4},diff={5},ret={6}",
|
|
||||||
LocalID, touchPosition, nearFeetHeightMin, directionFacing, touchNormal, diff, ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void RequestPhysicsterseUpdate()
|
public override void RequestPhysicsterseUpdate()
|
||||||
{
|
{
|
||||||
|
@ -403,7 +247,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
// Called at taint time!
|
// Called at taint time!
|
||||||
public override void ZeroMotion(bool inTaintTime)
|
public override void ZeroMotion(bool inTaintTime)
|
||||||
{
|
{
|
||||||
_velocity = OMV.Vector3.Zero;
|
RawVelocity = OMV.Vector3.Zero;
|
||||||
_acceleration = OMV.Vector3.Zero;
|
_acceleration = OMV.Vector3.Zero;
|
||||||
_rotationalVelocity = OMV.Vector3.Zero;
|
_rotationalVelocity = OMV.Vector3.Zero;
|
||||||
|
|
||||||
|
@ -542,15 +386,15 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
}
|
}
|
||||||
|
|
||||||
public override OMV.Vector3 Force {
|
public override OMV.Vector3 Force {
|
||||||
get { return _force; }
|
get { return RawForce; }
|
||||||
set {
|
set {
|
||||||
_force = value;
|
RawForce = value;
|
||||||
// m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
|
// m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
|
||||||
PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate()
|
PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force);
|
DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, RawForce);
|
||||||
if (PhysBody.HasPhysicalBody)
|
if (PhysBody.HasPhysicalBody)
|
||||||
PhysicsScene.PE.SetObjectForce(PhysBody, _force);
|
PhysicsScene.PE.SetObjectForce(PhysBody, RawForce);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -573,7 +417,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return m_targetVelocity;
|
return base.m_targetVelocity;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
@ -583,51 +427,39 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
if (_setAlwaysRun)
|
if (_setAlwaysRun)
|
||||||
targetVel *= new OMV.Vector3(BSParam.AvatarAlwaysRunFactor, BSParam.AvatarAlwaysRunFactor, 0f);
|
targetVel *= new OMV.Vector3(BSParam.AvatarAlwaysRunFactor, BSParam.AvatarAlwaysRunFactor, 0f);
|
||||||
|
|
||||||
PhysicsScene.TaintedObject("BSCharacter.setTargetVelocity", delegate()
|
if (m_moveActor != null)
|
||||||
{
|
m_moveActor.SetVelocityAndTarget(RawVelocity, targetVel, false /* inTaintTime */);
|
||||||
_velocityMotor.Reset();
|
|
||||||
_velocityMotor.SetTarget(targetVel);
|
|
||||||
_velocityMotor.SetCurrent(_velocity);
|
|
||||||
_velocityMotor.Enabled = true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public override OMV.Vector3 RawVelocity
|
|
||||||
{
|
|
||||||
get { return _velocity; }
|
|
||||||
set { _velocity = value; }
|
|
||||||
}
|
|
||||||
// Directly setting velocity means this is what the user really wants now.
|
// Directly setting velocity means this is what the user really wants now.
|
||||||
public override OMV.Vector3 Velocity {
|
public override OMV.Vector3 Velocity {
|
||||||
get { return _velocity; }
|
get { return RawVelocity; }
|
||||||
set {
|
set {
|
||||||
_velocity = value;
|
RawVelocity = value;
|
||||||
// m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
|
// m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, RawVelocity);
|
||||||
PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate()
|
PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate()
|
||||||
{
|
{
|
||||||
_velocityMotor.Reset();
|
if (m_moveActor != null)
|
||||||
_velocityMotor.SetCurrent(_velocity);
|
m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, true /* inTaintTime */);
|
||||||
_velocityMotor.SetTarget(_velocity);
|
|
||||||
_velocityMotor.Enabled = false;
|
|
||||||
|
|
||||||
DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
|
DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, RawVelocity);
|
||||||
ForceVelocity = _velocity;
|
ForceVelocity = RawVelocity;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public override OMV.Vector3 ForceVelocity {
|
public override OMV.Vector3 ForceVelocity {
|
||||||
get { return _velocity; }
|
get { return RawVelocity; }
|
||||||
set {
|
set {
|
||||||
PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity");
|
PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity");
|
||||||
|
|
||||||
_velocity = value;
|
RawVelocity = value;
|
||||||
PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity);
|
PhysicsScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
|
||||||
PhysicsScene.PE.Activate(PhysBody, true);
|
PhysicsScene.PE.Activate(PhysBody, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public override OMV.Vector3 Torque {
|
public override OMV.Vector3 Torque {
|
||||||
get { return _torque; }
|
get { return RawTorque; }
|
||||||
set { _torque = value;
|
set { RawTorque = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public override float CollisionScore {
|
public override float CollisionScore {
|
||||||
|
@ -783,27 +615,6 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
set { _PIDTau = value; }
|
set { _PIDTau = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used for llSetHoverHeight and maybe vehicle height
|
|
||||||
// Hover Height will override MoveTo target's Z
|
|
||||||
public override bool PIDHoverActive {
|
|
||||||
set { _useHoverPID = value; }
|
|
||||||
}
|
|
||||||
public override float PIDHoverHeight {
|
|
||||||
set { _PIDHoverHeight = value; }
|
|
||||||
}
|
|
||||||
public override PIDHoverType PIDHoverType {
|
|
||||||
set { _PIDHoverType = value; }
|
|
||||||
}
|
|
||||||
public override float PIDHoverTau {
|
|
||||||
set { _PIDHoverTao = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// For RotLookAt
|
|
||||||
public override OMV.Quaternion APIDTarget { set { return; } }
|
|
||||||
public override bool APIDActive { set { return; } }
|
|
||||||
public override float APIDStrength { set { return; } }
|
|
||||||
public override float APIDDamping { set { return; } }
|
|
||||||
|
|
||||||
public override void AddForce(OMV.Vector3 force, bool pushforce)
|
public override void AddForce(OMV.Vector3 force, bool pushforce)
|
||||||
{
|
{
|
||||||
// Since this force is being applied in only one step, make this a force per second.
|
// Since this force is being applied in only one step, make this a force per second.
|
||||||
|
@ -833,7 +644,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
|
public override void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
|
||||||
}
|
}
|
||||||
public override void SetMomentum(OMV.Vector3 momentum) {
|
public override void SetMomentum(OMV.Vector3 momentum) {
|
||||||
}
|
}
|
||||||
|
@ -887,7 +698,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
public override void UpdateProperties(EntityProperties entprop)
|
public override void UpdateProperties(EntityProperties entprop)
|
||||||
{
|
{
|
||||||
// Don't change position if standing on a stationary object.
|
// Don't change position if standing on a stationary object.
|
||||||
if (!_isStationaryStanding)
|
if (!IsStationary)
|
||||||
_position = entprop.Position;
|
_position = entprop.Position;
|
||||||
|
|
||||||
_orientation = entprop.Rotation;
|
_orientation = entprop.Rotation;
|
||||||
|
@ -896,8 +707,8 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
// and will send agent updates to the clients if velocity changes by more than
|
// and will send agent updates to the clients if velocity changes by more than
|
||||||
// 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many
|
// 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many
|
||||||
// extra updates.
|
// extra updates.
|
||||||
if (!entprop.Velocity.ApproxEquals(_velocity, 0.1f))
|
if (!entprop.Velocity.ApproxEquals(RawVelocity, 0.1f))
|
||||||
_velocity = entprop.Velocity;
|
RawVelocity = entprop.Velocity;
|
||||||
|
|
||||||
_acceleration = entprop.Acceleration;
|
_acceleration = entprop.Acceleration;
|
||||||
_rotationalVelocity = entprop.RotationalVelocity;
|
_rotationalVelocity = entprop.RotationalVelocity;
|
||||||
|
@ -920,7 +731,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
// base.RequestPhysicsterseUpdate();
|
// base.RequestPhysicsterseUpdate();
|
||||||
|
|
||||||
DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
|
DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
|
||||||
LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
|
LocalID, _position, _orientation, RawVelocity, _acceleration, _rotationalVelocity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1358,6 +1358,35 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
// If vertical attaction timescale is reasonable
|
// If vertical attaction timescale is reasonable
|
||||||
if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
|
if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
|
||||||
{
|
{
|
||||||
|
//Another formula to try got from :
|
||||||
|
//http://answers.unity3d.com/questions/10425/how-to-stabilize-angular-motion-alignment-of-hover.html
|
||||||
|
|
||||||
|
Vector3 VehicleUpAxis = Vector3.UnitZ * VehicleOrientation;
|
||||||
|
|
||||||
|
// Flipping what was originally a timescale into a speed variable and then multiplying it by 2
|
||||||
|
// since only computing half the distance between the angles.
|
||||||
|
float VerticalAttractionSpeed = (1 / m_verticalAttractionTimescale) * 2.0f;
|
||||||
|
|
||||||
|
// Make a prediction of where the up axis will be when this is applied rather then where it is now as
|
||||||
|
// this makes for a smoother adjustment and less fighting between the various forces.
|
||||||
|
Vector3 predictedUp = VehicleUpAxis * Quaternion.CreateFromAxisAngle(VehicleRotationalVelocity, 0f);
|
||||||
|
|
||||||
|
// This is only half the distance to the target so it will take 2 seconds to complete the turn.
|
||||||
|
Vector3 torqueVector = Vector3.Cross(predictedUp, Vector3.UnitZ);
|
||||||
|
|
||||||
|
// Scale vector by our timescale since it is an acceleration it is r/s^2 or radians a timescale squared
|
||||||
|
Vector3 vertContributionV = torqueVector * VerticalAttractionSpeed * VerticalAttractionSpeed;
|
||||||
|
|
||||||
|
VehicleRotationalVelocity += vertContributionV;
|
||||||
|
|
||||||
|
VDetailLog("{0}, MoveAngular,verticalAttraction,UpAxis={1},PredictedUp={2},torqueVector={3},contrib={4}",
|
||||||
|
ControllingPrim.LocalID,
|
||||||
|
VehicleUpAxis,
|
||||||
|
predictedUp,
|
||||||
|
torqueVector,
|
||||||
|
vertContributionV);
|
||||||
|
//=====================================================================
|
||||||
|
/*
|
||||||
// Possible solution derived from a discussion at:
|
// Possible solution derived from a discussion at:
|
||||||
// http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no
|
// http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no
|
||||||
|
|
||||||
|
@ -1392,6 +1421,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
differenceAngle,
|
differenceAngle,
|
||||||
correctionRotation,
|
correctionRotation,
|
||||||
vertContributionV);
|
vertContributionV);
|
||||||
|
*/
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -86,6 +86,7 @@ public static class BSParam
|
||||||
public static bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
|
public static bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
|
||||||
public static bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects
|
public static bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects
|
||||||
public static bool ShouldRemoveZeroWidthTriangles { get; private set; }
|
public static bool ShouldRemoveZeroWidthTriangles { get; private set; }
|
||||||
|
public static bool ShouldUseBulletHACD { get; set; }
|
||||||
|
|
||||||
public static float TerrainImplementation { get; private set; }
|
public static float TerrainImplementation { get; private set; }
|
||||||
public static int TerrainMeshMagnification { get; private set; }
|
public static int TerrainMeshMagnification { get; private set; }
|
||||||
|
@ -149,6 +150,15 @@ public static class BSParam
|
||||||
public static float CSHullVolumeConservationThresholdPercent { get; private set; }
|
public static float CSHullVolumeConservationThresholdPercent { get; private set; }
|
||||||
public static int CSHullMaxVertices { get; private set; }
|
public static int CSHullMaxVertices { get; private set; }
|
||||||
public static float CSHullMaxSkinWidth { get; private set; }
|
public static float CSHullMaxSkinWidth { get; private set; }
|
||||||
|
public static float BHullMaxVerticesPerHull { get; private set; } // 100
|
||||||
|
public static float BHullMinClusters { get; private set; } // 2
|
||||||
|
public static float BHullCompacityWeight { get; private set; } // 0.1
|
||||||
|
public static float BHullVolumeWeight { get; private set; } // 0.0
|
||||||
|
public static float BHullConcavity { get; private set; } // 100
|
||||||
|
public static bool BHullAddExtraDistPoints { get; private set; } // false
|
||||||
|
public static bool BHullAddNeighboursDistPoints { get; private set; } // false
|
||||||
|
public static bool BHullAddFacesPoints { get; private set; } // false
|
||||||
|
public static bool BHullShouldAdjustCollisionMargin { get; private set; } // false
|
||||||
|
|
||||||
// Linkset implementation parameters
|
// Linkset implementation parameters
|
||||||
public static float LinksetImplementation { get; private set; }
|
public static float LinksetImplementation { get; private set; }
|
||||||
|
@ -325,6 +335,10 @@ public static class BSParam
|
||||||
true,
|
true,
|
||||||
(s) => { return ShouldRemoveZeroWidthTriangles; },
|
(s) => { return ShouldRemoveZeroWidthTriangles; },
|
||||||
(s,v) => { ShouldRemoveZeroWidthTriangles = v; } ),
|
(s,v) => { ShouldRemoveZeroWidthTriangles = v; } ),
|
||||||
|
new ParameterDefn<bool>("ShouldUseBulletHACD", "If true, use the Bullet version of HACD",
|
||||||
|
false,
|
||||||
|
(s) => { return ShouldUseBulletHACD; },
|
||||||
|
(s,v) => { ShouldUseBulletHACD = v; } ),
|
||||||
|
|
||||||
new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions",
|
new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions",
|
||||||
5,
|
5,
|
||||||
|
@ -663,10 +677,47 @@ public static class BSParam
|
||||||
(s) => { return CSHullMaxVertices; },
|
(s) => { return CSHullMaxVertices; },
|
||||||
(s,v) => { CSHullMaxVertices = v; } ),
|
(s,v) => { CSHullMaxVertices = v; } ),
|
||||||
new ParameterDefn<float>("CSHullMaxSkinWidth", "CS impl: skin width to apply to output hulls.",
|
new ParameterDefn<float>("CSHullMaxSkinWidth", "CS impl: skin width to apply to output hulls.",
|
||||||
0,
|
0f,
|
||||||
(s) => { return CSHullMaxSkinWidth; },
|
(s) => { return CSHullMaxSkinWidth; },
|
||||||
(s,v) => { CSHullMaxSkinWidth = v; } ),
|
(s,v) => { CSHullMaxSkinWidth = v; } ),
|
||||||
|
|
||||||
|
new ParameterDefn<float>("BHullMaxVerticesPerHull", "Bullet impl: max number of vertices per created hull",
|
||||||
|
100f,
|
||||||
|
(s) => { return BHullMaxVerticesPerHull; },
|
||||||
|
(s,v) => { BHullMaxVerticesPerHull = v; } ),
|
||||||
|
new ParameterDefn<float>("BHullMinClusters", "Bullet impl: minimum number of hulls to create per mesh",
|
||||||
|
2f,
|
||||||
|
(s) => { return BHullMinClusters; },
|
||||||
|
(s,v) => { BHullMinClusters = v; } ),
|
||||||
|
new ParameterDefn<float>("BHullCompacityWeight", "Bullet impl: weight factor for how compact to make hulls",
|
||||||
|
2f,
|
||||||
|
(s) => { return BHullCompacityWeight; },
|
||||||
|
(s,v) => { BHullCompacityWeight = v; } ),
|
||||||
|
new ParameterDefn<float>("BHullVolumeWeight", "Bullet impl: weight factor for volume in created hull",
|
||||||
|
0.1f,
|
||||||
|
(s) => { return BHullVolumeWeight; },
|
||||||
|
(s,v) => { BHullVolumeWeight = v; } ),
|
||||||
|
new ParameterDefn<float>("BHullConcavity", "Bullet impl: weight factor for how convex a created hull can be",
|
||||||
|
100f,
|
||||||
|
(s) => { return BHullConcavity; },
|
||||||
|
(s,v) => { BHullConcavity = v; } ),
|
||||||
|
new ParameterDefn<bool>("BHullAddExtraDistPoints", "Bullet impl: whether to add extra vertices for long distance vectors",
|
||||||
|
false,
|
||||||
|
(s) => { return BHullAddExtraDistPoints; },
|
||||||
|
(s,v) => { BHullAddExtraDistPoints = v; } ),
|
||||||
|
new ParameterDefn<bool>("BHullAddNeighboursDistPoints", "Bullet impl: whether to add extra vertices between neighbor hulls",
|
||||||
|
false,
|
||||||
|
(s) => { return BHullAddNeighboursDistPoints; },
|
||||||
|
(s,v) => { BHullAddNeighboursDistPoints = v; } ),
|
||||||
|
new ParameterDefn<bool>("BHullAddFacesPoints", "Bullet impl: whether to add extra vertices to break up hull faces",
|
||||||
|
false,
|
||||||
|
(s) => { return BHullAddFacesPoints; },
|
||||||
|
(s,v) => { BHullAddFacesPoints = v; } ),
|
||||||
|
new ParameterDefn<bool>("BHullShouldAdjustCollisionMargin", "Bullet impl: whether to shrink resulting hulls to account for collision margin",
|
||||||
|
false,
|
||||||
|
(s) => { return BHullShouldAdjustCollisionMargin; },
|
||||||
|
(s,v) => { BHullShouldAdjustCollisionMargin = v; } ),
|
||||||
|
|
||||||
new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
|
new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
|
||||||
(float)BSLinkset.LinksetImplementation.Compound,
|
(float)BSLinkset.LinksetImplementation.Compound,
|
||||||
(s) => { return LinksetImplementation; },
|
(s) => { return LinksetImplementation; },
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
* VariableName: used by the simulator and performs taint operations, etc
|
* VariableName: used by the simulator and performs taint operations, etc
|
||||||
* RawVariableName: direct reference to the BulletSim storage for the variable value
|
* RawVariableName: direct reference to the BulletSim storage for the variable value
|
||||||
* ForceVariableName: direct reference (store and fetch) to the value in the physics engine.
|
* ForceVariableName: direct reference (store and fetch) to the value in the physics engine.
|
||||||
* The last two (and certainly the last one) should be referenced only in taint-time.
|
* The last one should only be referenced in taint-time.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -84,6 +84,7 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
// Initialize variables kept in base.
|
// Initialize variables kept in base.
|
||||||
GravModifier = 1.0f;
|
GravModifier = 1.0f;
|
||||||
Gravity = new OMV.Vector3(0f, 0f, BSParam.Gravity);
|
Gravity = new OMV.Vector3(0f, 0f, BSParam.Gravity);
|
||||||
|
HoverActive = false;
|
||||||
|
|
||||||
// We don't have any physical representation yet.
|
// We don't have any physical representation yet.
|
||||||
PhysBody = new BulletBody(localID);
|
PhysBody = new BulletBody(localID);
|
||||||
|
@ -110,11 +111,10 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
// Tell the object to clean up.
|
// Tell the object to clean up.
|
||||||
public virtual void Destroy()
|
public virtual void Destroy()
|
||||||
{
|
{
|
||||||
UnRegisterAllPreStepActions();
|
PhysicalActors.Enable(false);
|
||||||
UnRegisterAllPostStepActions();
|
|
||||||
PhysicsScene.TaintedObject("BSPhysObject.Destroy", delegate()
|
PhysicsScene.TaintedObject("BSPhysObject.Destroy", delegate()
|
||||||
{
|
{
|
||||||
PhysicalActors.Release();
|
PhysicalActors.Dispose();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,15 +203,48 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
public abstract OMV.Quaternion RawOrientation { get; set; }
|
public abstract OMV.Quaternion RawOrientation { get; set; }
|
||||||
public abstract OMV.Quaternion ForceOrientation { get; set; }
|
public abstract OMV.Quaternion ForceOrientation { get; set; }
|
||||||
|
|
||||||
public abstract OMV.Vector3 RawVelocity { get; set; }
|
public OMV.Vector3 RawVelocity { get; set; }
|
||||||
public abstract OMV.Vector3 ForceVelocity { get; set; }
|
public abstract OMV.Vector3 ForceVelocity { get; set; }
|
||||||
|
|
||||||
|
public OMV.Vector3 RawForce { get; set; }
|
||||||
|
public OMV.Vector3 RawTorque { get; set; }
|
||||||
|
public override void AddAngularForce(OMV.Vector3 force, bool pushforce)
|
||||||
|
{
|
||||||
|
AddAngularForce(force, pushforce, false);
|
||||||
|
}
|
||||||
|
public abstract void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime);
|
||||||
|
|
||||||
public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
|
public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
|
||||||
|
|
||||||
public abstract float ForceBuoyancy { get; set; }
|
public abstract float ForceBuoyancy { get; set; }
|
||||||
|
|
||||||
public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
|
public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
|
||||||
|
|
||||||
|
public override bool PIDActive { set { MoveToTargetActive = value; } }
|
||||||
|
public override OMV.Vector3 PIDTarget { set { MoveToTargetTarget = value; } }
|
||||||
|
public override float PIDTau { set { MoveToTargetTau = value; } }
|
||||||
|
|
||||||
|
public bool MoveToTargetActive { get; set; }
|
||||||
|
public OMV.Vector3 MoveToTargetTarget { get; set; }
|
||||||
|
public float MoveToTargetTau { get; set; }
|
||||||
|
|
||||||
|
// Used for llSetHoverHeight and maybe vehicle height. Hover Height will override MoveTo target's Z
|
||||||
|
public override bool PIDHoverActive { set { HoverActive = value; } }
|
||||||
|
public override float PIDHoverHeight { set { HoverHeight = value; } }
|
||||||
|
public override PIDHoverType PIDHoverType { set { HoverType = value; } }
|
||||||
|
public override float PIDHoverTau { set { HoverTau = value; } }
|
||||||
|
|
||||||
|
public bool HoverActive { get; set; }
|
||||||
|
public float HoverHeight { get; set; }
|
||||||
|
public PIDHoverType HoverType { get; set; }
|
||||||
|
public float HoverTau { get; set; }
|
||||||
|
|
||||||
|
// For RotLookAt
|
||||||
|
public override OMV.Quaternion APIDTarget { set { return; } }
|
||||||
|
public override bool APIDActive { set { return; } }
|
||||||
|
public override float APIDStrength { set { return; } }
|
||||||
|
public override float APIDDamping { set { return; } }
|
||||||
|
|
||||||
// The current velocity forward
|
// The current velocity forward
|
||||||
public virtual float ForwardSpeed
|
public virtual float ForwardSpeed
|
||||||
{
|
{
|
||||||
|
@ -237,7 +270,51 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
|
|
||||||
public OMV.Vector3 LockedAxis { get; set; } // zero means locked. one means free.
|
public OMV.Vector3 LockedAxis { get; set; } // zero means locked. one means free.
|
||||||
public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(1f, 1f, 1f); // All axis are free
|
public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(1f, 1f, 1f); // All axis are free
|
||||||
public readonly String LockedAxisActorName = "BSPrim.LockedAxis";
|
|
||||||
|
// Enable physical actions. Bullet will keep sleeping non-moving physical objects so
|
||||||
|
// they need waking up when parameters are changed.
|
||||||
|
// Called in taint-time!!
|
||||||
|
public void ActivateIfPhysical(bool forceIt)
|
||||||
|
{
|
||||||
|
if (IsPhysical && PhysBody.HasPhysicalBody)
|
||||||
|
PhysicsScene.PE.Activate(PhysBody, forceIt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'actors' act on the physical object to change or constrain its motion. These can range from
|
||||||
|
// hovering to complex vehicle motion.
|
||||||
|
// May be called at non-taint time as this just adds the actor to the action list and the real
|
||||||
|
// work is done during the simulation step.
|
||||||
|
// Note that, if the actor is already in the list and we are disabling same, the actor is just left
|
||||||
|
// in the list disabled.
|
||||||
|
public delegate BSActor CreateActor();
|
||||||
|
public void EnableActor(bool enableActor, string actorName, CreateActor creator)
|
||||||
|
{
|
||||||
|
lock (PhysicalActors)
|
||||||
|
{
|
||||||
|
BSActor theActor;
|
||||||
|
if (PhysicalActors.TryGetActor(actorName, out theActor))
|
||||||
|
{
|
||||||
|
// The actor already exists so just turn it on or off
|
||||||
|
DetailLog("{0},BSPhysObject.EnableActor,enablingExistingActor,name={1},enable={2}", LocalID, actorName, enableActor);
|
||||||
|
theActor.Enabled = enableActor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The actor does not exist. If it should, create it.
|
||||||
|
if (enableActor)
|
||||||
|
{
|
||||||
|
DetailLog("{0},BSPhysObject.EnableActor,creatingActor,name={1}", LocalID, actorName);
|
||||||
|
theActor = creator();
|
||||||
|
PhysicalActors.Add(actorName, theActor);
|
||||||
|
theActor.Enabled = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DetailLog("{0},BSPhysObject.EnableActor,notCreatingActorSinceNotEnabled,name={1}", LocalID, actorName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#region Collisions
|
#region Collisions
|
||||||
|
|
||||||
|
@ -255,7 +332,9 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
protected CollisionFlags CurrentCollisionFlags { get; set; }
|
protected CollisionFlags CurrentCollisionFlags { get; set; }
|
||||||
// On a collision, check the collider and remember if the last collider was moving
|
// On a collision, check the collider and remember if the last collider was moving
|
||||||
// Used to modify the standing of avatars (avatars on stationary things stand still)
|
// Used to modify the standing of avatars (avatars on stationary things stand still)
|
||||||
protected bool ColliderIsMoving;
|
public bool ColliderIsMoving;
|
||||||
|
// Used by BSCharacter to manage standing (and not slipping)
|
||||||
|
public bool IsStationary;
|
||||||
|
|
||||||
// Count of collisions for this object
|
// Count of collisions for this object
|
||||||
protected long CollisionAccumulation { get; set; }
|
protected long CollisionAccumulation { get; set; }
|
||||||
|
@ -293,7 +372,7 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
protected CollisionEventUpdate CollisionCollection;
|
protected CollisionEventUpdate CollisionCollection;
|
||||||
// Remember collisions from last tick for fancy collision based actions
|
// Remember collisions from last tick for fancy collision based actions
|
||||||
// (like a BSCharacter walking up stairs).
|
// (like a BSCharacter walking up stairs).
|
||||||
protected CollisionEventUpdate CollisionsLastTick;
|
public CollisionEventUpdate CollisionsLastTick;
|
||||||
|
|
||||||
// The simulation step is telling this object about a collision.
|
// The simulation step is telling this object about a collision.
|
||||||
// Return 'true' if a collision was processed and should be sent up.
|
// Return 'true' if a collision was processed and should be sent up.
|
||||||
|
@ -424,104 +503,6 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
|
|
||||||
public BSActorCollection PhysicalActors;
|
public BSActorCollection PhysicalActors;
|
||||||
|
|
||||||
// There are some actions that must be performed for a physical object before each simulation step.
|
|
||||||
// These actions are optional so, rather than scanning all the physical objects and asking them
|
|
||||||
// if they have anything to do, a physical object registers for an event call before the step is performed.
|
|
||||||
// This bookkeeping makes it easy to add, remove and clean up after all these registrations.
|
|
||||||
private Dictionary<string, BSScene.PreStepAction> RegisteredPrestepActions = new Dictionary<string, BSScene.PreStepAction>();
|
|
||||||
private Dictionary<string, BSScene.PostStepAction> RegisteredPoststepActions = new Dictionary<string, BSScene.PostStepAction>();
|
|
||||||
protected void RegisterPreStepAction(string op, uint id, BSScene.PreStepAction actn)
|
|
||||||
{
|
|
||||||
string identifier = op + "-" + id.ToString();
|
|
||||||
|
|
||||||
lock (RegisteredPrestepActions)
|
|
||||||
{
|
|
||||||
// Clean out any existing action
|
|
||||||
UnRegisterPreStepAction(op, id);
|
|
||||||
RegisteredPrestepActions[identifier] = actn;
|
|
||||||
PhysicsScene.BeforeStep += actn;
|
|
||||||
}
|
|
||||||
DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unregister a pre step action. Safe to call if the action has not been registered.
|
|
||||||
// Returns 'true' if an action was actually removed
|
|
||||||
protected bool UnRegisterPreStepAction(string op, uint id)
|
|
||||||
{
|
|
||||||
string identifier = op + "-" + id.ToString();
|
|
||||||
bool removed = false;
|
|
||||||
lock (RegisteredPrestepActions)
|
|
||||||
{
|
|
||||||
if (RegisteredPrestepActions.ContainsKey(identifier))
|
|
||||||
{
|
|
||||||
PhysicsScene.BeforeStep -= RegisteredPrestepActions[identifier];
|
|
||||||
RegisteredPrestepActions.Remove(identifier);
|
|
||||||
removed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DetailLog("{0},BSPhysObject.UnRegisterPreStepAction,id={1},removed={2}", LocalID, identifier, removed);
|
|
||||||
return removed;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void UnRegisterAllPreStepActions()
|
|
||||||
{
|
|
||||||
lock (RegisteredPrestepActions)
|
|
||||||
{
|
|
||||||
foreach (KeyValuePair<string, BSScene.PreStepAction> kvp in RegisteredPrestepActions)
|
|
||||||
{
|
|
||||||
PhysicsScene.BeforeStep -= kvp.Value;
|
|
||||||
}
|
|
||||||
RegisteredPrestepActions.Clear();
|
|
||||||
}
|
|
||||||
DetailLog("{0},BSPhysObject.UnRegisterAllPreStepActions,", LocalID);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void RegisterPostStepAction(string op, uint id, BSScene.PostStepAction actn)
|
|
||||||
{
|
|
||||||
string identifier = op + "-" + id.ToString();
|
|
||||||
|
|
||||||
lock (RegisteredPoststepActions)
|
|
||||||
{
|
|
||||||
// Clean out any existing action
|
|
||||||
UnRegisterPostStepAction(op, id);
|
|
||||||
RegisteredPoststepActions[identifier] = actn;
|
|
||||||
PhysicsScene.AfterStep += actn;
|
|
||||||
}
|
|
||||||
DetailLog("{0},BSPhysObject.RegisterPostStepAction,id={1}", LocalID, identifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unregister a pre step action. Safe to call if the action has not been registered.
|
|
||||||
// Returns 'true' if an action was actually removed.
|
|
||||||
protected bool UnRegisterPostStepAction(string op, uint id)
|
|
||||||
{
|
|
||||||
string identifier = op + "-" + id.ToString();
|
|
||||||
bool removed = false;
|
|
||||||
lock (RegisteredPoststepActions)
|
|
||||||
{
|
|
||||||
if (RegisteredPoststepActions.ContainsKey(identifier))
|
|
||||||
{
|
|
||||||
PhysicsScene.AfterStep -= RegisteredPoststepActions[identifier];
|
|
||||||
RegisteredPoststepActions.Remove(identifier);
|
|
||||||
removed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DetailLog("{0},BSPhysObject.UnRegisterPostStepAction,id={1},removed={2}", LocalID, identifier, removed);
|
|
||||||
return removed;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void UnRegisterAllPostStepActions()
|
|
||||||
{
|
|
||||||
lock (RegisteredPoststepActions)
|
|
||||||
{
|
|
||||||
foreach (KeyValuePair<string, BSScene.PostStepAction> kvp in RegisteredPoststepActions)
|
|
||||||
{
|
|
||||||
PhysicsScene.AfterStep -= kvp.Value;
|
|
||||||
}
|
|
||||||
RegisteredPoststepActions.Clear();
|
|
||||||
}
|
|
||||||
DetailLog("{0},BSPhysObject.UnRegisterAllPostStepActions,", LocalID);
|
|
||||||
}
|
|
||||||
|
|
||||||
// When an update to the physical properties happens, this event is fired to let
|
// When an update to the physical properties happens, this event is fired to let
|
||||||
// different actors to modify the update before it is passed around
|
// different actors to modify the update before it is passed around
|
||||||
public delegate void PreUpdatePropertyAction(ref EntityProperties entprop);
|
public delegate void PreUpdatePropertyAction(ref EntityProperties entprop);
|
||||||
|
@ -533,46 +514,6 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
actions(ref entprop);
|
actions(ref entprop);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dictionary<string, PreUpdatePropertyAction> RegisteredPreUpdatePropertyActions = new Dictionary<string, PreUpdatePropertyAction>();
|
|
||||||
public void RegisterPreUpdatePropertyAction(string identifier, PreUpdatePropertyAction actn)
|
|
||||||
{
|
|
||||||
lock (RegisteredPreUpdatePropertyActions)
|
|
||||||
{
|
|
||||||
// Clean out any existing action
|
|
||||||
UnRegisterPreUpdatePropertyAction(identifier);
|
|
||||||
RegisteredPreUpdatePropertyActions[identifier] = actn;
|
|
||||||
OnPreUpdateProperty += actn;
|
|
||||||
}
|
|
||||||
DetailLog("{0},BSPhysObject.RegisterPreUpdatePropertyAction,id={1}", LocalID, identifier);
|
|
||||||
}
|
|
||||||
public bool UnRegisterPreUpdatePropertyAction(string identifier)
|
|
||||||
{
|
|
||||||
bool removed = false;
|
|
||||||
lock (RegisteredPreUpdatePropertyActions)
|
|
||||||
{
|
|
||||||
if (RegisteredPreUpdatePropertyActions.ContainsKey(identifier))
|
|
||||||
{
|
|
||||||
OnPreUpdateProperty -= RegisteredPreUpdatePropertyActions[identifier];
|
|
||||||
RegisteredPreUpdatePropertyActions.Remove(identifier);
|
|
||||||
removed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DetailLog("{0},BSPhysObject.UnRegisterPreUpdatePropertyAction,id={1},removed={2}", LocalID, identifier, removed);
|
|
||||||
return removed;
|
|
||||||
}
|
|
||||||
public void UnRegisterAllPreUpdatePropertyActions()
|
|
||||||
{
|
|
||||||
lock (RegisteredPreUpdatePropertyActions)
|
|
||||||
{
|
|
||||||
foreach (KeyValuePair<string, PreUpdatePropertyAction> kvp in RegisteredPreUpdatePropertyActions)
|
|
||||||
{
|
|
||||||
OnPreUpdateProperty -= kvp.Value;
|
|
||||||
}
|
|
||||||
RegisteredPreUpdatePropertyActions.Clear();
|
|
||||||
}
|
|
||||||
DetailLog("{0},BSPhysObject.UnRegisterAllPreUpdatePropertyAction,", LocalID);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion // Per Simulation Step actions
|
#endregion // Per Simulation Step actions
|
||||||
|
|
||||||
// High performance detailed logging routine used by the physical objects.
|
// High performance detailed logging routine used by the physical objects.
|
||||||
|
|
|
@ -55,9 +55,6 @@ public class BSPrim : BSPhysObject
|
||||||
private OMV.Vector3 _position;
|
private OMV.Vector3 _position;
|
||||||
|
|
||||||
private float _mass; // the mass of this object
|
private float _mass; // the mass of this object
|
||||||
private OMV.Vector3 _force;
|
|
||||||
private OMV.Vector3 _velocity;
|
|
||||||
private OMV.Vector3 _torque;
|
|
||||||
private OMV.Vector3 _acceleration;
|
private OMV.Vector3 _acceleration;
|
||||||
private OMV.Quaternion _orientation;
|
private OMV.Quaternion _orientation;
|
||||||
private int _physicsActorType;
|
private int _physicsActorType;
|
||||||
|
@ -73,16 +70,13 @@ public class BSPrim : BSPhysObject
|
||||||
private int CrossingFailures { get; set; }
|
private int CrossingFailures { get; set; }
|
||||||
|
|
||||||
public BSDynamics VehicleActor;
|
public BSDynamics VehicleActor;
|
||||||
public string VehicleActorName = "BasicVehicle";
|
public const string VehicleActorName = "BasicVehicle";
|
||||||
|
|
||||||
private BSVMotor _targetMotor;
|
public const string HoverActorName = "HoverActor";
|
||||||
private OMV.Vector3 _PIDTarget;
|
public const String LockedAxisActorName = "BSPrim.LockedAxis";
|
||||||
private float _PIDTau;
|
public const string MoveToTargetActorName = "MoveToTargetActor";
|
||||||
|
public const string SetForceActorName = "SetForceActor";
|
||||||
private BSFMotor _hoverMotor;
|
public const string SetTorqueActorName = "SetTorqueActor";
|
||||||
private float _PIDHoverHeight;
|
|
||||||
private PIDHoverType _PIDHoverType;
|
|
||||||
private float _PIDHoverTau;
|
|
||||||
|
|
||||||
public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
|
public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
|
||||||
OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
|
OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
|
||||||
|
@ -95,12 +89,13 @@ public class BSPrim : BSPhysObject
|
||||||
Scale = size; // prims are the size the user wants them to be (different for BSCharactes).
|
Scale = size; // prims are the size the user wants them to be (different for BSCharactes).
|
||||||
_orientation = rotation;
|
_orientation = rotation;
|
||||||
_buoyancy = 0f;
|
_buoyancy = 0f;
|
||||||
_velocity = OMV.Vector3.Zero;
|
RawVelocity = OMV.Vector3.Zero;
|
||||||
_rotationalVelocity = OMV.Vector3.Zero;
|
_rotationalVelocity = OMV.Vector3.Zero;
|
||||||
BaseShape = pbs;
|
BaseShape = pbs;
|
||||||
_isPhysical = pisPhysical;
|
_isPhysical = pisPhysical;
|
||||||
_isVolumeDetect = false;
|
_isVolumeDetect = false;
|
||||||
|
|
||||||
|
// We keep a handle to the vehicle actor so we can set vehicle parameters later.
|
||||||
VehicleActor = new BSDynamics(PhysicsScene, this, VehicleActorName);
|
VehicleActor = new BSDynamics(PhysicsScene, this, VehicleActorName);
|
||||||
PhysicalActors.Add(VehicleActorName, VehicleActor);
|
PhysicalActors.Add(VehicleActorName, VehicleActor);
|
||||||
|
|
||||||
|
@ -233,7 +228,7 @@ public class BSPrim : BSPhysObject
|
||||||
// Called at taint time!
|
// Called at taint time!
|
||||||
public override void ZeroMotion(bool inTaintTime)
|
public override void ZeroMotion(bool inTaintTime)
|
||||||
{
|
{
|
||||||
_velocity = OMV.Vector3.Zero;
|
RawVelocity = OMV.Vector3.Zero;
|
||||||
_acceleration = OMV.Vector3.Zero;
|
_acceleration = OMV.Vector3.Zero;
|
||||||
_rotationalVelocity = OMV.Vector3.Zero;
|
_rotationalVelocity = OMV.Vector3.Zero;
|
||||||
|
|
||||||
|
@ -270,19 +265,17 @@ public class BSPrim : BSPhysObject
|
||||||
if (axis.Z != 1) locking.Z = 0f;
|
if (axis.Z != 1) locking.Z = 0f;
|
||||||
LockedAxis = locking;
|
LockedAxis = locking;
|
||||||
|
|
||||||
if (LockedAxis != LockedAxisFree)
|
EnableActor(LockedAxis != LockedAxisFree, LockedAxisActorName, delegate()
|
||||||
{
|
{
|
||||||
PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate()
|
return new BSActorLockAxis(PhysicsScene, this, LockedAxisActorName);
|
||||||
{
|
});
|
||||||
// If there is not already an axis locker, make one
|
|
||||||
if (!PhysicalActors.HasActor(LockedAxisActorName))
|
// Update parameters so the new actor's Refresh() action is called at the right time.
|
||||||
{
|
PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate()
|
||||||
DetailLog("{0},BSPrim.LockAngularMotion,taint,registeringLockAxisActor", LocalID);
|
{
|
||||||
PhysicalActors.Add(LockedAxisActorName, new BSActorLockAxis(PhysicsScene, this, LockedAxisActorName));
|
UpdatePhysicalParameters();
|
||||||
}
|
});
|
||||||
UpdatePhysicalParameters();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,9 +400,9 @@ public class BSPrim : BSPhysObject
|
||||||
ZeroMotion(inTaintTime);
|
ZeroMotion(inTaintTime);
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
if (_velocity.LengthSquared() > BSParam.MaxLinearVelocity)
|
if (RawVelocity.LengthSquared() > BSParam.MaxLinearVelocity)
|
||||||
{
|
{
|
||||||
_velocity = Util.ClampV(_velocity, BSParam.MaxLinearVelocity);
|
RawVelocity = Util.ClampV(RawVelocity, BSParam.MaxLinearVelocity);
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
if (_rotationalVelocity.LengthSquared() > BSParam.MaxAngularVelocitySquared)
|
if (_rotationalVelocity.LengthSquared() > BSParam.MaxAngularVelocitySquared)
|
||||||
|
@ -506,48 +499,25 @@ public class BSPrim : BSPhysObject
|
||||||
}
|
}
|
||||||
|
|
||||||
public override OMV.Vector3 Force {
|
public override OMV.Vector3 Force {
|
||||||
get { return _force; }
|
get { return RawForce; }
|
||||||
set {
|
set {
|
||||||
_force = value;
|
RawForce = value;
|
||||||
if (_force != OMV.Vector3.Zero)
|
EnableActor(RawForce != OMV.Vector3.Zero, SetForceActorName, delegate()
|
||||||
{
|
{
|
||||||
// If the force is non-zero, it must be reapplied each tick because
|
return new BSActorSetForce(PhysicsScene, this, SetForceActorName);
|
||||||
// Bullet clears the forces applied last frame.
|
});
|
||||||
RegisterPreStepAction("BSPrim.setForce", LocalID,
|
|
||||||
delegate(float timeStep)
|
|
||||||
{
|
|
||||||
if (!IsPhysicallyActive || _force == OMV.Vector3.Zero)
|
|
||||||
{
|
|
||||||
UnRegisterPreStepAction("BSPrim.setForce", LocalID);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DetailLog("{0},BSPrim.setForce,preStep,force={1}", LocalID, _force);
|
|
||||||
if (PhysBody.HasPhysicalBody)
|
|
||||||
{
|
|
||||||
PhysicsScene.PE.ApplyCentralForce(PhysBody, _force);
|
|
||||||
ActivateIfPhysical(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UnRegisterPreStepAction("BSPrim.setForce", LocalID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int VehicleType {
|
public override int VehicleType {
|
||||||
get {
|
get {
|
||||||
return (int)VehicleActor.Type; // if we are a vehicle, return that type
|
return (int)VehicleActor.Type;
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
Vehicle type = (Vehicle)value;
|
Vehicle type = (Vehicle)value;
|
||||||
|
|
||||||
PhysicsScene.TaintedObject("setVehicleType", delegate()
|
PhysicsScene.TaintedObject("setVehicleType", delegate()
|
||||||
{
|
{
|
||||||
// Done at taint time so we're sure the physics engine is not using the variables
|
|
||||||
// Vehicle code changes the parameters for this vehicle type.
|
// Vehicle code changes the parameters for this vehicle type.
|
||||||
VehicleActor.ProcessTypeChange(type);
|
VehicleActor.ProcessTypeChange(type);
|
||||||
ActivateIfPhysical(false);
|
ActivateIfPhysical(false);
|
||||||
|
@ -670,63 +640,40 @@ public class BSPrim : BSPhysObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public override OMV.Vector3 RawVelocity
|
|
||||||
{
|
|
||||||
get { return _velocity; }
|
|
||||||
set { _velocity = value; }
|
|
||||||
}
|
|
||||||
public override OMV.Vector3 Velocity {
|
public override OMV.Vector3 Velocity {
|
||||||
get { return _velocity; }
|
get { return RawVelocity; }
|
||||||
set {
|
set {
|
||||||
_velocity = value;
|
RawVelocity = value;
|
||||||
PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate()
|
PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate()
|
||||||
{
|
{
|
||||||
// DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
|
// DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, RawVelocity);
|
||||||
ForceVelocity = _velocity;
|
ForceVelocity = RawVelocity;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public override OMV.Vector3 ForceVelocity {
|
public override OMV.Vector3 ForceVelocity {
|
||||||
get { return _velocity; }
|
get { return RawVelocity; }
|
||||||
set {
|
set {
|
||||||
PhysicsScene.AssertInTaintTime("BSPrim.ForceVelocity");
|
PhysicsScene.AssertInTaintTime("BSPrim.ForceVelocity");
|
||||||
|
|
||||||
_velocity = Util.ClampV(value, BSParam.MaxLinearVelocity);
|
RawVelocity = Util.ClampV(value, BSParam.MaxLinearVelocity);
|
||||||
if (PhysBody.HasPhysicalBody)
|
if (PhysBody.HasPhysicalBody)
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, _velocity);
|
DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, RawVelocity);
|
||||||
PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity);
|
PhysicsScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
|
||||||
ActivateIfPhysical(false);
|
ActivateIfPhysical(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public override OMV.Vector3 Torque {
|
public override OMV.Vector3 Torque {
|
||||||
get { return _torque; }
|
get { return RawTorque; }
|
||||||
set {
|
set {
|
||||||
_torque = value;
|
RawTorque = value;
|
||||||
if (_torque != OMV.Vector3.Zero)
|
EnableActor(RawTorque != OMV.Vector3.Zero, SetTorqueActorName, delegate()
|
||||||
{
|
{
|
||||||
// If the torque is non-zero, it must be reapplied each tick because
|
return new BSActorSetTorque(PhysicsScene, this, SetTorqueActorName);
|
||||||
// Bullet clears the forces applied last frame.
|
});
|
||||||
RegisterPreStepAction("BSPrim.setTorque", LocalID,
|
DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, RawTorque);
|
||||||
delegate(float timeStep)
|
|
||||||
{
|
|
||||||
if (!IsPhysicallyActive || _torque == OMV.Vector3.Zero)
|
|
||||||
{
|
|
||||||
UnRegisterPreStepAction("BSPrim.setTorque", LocalID);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PhysBody.HasPhysicalBody)
|
|
||||||
AddAngularForce(_torque, false, true);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UnRegisterPreStepAction("BSPrim.setTorque", LocalID);
|
|
||||||
}
|
|
||||||
// DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public override OMV.Vector3 Acceleration {
|
public override OMV.Vector3 Acceleration {
|
||||||
|
@ -839,7 +786,6 @@ public class BSPrim : BSPhysObject
|
||||||
MakeDynamic(IsStatic);
|
MakeDynamic(IsStatic);
|
||||||
|
|
||||||
// Update vehicle specific parameters (after MakeDynamic() so can change physical parameters)
|
// Update vehicle specific parameters (after MakeDynamic() so can change physical parameters)
|
||||||
VehicleActor.Refresh();
|
|
||||||
PhysicalActors.Refresh();
|
PhysicalActors.Refresh();
|
||||||
|
|
||||||
// Arrange for collision events if the simulator wants them
|
// Arrange for collision events if the simulator wants them
|
||||||
|
@ -909,7 +855,7 @@ public class BSPrim : BSPhysObject
|
||||||
|
|
||||||
// For good measure, make sure the transform is set through to the motion state
|
// For good measure, make sure the transform is set through to the motion state
|
||||||
ForcePosition = _position;
|
ForcePosition = _position;
|
||||||
ForceVelocity = _velocity;
|
ForceVelocity = RawVelocity;
|
||||||
ForceRotationalVelocity = _rotationalVelocity;
|
ForceRotationalVelocity = _rotationalVelocity;
|
||||||
|
|
||||||
// A dynamic object has mass
|
// A dynamic object has mass
|
||||||
|
@ -966,15 +912,6 @@ public class BSPrim : BSPhysObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable physical actions. Bullet will keep sleeping non-moving physical objects so
|
|
||||||
// they need waking up when parameters are changed.
|
|
||||||
// Called in taint-time!!
|
|
||||||
private void ActivateIfPhysical(bool forceIt)
|
|
||||||
{
|
|
||||||
if (IsPhysical && PhysBody.HasPhysicalBody)
|
|
||||||
PhysicsScene.PE.Activate(PhysBody, forceIt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Turn on or off the flag controlling whether collision events are returned to the simulator.
|
// Turn on or off the flag controlling whether collision events are returned to the simulator.
|
||||||
private void EnableCollisions(bool wantsCollisionEvents)
|
private void EnableCollisions(bool wantsCollisionEvents)
|
||||||
{
|
{
|
||||||
|
@ -1096,78 +1033,13 @@ public class BSPrim : BSPhysObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used for MoveTo
|
|
||||||
public override OMV.Vector3 PIDTarget {
|
|
||||||
set
|
|
||||||
{
|
|
||||||
// TODO: add a sanity check -- don't move more than a region or something like that.
|
|
||||||
_PIDTarget = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override float PIDTau {
|
|
||||||
set { _PIDTau = value; }
|
|
||||||
}
|
|
||||||
public override bool PIDActive {
|
public override bool PIDActive {
|
||||||
set {
|
set {
|
||||||
if (value)
|
base.MoveToTargetActive = value;
|
||||||
|
EnableActor(MoveToTargetActive, MoveToTargetActorName, delegate()
|
||||||
{
|
{
|
||||||
// We're taking over after this.
|
return new BSActorMoveToTarget(PhysicsScene, this, MoveToTargetActorName);
|
||||||
ZeroMotion(true);
|
});
|
||||||
|
|
||||||
_targetMotor = new BSVMotor("BSPrim.PIDTarget",
|
|
||||||
_PIDTau, // timeScale
|
|
||||||
BSMotor.Infinite, // decay time scale
|
|
||||||
BSMotor.InfiniteVector, // friction timescale
|
|
||||||
1f // efficiency
|
|
||||||
);
|
|
||||||
_targetMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
|
|
||||||
_targetMotor.SetTarget(_PIDTarget);
|
|
||||||
_targetMotor.SetCurrent(RawPosition);
|
|
||||||
/*
|
|
||||||
_targetMotor = new BSPIDVMotor("BSPrim.PIDTarget");
|
|
||||||
_targetMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
|
|
||||||
|
|
||||||
_targetMotor.SetTarget(_PIDTarget);
|
|
||||||
_targetMotor.SetCurrent(RawPosition);
|
|
||||||
_targetMotor.TimeScale = _PIDTau;
|
|
||||||
_targetMotor.Efficiency = 1f;
|
|
||||||
*/
|
|
||||||
|
|
||||||
RegisterPreStepAction("BSPrim.PIDTarget", LocalID, delegate(float timeStep)
|
|
||||||
{
|
|
||||||
if (!IsPhysicallyActive)
|
|
||||||
{
|
|
||||||
UnRegisterPreStepAction("BSPrim.PIDTarget", LocalID);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
OMV.Vector3 origPosition = RawPosition; // DEBUG DEBUG (for printout below)
|
|
||||||
|
|
||||||
// 'movePosition' is where we'd like the prim to be at this moment.
|
|
||||||
OMV.Vector3 movePosition = RawPosition + _targetMotor.Step(timeStep);
|
|
||||||
|
|
||||||
// If we are very close to our target, turn off the movement motor.
|
|
||||||
if (_targetMotor.ErrorIsZero())
|
|
||||||
{
|
|
||||||
DetailLog("{0},BSPrim.PIDTarget,zeroMovement,movePos={1},pos={2},mass={3}",
|
|
||||||
LocalID, movePosition, RawPosition, Mass);
|
|
||||||
ForcePosition = _targetMotor.TargetValue;
|
|
||||||
_targetMotor.Enabled = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_position = movePosition;
|
|
||||||
PositionSanityCheck(true /* intaintTime */);
|
|
||||||
ForcePosition = _position;
|
|
||||||
}
|
|
||||||
DetailLog("{0},BSPrim.PIDTarget,move,fromPos={1},movePos={2}", LocalID, origPosition, movePosition);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Stop any targetting
|
|
||||||
UnRegisterPreStepAction("BSPrim.PIDTarget", LocalID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1175,87 +1047,13 @@ public class BSPrim : BSPhysObject
|
||||||
// Hover Height will override MoveTo target's Z
|
// Hover Height will override MoveTo target's Z
|
||||||
public override bool PIDHoverActive {
|
public override bool PIDHoverActive {
|
||||||
set {
|
set {
|
||||||
if (value)
|
base.HoverActive = value;
|
||||||
|
EnableActor(HoverActive, HoverActorName, delegate()
|
||||||
{
|
{
|
||||||
// Turning the target on
|
return new BSActorHover(PhysicsScene, this, HoverActorName);
|
||||||
_hoverMotor = new BSFMotor("BSPrim.Hover",
|
});
|
||||||
_PIDHoverTau, // timeScale
|
|
||||||
BSMotor.Infinite, // decay time scale
|
|
||||||
BSMotor.Infinite, // friction timescale
|
|
||||||
1f // efficiency
|
|
||||||
);
|
|
||||||
_hoverMotor.SetTarget(ComputeCurrentPIDHoverHeight());
|
|
||||||
_hoverMotor.SetCurrent(RawPosition.Z);
|
|
||||||
_hoverMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
|
|
||||||
|
|
||||||
RegisterPreStepAction("BSPrim.Hover", LocalID, delegate(float timeStep)
|
|
||||||
{
|
|
||||||
// Don't do hovering while the object is selected.
|
|
||||||
if (!IsPhysicallyActive)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_hoverMotor.SetCurrent(RawPosition.Z);
|
|
||||||
_hoverMotor.SetTarget(ComputeCurrentPIDHoverHeight());
|
|
||||||
float targetHeight = _hoverMotor.Step(timeStep);
|
|
||||||
|
|
||||||
// 'targetHeight' is where we'd like the Z of the prim to be at this moment.
|
|
||||||
// Compute the amount of force to push us there.
|
|
||||||
float moveForce = (targetHeight - RawPosition.Z) * Mass;
|
|
||||||
// Undo anything the object thinks it's doing at the moment
|
|
||||||
moveForce = -RawVelocity.Z * Mass;
|
|
||||||
|
|
||||||
PhysicsScene.PE.ApplyCentralImpulse(PhysBody, new OMV.Vector3(0f, 0f, moveForce));
|
|
||||||
DetailLog("{0},BSPrim.Hover,move,targHt={1},moveForce={2},mass={3}", LocalID, targetHeight, moveForce, Mass);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UnRegisterPreStepAction("BSPrim.Hover", LocalID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public override float PIDHoverHeight {
|
|
||||||
set { _PIDHoverHeight = value; }
|
|
||||||
}
|
|
||||||
public override PIDHoverType PIDHoverType {
|
|
||||||
set { _PIDHoverType = value; }
|
|
||||||
}
|
|
||||||
public override float PIDHoverTau {
|
|
||||||
set { _PIDHoverTau = value; }
|
|
||||||
}
|
|
||||||
// Based on current position, determine what we should be hovering at now.
|
|
||||||
// Must recompute often. What if we walked offa cliff>
|
|
||||||
private float ComputeCurrentPIDHoverHeight()
|
|
||||||
{
|
|
||||||
float ret = _PIDHoverHeight;
|
|
||||||
float groundHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
|
|
||||||
|
|
||||||
switch (_PIDHoverType)
|
|
||||||
{
|
|
||||||
case PIDHoverType.Ground:
|
|
||||||
ret = groundHeight + _PIDHoverHeight;
|
|
||||||
break;
|
|
||||||
case PIDHoverType.GroundAndWater:
|
|
||||||
float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(RawPosition);
|
|
||||||
if (groundHeight > waterHeight)
|
|
||||||
{
|
|
||||||
ret = groundHeight + _PIDHoverHeight;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = waterHeight + _PIDHoverHeight;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// For RotLookAt
|
|
||||||
public override OMV.Quaternion APIDTarget { set { return; } }
|
|
||||||
public override bool APIDActive { set { return; } }
|
|
||||||
public override float APIDStrength { set { return; } }
|
|
||||||
public override float APIDDamping { set { return; } }
|
|
||||||
|
|
||||||
public override void AddForce(OMV.Vector3 force, bool pushforce) {
|
public override void AddForce(OMV.Vector3 force, bool pushforce) {
|
||||||
// Per documentation, max force is limited.
|
// Per documentation, max force is limited.
|
||||||
|
@ -1324,10 +1122,8 @@ public class BSPrim : BSPhysObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
|
// BSPhysObject.AddAngularForce()
|
||||||
AddAngularForce(force, pushforce, false);
|
public override void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime)
|
||||||
}
|
|
||||||
public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime)
|
|
||||||
{
|
{
|
||||||
if (force.IsFinite())
|
if (force.IsFinite())
|
||||||
{
|
{
|
||||||
|
@ -1661,7 +1457,7 @@ public class BSPrim : BSPhysObject
|
||||||
{
|
{
|
||||||
// Create the correct physical representation for this type of object.
|
// Create the correct physical representation for this type of object.
|
||||||
// Updates base.PhysBody and base.PhysShape with the new information.
|
// Updates base.PhysBody and base.PhysShape with the new information.
|
||||||
// Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary.
|
// Ignore 'forceRebuild'. 'GetBodyAndShape' makes the right choices and changes of necessary.
|
||||||
PhysicsScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysicsScene.World, this, null, delegate(BulletBody dBody)
|
PhysicsScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysicsScene.World, this, null, delegate(BulletBody dBody)
|
||||||
{
|
{
|
||||||
// Called if the current prim body is about to be destroyed.
|
// Called if the current prim body is about to be destroyed.
|
||||||
|
@ -1675,9 +1471,9 @@ public class BSPrim : BSPhysObject
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called at taint-time
|
||||||
protected virtual void RemoveBodyDependencies()
|
protected virtual void RemoveBodyDependencies()
|
||||||
{
|
{
|
||||||
VehicleActor.RemoveBodyDependencies();
|
|
||||||
PhysicalActors.RemoveBodyDependencies();
|
PhysicalActors.RemoveBodyDependencies();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1685,6 +1481,7 @@ public class BSPrim : BSPhysObject
|
||||||
// the world that things have changed.
|
// the world that things have changed.
|
||||||
public override void UpdateProperties(EntityProperties entprop)
|
public override void UpdateProperties(EntityProperties entprop)
|
||||||
{
|
{
|
||||||
|
// Let anyone (like the actors) modify the updated properties before they are pushed into the object and the simulator.
|
||||||
TriggerPreUpdatePropertyAction(ref entprop);
|
TriggerPreUpdatePropertyAction(ref entprop);
|
||||||
|
|
||||||
// DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG
|
// DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG
|
||||||
|
@ -1694,8 +1491,8 @@ public class BSPrim : BSPhysObject
|
||||||
_orientation = entprop.Rotation;
|
_orientation = entprop.Rotation;
|
||||||
// DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be
|
// DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be
|
||||||
// very sensitive to velocity changes.
|
// very sensitive to velocity changes.
|
||||||
if (entprop.Velocity == OMV.Vector3.Zero || !entprop.Velocity.ApproxEquals(_velocity, BSParam.UpdateVelocityChangeThreshold))
|
if (entprop.Velocity == OMV.Vector3.Zero || !entprop.Velocity.ApproxEquals(RawVelocity, BSParam.UpdateVelocityChangeThreshold))
|
||||||
_velocity = entprop.Velocity;
|
RawVelocity = entprop.Velocity;
|
||||||
_acceleration = entprop.Acceleration;
|
_acceleration = entprop.Acceleration;
|
||||||
_rotationalVelocity = entprop.RotationalVelocity;
|
_rotationalVelocity = entprop.RotationalVelocity;
|
||||||
|
|
||||||
|
@ -1705,7 +1502,7 @@ public class BSPrim : BSPhysObject
|
||||||
if (PositionSanityCheck(true /* inTaintTime */ ))
|
if (PositionSanityCheck(true /* inTaintTime */ ))
|
||||||
{
|
{
|
||||||
entprop.Position = _position;
|
entprop.Position = _position;
|
||||||
entprop.Velocity = _velocity;
|
entprop.Velocity = RawVelocity;
|
||||||
entprop.RotationalVelocity = _rotationalVelocity;
|
entprop.RotationalVelocity = _rotationalVelocity;
|
||||||
entprop.Acceleration = _acceleration;
|
entprop.Acceleration = _acceleration;
|
||||||
}
|
}
|
||||||
|
@ -1717,16 +1514,8 @@ public class BSPrim : BSPhysObject
|
||||||
LastEntityProperties = CurrentEntityProperties;
|
LastEntityProperties = CurrentEntityProperties;
|
||||||
CurrentEntityProperties = entprop;
|
CurrentEntityProperties = entprop;
|
||||||
|
|
||||||
|
// Note that BSPrim can be overloaded by BSPrimLinkable which controls updates from root and children prims.
|
||||||
base.RequestPhysicsterseUpdate();
|
base.RequestPhysicsterseUpdate();
|
||||||
/*
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// For debugging, report the movement of children
|
|
||||||
DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
|
|
||||||
LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
|
|
||||||
entprop.Acceleration, entprop.RotationalVelocity);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,6 +163,15 @@ public class BSPrimLinkable : BSPrimDisplaced
|
||||||
// TODO: this will have to change when linksets are articulated.
|
// TODO: this will have to change when linksets are articulated.
|
||||||
base.UpdateProperties(entprop);
|
base.UpdateProperties(entprop);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// For debugging, report the movement of children
|
||||||
|
DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
|
||||||
|
LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
|
||||||
|
entprop.Acceleration, entprop.RotationalVelocity);
|
||||||
|
}
|
||||||
|
*/
|
||||||
// The linkset might like to know about changing locations
|
// The linkset might like to know about changing locations
|
||||||
Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this);
|
Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -316,6 +316,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
break;
|
break;
|
||||||
case "bulletxna":
|
case "bulletxna":
|
||||||
ret = new BSAPIXNA(engineName, this);
|
ret = new BSAPIXNA(engineName, this);
|
||||||
|
BSParam.ShouldUseBulletHACD = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -722,7 +722,7 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
// Remove usage of the previous shape.
|
// Remove usage of the previous shape.
|
||||||
DereferenceShape(prim.PhysShape, shapeCallback);
|
DereferenceShape(prim.PhysShape, shapeCallback);
|
||||||
|
|
||||||
newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod);
|
newShape = CreatePhysicalHull(prim, newHullKey, prim.BaseShape, prim.Size, lod);
|
||||||
// It might not have been created if we're waiting for an asset.
|
// It might not have been created if we're waiting for an asset.
|
||||||
newShape = VerifyMeshCreated(newShape, prim);
|
newShape = VerifyMeshCreated(newShape, prim);
|
||||||
|
|
||||||
|
@ -733,7 +733,7 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ConvexResult> m_hulls;
|
List<ConvexResult> m_hulls;
|
||||||
private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
|
private BulletShape CreatePhysicalHull(BSPhysObject prim, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
|
||||||
{
|
{
|
||||||
|
|
||||||
BulletShape newShape = new BulletShape();
|
BulletShape newShape = new BulletShape();
|
||||||
|
@ -747,115 +747,152 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Build a new hull in the physical world.
|
if (BSParam.ShouldUseBulletHACD)
|
||||||
// Pass true for physicalness as this prevents the creation of bounding box which is not needed
|
|
||||||
IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false, false, false);
|
|
||||||
if (meshData != null)
|
|
||||||
{
|
{
|
||||||
|
DetailLog("{0},BSShapeCollection.CreatePhysicalHull,shouldUseBulletHACD,entry", prim.LocalID);
|
||||||
int[] indices = meshData.getIndexListAsInt();
|
MeshDesc meshDesc;
|
||||||
List<OMV.Vector3> vertices = meshData.getVertexList();
|
if (!Meshes.TryGetValue(newHullKey, out meshDesc))
|
||||||
|
|
||||||
//format conversion from IMesh format to DecompDesc format
|
|
||||||
List<int> convIndices = new List<int>();
|
|
||||||
List<float3> convVertices = new List<float3>();
|
|
||||||
for (int ii = 0; ii < indices.GetLength(0); ii++)
|
|
||||||
{
|
{
|
||||||
convIndices.Add(indices[ii]);
|
// That's odd because the mesh should have been created before the hull
|
||||||
}
|
// but, since it doesn't exist, create it.
|
||||||
foreach (OMV.Vector3 vv in vertices)
|
newShape = CreatePhysicalMesh(prim, newHullKey, prim.BaseShape, prim.Size, lod);
|
||||||
{
|
DetailLog("{0},BSShapeCollection.CreatePhysicalHull,noMeshBuiltNew,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
|
||||||
convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
|
if (newShape.HasPhysicalShape)
|
||||||
if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
|
|
||||||
{
|
|
||||||
// Simple primitive shapes we know are convex so they are better implemented with
|
|
||||||
// fewer hulls.
|
|
||||||
// Check for simple shape (prim without cuts) and reduce split parameter if so.
|
|
||||||
if (PrimHasNoCuts(pbs))
|
|
||||||
{
|
{
|
||||||
maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
|
ReferenceShape(newShape);
|
||||||
|
Meshes.TryGetValue(newHullKey, out meshDesc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (meshDesc.shape.HasPhysicalShape)
|
||||||
// setup and do convex hull conversion
|
|
||||||
m_hulls = new List<ConvexResult>();
|
|
||||||
DecompDesc dcomp = new DecompDesc();
|
|
||||||
dcomp.mIndices = convIndices;
|
|
||||||
dcomp.mVertices = convVertices;
|
|
||||||
dcomp.mDepth = maxDepthSplit;
|
|
||||||
dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
|
|
||||||
dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
|
|
||||||
dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
|
|
||||||
dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
|
|
||||||
ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
|
|
||||||
// create the hull into the _hulls variable
|
|
||||||
convexBuilder.process(dcomp);
|
|
||||||
|
|
||||||
DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
|
|
||||||
BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
|
|
||||||
|
|
||||||
// Convert the vertices and indices for passing to unmanaged.
|
|
||||||
// The hull information is passed as a large floating point array.
|
|
||||||
// The format is:
|
|
||||||
// convHulls[0] = number of hulls
|
|
||||||
// convHulls[1] = number of vertices in first hull
|
|
||||||
// convHulls[2] = hull centroid X coordinate
|
|
||||||
// convHulls[3] = hull centroid Y coordinate
|
|
||||||
// convHulls[4] = hull centroid Z coordinate
|
|
||||||
// convHulls[5] = first hull vertex X
|
|
||||||
// convHulls[6] = first hull vertex Y
|
|
||||||
// convHulls[7] = first hull vertex Z
|
|
||||||
// convHulls[8] = second hull vertex X
|
|
||||||
// ...
|
|
||||||
// convHulls[n] = number of vertices in second hull
|
|
||||||
// convHulls[n+1] = second hull centroid X coordinate
|
|
||||||
// ...
|
|
||||||
//
|
|
||||||
// TODO: is is very inefficient. Someday change the convex hull generator to return
|
|
||||||
// data structures that do not need to be converted in order to pass to Bullet.
|
|
||||||
// And maybe put the values directly into pinned memory rather than marshaling.
|
|
||||||
int hullCount = m_hulls.Count;
|
|
||||||
int totalVertices = 1; // include one for the count of the hulls
|
|
||||||
foreach (ConvexResult cr in m_hulls)
|
|
||||||
{
|
{
|
||||||
totalVertices += 4; // add four for the vertex count and centroid
|
HACDParams parms;
|
||||||
totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
|
parms.maxVerticesPerHull = BSParam.BHullMaxVerticesPerHull;
|
||||||
}
|
parms.minClusters = BSParam.BHullMinClusters;
|
||||||
float[] convHulls = new float[totalVertices];
|
parms.compacityWeight = BSParam.BHullCompacityWeight;
|
||||||
|
parms.volumeWeight = BSParam.BHullVolumeWeight;
|
||||||
|
parms.concavity = BSParam.BHullConcavity;
|
||||||
|
parms.addExtraDistPoints = BSParam.NumericBool(BSParam.BHullAddExtraDistPoints);
|
||||||
|
parms.addNeighboursDistPoints = BSParam.NumericBool(BSParam.BHullAddNeighboursDistPoints);
|
||||||
|
parms.addFacesPoints = BSParam.NumericBool(BSParam.BHullAddFacesPoints);
|
||||||
|
parms.shouldAdjustCollisionMargin = BSParam.NumericBool(BSParam.BHullShouldAdjustCollisionMargin);
|
||||||
|
|
||||||
convHulls[0] = (float)hullCount;
|
DetailLog("{0},BSShapeCollection.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
|
||||||
int jj = 1;
|
newShape = PhysicsScene.PE.BuildHullShapeFromMesh(PhysicsScene.World, meshDesc.shape, parms);
|
||||||
foreach (ConvexResult cr in m_hulls)
|
DetailLog("{0},BSShapeCollection.CreatePhysicalHull,hullFromMesh,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
|
||||||
{
|
|
||||||
// copy vertices for index access
|
|
||||||
float3[] verts = new float3[cr.HullVertices.Count];
|
|
||||||
int kk = 0;
|
|
||||||
foreach (float3 ff in cr.HullVertices)
|
|
||||||
{
|
|
||||||
verts[kk++] = ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add to the array one hull's worth of data
|
|
||||||
convHulls[jj++] = cr.HullIndices.Count;
|
|
||||||
convHulls[jj++] = 0f; // centroid x,y,z
|
|
||||||
convHulls[jj++] = 0f;
|
|
||||||
convHulls[jj++] = 0f;
|
|
||||||
foreach (int ind in cr.HullIndices)
|
|
||||||
{
|
|
||||||
convHulls[jj++] = verts[ind].x;
|
|
||||||
convHulls[jj++] = verts[ind].y;
|
|
||||||
convHulls[jj++] = verts[ind].z;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// create the hull data structure in Bullet
|
DetailLog("{0},BSShapeCollection.CreatePhysicalHull,shouldUseBulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
|
||||||
newShape = PhysicsScene.PE.CreateHullShape(PhysicsScene.World, hullCount, convHulls);
|
|
||||||
}
|
}
|
||||||
}
|
if (!newShape.HasPhysicalShape)
|
||||||
|
{
|
||||||
|
// Build a new hull in the physical world.
|
||||||
|
// Pass true for physicalness as this prevents the creation of bounding box which is not needed
|
||||||
|
IMesh meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */, false, false);
|
||||||
|
if (meshData != null)
|
||||||
|
{
|
||||||
|
int[] indices = meshData.getIndexListAsInt();
|
||||||
|
List<OMV.Vector3> vertices = meshData.getVertexList();
|
||||||
|
|
||||||
newShape.shapeKey = newHullKey;
|
//format conversion from IMesh format to DecompDesc format
|
||||||
|
List<int> convIndices = new List<int>();
|
||||||
|
List<float3> convVertices = new List<float3>();
|
||||||
|
for (int ii = 0; ii < indices.GetLength(0); ii++)
|
||||||
|
{
|
||||||
|
convIndices.Add(indices[ii]);
|
||||||
|
}
|
||||||
|
foreach (OMV.Vector3 vv in vertices)
|
||||||
|
{
|
||||||
|
convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
|
||||||
|
if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
|
||||||
|
{
|
||||||
|
// Simple primitive shapes we know are convex so they are better implemented with
|
||||||
|
// fewer hulls.
|
||||||
|
// Check for simple shape (prim without cuts) and reduce split parameter if so.
|
||||||
|
if (PrimHasNoCuts(pbs))
|
||||||
|
{
|
||||||
|
maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup and do convex hull conversion
|
||||||
|
m_hulls = new List<ConvexResult>();
|
||||||
|
DecompDesc dcomp = new DecompDesc();
|
||||||
|
dcomp.mIndices = convIndices;
|
||||||
|
dcomp.mVertices = convVertices;
|
||||||
|
dcomp.mDepth = maxDepthSplit;
|
||||||
|
dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
|
||||||
|
dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
|
||||||
|
dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
|
||||||
|
dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
|
||||||
|
ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
|
||||||
|
// create the hull into the _hulls variable
|
||||||
|
convexBuilder.process(dcomp);
|
||||||
|
|
||||||
|
DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
|
||||||
|
BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
|
||||||
|
|
||||||
|
// Convert the vertices and indices for passing to unmanaged.
|
||||||
|
// The hull information is passed as a large floating point array.
|
||||||
|
// The format is:
|
||||||
|
// convHulls[0] = number of hulls
|
||||||
|
// convHulls[1] = number of vertices in first hull
|
||||||
|
// convHulls[2] = hull centroid X coordinate
|
||||||
|
// convHulls[3] = hull centroid Y coordinate
|
||||||
|
// convHulls[4] = hull centroid Z coordinate
|
||||||
|
// convHulls[5] = first hull vertex X
|
||||||
|
// convHulls[6] = first hull vertex Y
|
||||||
|
// convHulls[7] = first hull vertex Z
|
||||||
|
// convHulls[8] = second hull vertex X
|
||||||
|
// ...
|
||||||
|
// convHulls[n] = number of vertices in second hull
|
||||||
|
// convHulls[n+1] = second hull centroid X coordinate
|
||||||
|
// ...
|
||||||
|
//
|
||||||
|
// TODO: is is very inefficient. Someday change the convex hull generator to return
|
||||||
|
// data structures that do not need to be converted in order to pass to Bullet.
|
||||||
|
// And maybe put the values directly into pinned memory rather than marshaling.
|
||||||
|
int hullCount = m_hulls.Count;
|
||||||
|
int totalVertices = 1; // include one for the count of the hulls
|
||||||
|
foreach (ConvexResult cr in m_hulls)
|
||||||
|
{
|
||||||
|
totalVertices += 4; // add four for the vertex count and centroid
|
||||||
|
totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
|
||||||
|
}
|
||||||
|
float[] convHulls = new float[totalVertices];
|
||||||
|
|
||||||
|
convHulls[0] = (float)hullCount;
|
||||||
|
int jj = 1;
|
||||||
|
foreach (ConvexResult cr in m_hulls)
|
||||||
|
{
|
||||||
|
// copy vertices for index access
|
||||||
|
float3[] verts = new float3[cr.HullVertices.Count];
|
||||||
|
int kk = 0;
|
||||||
|
foreach (float3 ff in cr.HullVertices)
|
||||||
|
{
|
||||||
|
verts[kk++] = ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add to the array one hull's worth of data
|
||||||
|
convHulls[jj++] = cr.HullIndices.Count;
|
||||||
|
convHulls[jj++] = 0f; // centroid x,y,z
|
||||||
|
convHulls[jj++] = 0f;
|
||||||
|
convHulls[jj++] = 0f;
|
||||||
|
foreach (int ind in cr.HullIndices)
|
||||||
|
{
|
||||||
|
convHulls[jj++] = verts[ind].x;
|
||||||
|
convHulls[jj++] = verts[ind].y;
|
||||||
|
convHulls[jj++] = verts[ind].z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// create the hull data structure in Bullet
|
||||||
|
newShape = PhysicsScene.PE.CreateHullShape(PhysicsScene.World, hullCount, convHulls);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newShape.shapeKey = newHullKey;
|
||||||
|
}
|
||||||
|
|
||||||
return newShape;
|
return newShape;
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,13 +213,13 @@ public sealed class BSTerrainManager : IDisposable
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Another region is calling this region passing a terrain.
|
// Another region is calling this region and passing a terrain.
|
||||||
// A region that is not the mega-region root will pass its terrain to the root region so the root region
|
// A region that is not the mega-region root will pass its terrain to the root region so the root region
|
||||||
// physics engine will have all the terrains.
|
// physics engine will have all the terrains.
|
||||||
private void AddMegaRegionChildTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
|
private void AddMegaRegionChildTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
|
||||||
{
|
{
|
||||||
// Since we are called by another region's thread, the action must be rescheduled onto our processing thread.
|
// Since we are called by another region's thread, the action must be rescheduled onto our processing thread.
|
||||||
PhysicsScene.PostTaintObject("TerrainManager.AddMegaRegionChild" + m_worldOffset.ToString(), 0, delegate()
|
PhysicsScene.PostTaintObject("TerrainManager.AddMegaRegionChild" + minCoords.ToString(), id, delegate()
|
||||||
{
|
{
|
||||||
UpdateTerrain(id, heightMap, minCoords, maxCoords);
|
UpdateTerrain(id, heightMap, minCoords, maxCoords);
|
||||||
});
|
});
|
||||||
|
@ -306,7 +306,7 @@ public sealed class BSTerrainManager : IDisposable
|
||||||
newTerrainID = ++m_terrainCount;
|
newTerrainID = ++m_terrainCount;
|
||||||
|
|
||||||
DetailLog("{0},BSTerrainManager.UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}",
|
DetailLog("{0},BSTerrainManager.UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}",
|
||||||
BSScene.DetailLogZero, newTerrainID, minCoords, minCoords);
|
BSScene.DetailLogZero, newTerrainID, minCoords, maxCoords);
|
||||||
BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
|
BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
|
||||||
m_terrains.Add(terrainRegionBase, newTerrainPhys);
|
m_terrains.Add(terrainRegionBase, newTerrainPhys);
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ Enable vehicle border crossings (at least as poorly as ODE)
|
||||||
Terrain skirts
|
Terrain skirts
|
||||||
Avatar created in previous region and not new region when crossing border
|
Avatar created in previous region and not new region when crossing border
|
||||||
Vehicle recreated in new sim at small Z value (offset from root value?) (DONE)
|
Vehicle recreated in new sim at small Z value (offset from root value?) (DONE)
|
||||||
Lock axis
|
|
||||||
Deleting a linkset while standing on the root will leave the physical shape of the root behind.
|
Deleting a linkset while standing on the root will leave the physical shape of the root behind.
|
||||||
Not sure if it is because standing on it. Done with large prim linksets.
|
Not sure if it is because standing on it. Done with large prim linksets.
|
||||||
Linkset child rotations.
|
Linkset child rotations.
|
||||||
|
@ -344,3 +343,5 @@ 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 that angular motion specified around Z moves in the vehicle coordinates.
|
||||||
DONE 20130120: BulletSim properly applies force in vehicle relative coordinates.
|
DONE 20130120: BulletSim properly applies force in vehicle relative coordinates.
|
||||||
Nebadon vehicles turning funny in arena (DONE)
|
Nebadon vehicles turning funny in arena (DONE)
|
||||||
|
Lock axis (DONE 20130401)
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using log4net;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
@ -34,10 +36,10 @@ using OpenSim.Region.CoreModules.World.Land;
|
||||||
|
|
||||||
namespace OpenSim.Region.RegionCombinerModule
|
namespace OpenSim.Region.RegionCombinerModule
|
||||||
{
|
{
|
||||||
public class RegionCombinerLargeLandChannel : ILandChannel
|
public class RegionCombinerLargeLandChannel : ILandChannel
|
||||||
{
|
{
|
||||||
// private static readonly ILog m_log =
|
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
|
||||||
private RegionData RegData;
|
private RegionData RegData;
|
||||||
private ILandChannel RootRegionLandChannel;
|
private ILandChannel RootRegionLandChannel;
|
||||||
private readonly List<RegionData> RegionConnections;
|
private readonly List<RegionData> RegionConnections;
|
||||||
|
@ -75,40 +77,51 @@ public class RegionCombinerLargeLandChannel : ILandChannel
|
||||||
|
|
||||||
public ILandObject GetLandObject(int x, int y)
|
public ILandObject GetLandObject(int x, int y)
|
||||||
{
|
{
|
||||||
//m_log.DebugFormat("[BIGLANDTESTINT]: <{0},{1}>", x, y);
|
return GetLandObject((float)x, (float)y);
|
||||||
|
|
||||||
if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize)
|
// m_log.DebugFormat("[BIGLANDTESTINT]: <{0},{1}>", x, y);
|
||||||
{
|
//
|
||||||
return RootRegionLandChannel.GetLandObject(x, y);
|
// if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize)
|
||||||
}
|
// {
|
||||||
else
|
// return RootRegionLandChannel.GetLandObject(x, y);
|
||||||
{
|
// }
|
||||||
int offsetX = (x / (int)Constants.RegionSize);
|
// else
|
||||||
int offsetY = (y / (int)Constants.RegionSize);
|
// {
|
||||||
offsetX *= (int)Constants.RegionSize;
|
// int offsetX = (x / (int)Constants.RegionSize);
|
||||||
offsetY *= (int)Constants.RegionSize;
|
// int offsetY = (y / (int)Constants.RegionSize);
|
||||||
|
// offsetX *= (int)Constants.RegionSize;
|
||||||
foreach (RegionData regionData in RegionConnections)
|
// offsetY *= (int)Constants.RegionSize;
|
||||||
{
|
//
|
||||||
if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY)
|
// foreach (RegionData regionData in RegionConnections)
|
||||||
{
|
// {
|
||||||
return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY);
|
// if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY)
|
||||||
}
|
// {
|
||||||
}
|
// m_log.DebugFormat(
|
||||||
ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene);
|
// "[REGION COMBINER LARGE LAND CHANNEL]: Found region {0} at offset {1},{2}",
|
||||||
obj.LandData.Name = "NO LAND";
|
// regionData.RegionScene.Name, offsetX, offsetY);
|
||||||
return obj;
|
//
|
||||||
}
|
// return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// //ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene);
|
||||||
|
// //obj.LandData.Name = "NO LAND";
|
||||||
|
// //return obj;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// m_log.DebugFormat("[REGION COMBINER LARGE LAND CHANNEL]: No region found at {0},{1}, returning null", x, y);
|
||||||
|
//
|
||||||
|
// return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ILandObject GetLandObject(int localID)
|
public ILandObject GetLandObject(int localID)
|
||||||
{
|
{
|
||||||
|
// XXX: Possibly should be looking in every land channel, not just the root.
|
||||||
return RootRegionLandChannel.GetLandObject(localID);
|
return RootRegionLandChannel.GetLandObject(localID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ILandObject GetLandObject(float x, float y)
|
public ILandObject GetLandObject(float x, float y)
|
||||||
{
|
{
|
||||||
//m_log.DebugFormat("[BIGLANDTESTFLOAT]: <{0},{1}>", x, y);
|
// m_log.DebugFormat("[BIGLANDTESTFLOAT]: <{0},{1}>", x, y);
|
||||||
|
|
||||||
if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize)
|
if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize)
|
||||||
{
|
{
|
||||||
|
@ -125,14 +138,22 @@ public class RegionCombinerLargeLandChannel : ILandChannel
|
||||||
{
|
{
|
||||||
if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY)
|
if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY)
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[REGION COMBINER LARGE LAND CHANNEL]: Found region {0} at offset {1},{2}",
|
||||||
|
// regionData.RegionScene.Name, offsetX, offsetY);
|
||||||
|
|
||||||
return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY);
|
return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene);
|
// ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene);
|
||||||
obj.LandData.Name = "NO LAND";
|
// obj.LandData.Name = "NO LAND";
|
||||||
return obj;
|
// return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// m_log.DebugFormat("[REGION COMBINER LARGE LAND CHANNEL]: No region found at {0},{1}, returning null", x, y);
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsForcefulBansAllowed()
|
public bool IsForcefulBansAllowed()
|
||||||
|
|
|
@ -528,8 +528,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||||
{
|
{
|
||||||
File.Delete(savedState);
|
File.Delete(savedState);
|
||||||
}
|
}
|
||||||
catch(Exception)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
m_log.Warn(
|
||||||
|
string.Format(
|
||||||
|
"[SCRIPT INSTANCE]: Could not delete script state {0} for script {1} (id {2}) in part {3} (id {4}) in object {5} in {6}. Exception ",
|
||||||
|
ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name),
|
||||||
|
e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -137,10 +137,11 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
||||||
userID, sessionID, secureSessionID);
|
userID, sessionID, secureSessionID);
|
||||||
|
|
||||||
NameValueCollection requestArgs = new NameValueCollection
|
NameValueCollection requestArgs = new NameValueCollection
|
||||||
{
|
{
|
||||||
{ "RequestMethod", "AddSession" },
|
{ "RequestMethod", "AddSession" },
|
||||||
{ "UserID", userID.ToString() }
|
{ "UserID", userID.ToString() }
|
||||||
};
|
};
|
||||||
|
|
||||||
if (sessionID != UUID.Zero)
|
if (sessionID != UUID.Zero)
|
||||||
{
|
{
|
||||||
requestArgs["SessionID"] = sessionID.ToString();
|
requestArgs["SessionID"] = sessionID.ToString();
|
||||||
|
@ -158,13 +159,13 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
||||||
|
|
||||||
public bool LogoutAgent(UUID sessionID)
|
public bool LogoutAgent(UUID sessionID)
|
||||||
{
|
{
|
||||||
// m_log.InfoFormat("[SIMIAN PRESENCE CONNECTOR]: Logout requested for agent with sessionID " + sessionID);
|
// m_log.InfoFormat("[SIMIAN PRESENCE CONNECTOR]: Logout requested for agent with sessionID " + sessionID);
|
||||||
|
|
||||||
NameValueCollection requestArgs = new NameValueCollection
|
NameValueCollection requestArgs = new NameValueCollection
|
||||||
{
|
{
|
||||||
{ "RequestMethod", "RemoveSession" },
|
{ "RequestMethod", "RemoveSession" },
|
||||||
{ "SessionID", sessionID.ToString() }
|
{ "SessionID", sessionID.ToString() }
|
||||||
};
|
};
|
||||||
|
|
||||||
OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
|
OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
|
||||||
bool success = response["Success"].AsBoolean();
|
bool success = response["Success"].AsBoolean();
|
||||||
|
@ -177,13 +178,13 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
||||||
|
|
||||||
public bool LogoutRegionAgents(UUID regionID)
|
public bool LogoutRegionAgents(UUID regionID)
|
||||||
{
|
{
|
||||||
// m_log.InfoFormat("[SIMIAN PRESENCE CONNECTOR]: Logout requested for all agents in region " + regionID);
|
// m_log.InfoFormat("[SIMIAN PRESENCE CONNECTOR]: Logout requested for all agents in region " + regionID);
|
||||||
|
|
||||||
NameValueCollection requestArgs = new NameValueCollection
|
NameValueCollection requestArgs = new NameValueCollection
|
||||||
{
|
{
|
||||||
{ "RequestMethod", "RemoveSessions" },
|
{ "RequestMethod", "RemoveSessions" },
|
||||||
{ "SceneID", regionID.ToString() }
|
{ "SceneID", regionID.ToString() }
|
||||||
};
|
};
|
||||||
|
|
||||||
OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
|
OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
|
||||||
bool success = response["Success"].AsBoolean();
|
bool success = response["Success"].AsBoolean();
|
||||||
|
@ -202,49 +203,46 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
||||||
|
|
||||||
public PresenceInfo GetAgent(UUID sessionID)
|
public PresenceInfo GetAgent(UUID sessionID)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting session data for agent with sessionID " + sessionID);
|
OSDMap sessionResponse = GetSessionDataFromSessionID(sessionID);
|
||||||
|
if (sessionResponse == null)
|
||||||
NameValueCollection requestArgs = new NameValueCollection
|
|
||||||
{
|
{
|
||||||
{ "RequestMethod", "GetSession" },
|
m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve session {0}: {1}",sessionID.ToString(),sessionResponse["Message"].AsString());
|
||||||
{ "SessionID", sessionID.ToString() }
|
return null;
|
||||||
};
|
|
||||||
|
|
||||||
OSDMap sessionResponse = WebUtil.PostToService(m_serverUrl, requestArgs);
|
|
||||||
if (sessionResponse["Success"].AsBoolean())
|
|
||||||
{
|
|
||||||
UUID userID = sessionResponse["UserID"].AsUUID();
|
|
||||||
m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting user data for " + userID);
|
|
||||||
|
|
||||||
requestArgs = new NameValueCollection
|
|
||||||
{
|
|
||||||
{ "RequestMethod", "GetUser" },
|
|
||||||
{ "UserID", userID.ToString() }
|
|
||||||
};
|
|
||||||
|
|
||||||
OSDMap userResponse = WebUtil.PostToService(m_serverUrl, requestArgs);
|
|
||||||
if (userResponse["Success"].AsBoolean())
|
|
||||||
return ResponseToPresenceInfo(sessionResponse, userResponse);
|
|
||||||
else
|
|
||||||
m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for " + userID + ": " + userResponse["Message"].AsString());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve session " + sessionID + ": " + sessionResponse["Message"].AsString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
UUID userID = sessionResponse["UserID"].AsUUID();
|
||||||
|
OSDMap userResponse = GetUserData(userID);
|
||||||
|
if (userResponse == null)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for {0}: {1}",userID.ToString(),userResponse["Message"].AsString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponseToPresenceInfo(sessionResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PresenceInfo[] GetAgents(string[] userIDs)
|
public PresenceInfo[] GetAgents(string[] userIDs)
|
||||||
{
|
{
|
||||||
List<PresenceInfo> presences = new List<PresenceInfo>(userIDs.Length);
|
List<PresenceInfo> presences = new List<PresenceInfo>();
|
||||||
|
|
||||||
for (int i = 0; i < userIDs.Length; i++)
|
NameValueCollection requestArgs = new NameValueCollection
|
||||||
{
|
{
|
||||||
UUID userID;
|
{ "RequestMethod", "GetSessions" },
|
||||||
if (UUID.TryParse(userIDs[i], out userID) && userID != UUID.Zero)
|
{ "UserIDList", String.Join(",",userIDs) }
|
||||||
presences.AddRange(GetSessions(userID));
|
};
|
||||||
|
|
||||||
|
OSDMap sessionListResponse = WebUtil.PostToService(m_serverUrl, requestArgs);
|
||||||
|
if (! sessionListResponse["Success"].AsBoolean())
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve sessions: {0}",sessionListResponse["Message"].AsString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSDArray sessionList = sessionListResponse["Sessions"] as OSDArray;
|
||||||
|
for (int i = 0; i < sessionList.Count; i++)
|
||||||
|
{
|
||||||
|
OSDMap sessionInfo = sessionList[i] as OSDMap;
|
||||||
|
presences.Add(ResponseToPresenceInfo(sessionInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
return presences.ToArray();
|
return presences.ToArray();
|
||||||
|
@ -262,7 +260,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
||||||
|
|
||||||
public bool LoggedOut(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt)
|
public bool LoggedOut(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Logging out user " + userID);
|
// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Logging out user " + userID);
|
||||||
|
|
||||||
// Remove the session to mark this user offline
|
// Remove the session to mark this user offline
|
||||||
if (!LogoutAgent(sessionID))
|
if (!LogoutAgent(sessionID))
|
||||||
|
@ -270,11 +268,11 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
||||||
|
|
||||||
// Save our last position as user data
|
// Save our last position as user data
|
||||||
NameValueCollection requestArgs = new NameValueCollection
|
NameValueCollection requestArgs = new NameValueCollection
|
||||||
{
|
{
|
||||||
{ "RequestMethod", "AddUserData" },
|
{ "RequestMethod", "AddUserData" },
|
||||||
{ "UserID", userID.ToString() },
|
{ "UserID", userID.ToString() },
|
||||||
{ "LastLocation", SerializeLocation(regionID, lastPosition, lastLookAt) }
|
{ "LastLocation", SerializeLocation(regionID, lastPosition, lastLookAt) }
|
||||||
};
|
};
|
||||||
|
|
||||||
OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
|
OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
|
||||||
bool success = response["Success"].AsBoolean();
|
bool success = response["Success"].AsBoolean();
|
||||||
|
@ -287,14 +285,14 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
||||||
|
|
||||||
public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt)
|
public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Setting home location for user " + userID);
|
// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Setting home location for user " + userID);
|
||||||
|
|
||||||
NameValueCollection requestArgs = new NameValueCollection
|
NameValueCollection requestArgs = new NameValueCollection
|
||||||
{
|
{
|
||||||
{ "RequestMethod", "AddUserData" },
|
{ "RequestMethod", "AddUserData" },
|
||||||
{ "UserID", userID.ToString() },
|
{ "UserID", userID.ToString() },
|
||||||
{ "HomeLocation", SerializeLocation(regionID, position, lookAt) }
|
{ "HomeLocation", SerializeLocation(regionID, position, lookAt) }
|
||||||
};
|
};
|
||||||
|
|
||||||
OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
|
OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
|
||||||
bool success = response["Success"].AsBoolean();
|
bool success = response["Success"].AsBoolean();
|
||||||
|
@ -312,23 +310,14 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
||||||
|
|
||||||
public GridUserInfo GetGridUserInfo(string user)
|
public GridUserInfo GetGridUserInfo(string user)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting session data for agent " + user);
|
// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting session data for agent " + user);
|
||||||
|
|
||||||
UUID userID = new UUID(user);
|
UUID userID = new UUID(user);
|
||||||
// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting user data for " + userID);
|
OSDMap userResponse = GetUserData(userID);
|
||||||
|
if (userResponse != null)
|
||||||
NameValueCollection requestArgs = new NameValueCollection
|
|
||||||
{
|
|
||||||
{ "RequestMethod", "GetUser" },
|
|
||||||
{ "UserID", userID.ToString() }
|
|
||||||
};
|
|
||||||
|
|
||||||
OSDMap userResponse = WebUtil.PostToService(m_serverUrl, requestArgs);
|
|
||||||
if (userResponse["Success"].AsBoolean())
|
|
||||||
return ResponseToGridUserInfo(userResponse);
|
return ResponseToGridUserInfo(userResponse);
|
||||||
else
|
|
||||||
m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for " + userID + ": " + userResponse["Message"].AsString());
|
|
||||||
|
|
||||||
|
m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for {0}: {1}",userID,userResponse["Message"].AsString());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,65 +327,49 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
||||||
|
|
||||||
private OSDMap GetUserData(UUID userID)
|
private OSDMap GetUserData(UUID userID)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting user data for " + userID);
|
// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting user data for " + userID);
|
||||||
|
|
||||||
NameValueCollection requestArgs = new NameValueCollection
|
NameValueCollection requestArgs = new NameValueCollection
|
||||||
{
|
{
|
||||||
{ "RequestMethod", "GetUser" },
|
{ "RequestMethod", "GetUser" },
|
||||||
{ "UserID", userID.ToString() }
|
{ "UserID", userID.ToString() }
|
||||||
};
|
};
|
||||||
|
|
||||||
OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
|
OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
|
||||||
if (response["Success"].AsBoolean() && response["User"] is OSDMap)
|
if (response["Success"].AsBoolean() && response["User"] is OSDMap)
|
||||||
return response;
|
return response;
|
||||||
else
|
|
||||||
m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for " + userID + ": " + response["Message"].AsString());
|
|
||||||
|
|
||||||
|
m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for {0}; {1}",userID.ToString(),response["Message"].AsString());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<PresenceInfo> GetSessions(UUID userID)
|
private OSDMap GetSessionDataFromSessionID(UUID sessionID)
|
||||||
{
|
{
|
||||||
List<PresenceInfo> presences = new List<PresenceInfo>(1);
|
NameValueCollection requestArgs = new NameValueCollection
|
||||||
|
|
||||||
OSDMap userResponse = GetUserData(userID);
|
|
||||||
if (userResponse != null)
|
|
||||||
{
|
|
||||||
// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting sessions for " + userID);
|
|
||||||
|
|
||||||
NameValueCollection requestArgs = new NameValueCollection
|
|
||||||
{
|
{
|
||||||
{ "RequestMethod", "GetSession" },
|
{ "RequestMethod", "GetSession" },
|
||||||
{ "UserID", userID.ToString() }
|
{ "SessionID", sessionID.ToString() }
|
||||||
};
|
};
|
||||||
|
|
||||||
OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
|
OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
|
||||||
if (response["Success"].AsBoolean())
|
if (response["Success"].AsBoolean())
|
||||||
{
|
return response;
|
||||||
PresenceInfo presence = ResponseToPresenceInfo(response, userResponse);
|
|
||||||
if (presence != null)
|
|
||||||
presences.Add(presence);
|
|
||||||
}
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// m_log.Debug("[SIMIAN PRESENCE CONNECTOR]: No session returned for " + userID + ": " + response["Message"].AsString());
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
return presences;
|
m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve session data for {0}; {1}",sessionID.ToString(),response["Message"].AsString());
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool UpdateSession(UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt)
|
private bool UpdateSession(UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt)
|
||||||
{
|
{
|
||||||
// Save our current location as session data
|
// Save our current location as session data
|
||||||
NameValueCollection requestArgs = new NameValueCollection
|
NameValueCollection requestArgs = new NameValueCollection
|
||||||
{
|
{
|
||||||
{ "RequestMethod", "UpdateSession" },
|
{ "RequestMethod", "UpdateSession" },
|
||||||
{ "SessionID", sessionID.ToString() },
|
{ "SessionID", sessionID.ToString() },
|
||||||
{ "SceneID", regionID.ToString() },
|
{ "SceneID", regionID.ToString() },
|
||||||
{ "ScenePosition", lastPosition.ToString() },
|
{ "ScenePosition", lastPosition.ToString() },
|
||||||
{ "SceneLookAt", lastLookAt.ToString() }
|
{ "SceneLookAt", lastLookAt.ToString() }
|
||||||
};
|
};
|
||||||
|
|
||||||
OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
|
OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
|
||||||
bool success = response["Success"].AsBoolean();
|
bool success = response["Success"].AsBoolean();
|
||||||
|
@ -407,7 +380,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PresenceInfo ResponseToPresenceInfo(OSDMap sessionResponse, OSDMap userResponse)
|
private PresenceInfo ResponseToPresenceInfo(OSDMap sessionResponse)
|
||||||
{
|
{
|
||||||
if (sessionResponse == null)
|
if (sessionResponse == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -43,9 +43,14 @@
|
||||||
; Sets the method that OpenSim will use to fire asynchronous
|
; Sets the method that OpenSim will use to fire asynchronous
|
||||||
; events. Valid values are UnsafeQueueUserWorkItem,
|
; events. Valid values are UnsafeQueueUserWorkItem,
|
||||||
; QueueUserWorkItem, BeginInvoke, SmartThreadPool, and Thread.
|
; QueueUserWorkItem, BeginInvoke, SmartThreadPool, and Thread.
|
||||||
|
;
|
||||||
; SmartThreadPool is reported to work well on Mono/Linux, but
|
; SmartThreadPool is reported to work well on Mono/Linux, but
|
||||||
; UnsafeQueueUserWorkItem has been benchmarked with better
|
; UnsafeQueueUserWorkItem has been benchmarked with better
|
||||||
; performance on .NET/Windows
|
; performance on .NET/Windows
|
||||||
|
;
|
||||||
|
; UnsafeQueueUserWorkItem refers to the fact that the code creating the event could elevate its security
|
||||||
|
; privileges. However, as calling code is trusted anyway this is safe (if you set
|
||||||
|
; TrustedBinaries = true in the [XEngine] section then you already have to trust that incoming code for other reasons).
|
||||||
async_call_method = SmartThreadPool
|
async_call_method = SmartThreadPool
|
||||||
|
|
||||||
; Max threads to allocate on the FireAndForget thread pool
|
; Max threads to allocate on the FireAndForget thread pool
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<configuration>
|
<configuration>
|
||||||
<dllmap os="windows" cpu="x86" dll="BulletSim" target="lib32/BulletSim" />
|
<dllmap os="windows" cpu="x86" dll="BulletSim" target="lib32/BulletSim" />
|
||||||
<dllmap os="windows" cpu="x86-64,ia64" dll="BulletSim" target="lib64/BulletSim" />
|
<dllmap os="windows" cpu="x86-64,ia64" dll="BulletSim" target="lib64/BulletSim" />
|
||||||
|
<dllmap os="osx" cpu="x86" dll="BulletSim" target="lib32/libBulletSim.dylib" />
|
||||||
|
<dllmap os="osx" cpu="x86-64,ia64" dll="BulletSim" target="lib32/libBulletSim.dylib" />
|
||||||
<dllmap os="!windows,osx" cpu="x86" dll="BulletSim" target="lib32/libBulletSim.so" />
|
<dllmap os="!windows,osx" cpu="x86" dll="BulletSim" target="lib32/libBulletSim.so" />
|
||||||
<dllmap os="!windows,osx" cpu="x86-64,ia64" dll="BulletSim" target="lib64/libBulletSim.so" />
|
<dllmap os="!windows,osx" cpu="x86-64,ia64" dll="BulletSim" target="lib64/libBulletSim.so" />
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue