Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
commit
aab2b032aa
|
@ -101,6 +101,7 @@ what it is today.
|
|||
* jhurliman
|
||||
* John R Sohn (XenReborn)
|
||||
* jonc
|
||||
* Jon Cundill
|
||||
* Junta Kohime
|
||||
* Kayne
|
||||
* Kevin Cozens
|
||||
|
|
|
@ -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 && 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},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
|
||||
{
|
||||
bool TryExperimentalLockAxisCode = true;
|
||||
BSConstraint LockAxisConstraint = null;
|
||||
|
||||
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);
|
||||
LockAxisConstraint = null;
|
||||
|
@ -69,18 +68,13 @@ public class BSActorLockAxis : BSActor
|
|||
// If all the axis are free, we don't need to exist
|
||||
if (m_controllingPrim.LockedAxis == m_controllingPrim.LockedAxisFree)
|
||||
{
|
||||
m_physicsScene.DetailLog("{0},BSActorLockAxis,refresh,allAxisFree,removing={1}", m_controllingPrim.LocalID, ActorName);
|
||||
m_controllingPrim.PhysicalActors.RemoveAndRelease(ActorName);
|
||||
return;
|
||||
Enabled = false;
|
||||
}
|
||||
|
||||
// If the object is physically active, add the axis locking constraint
|
||||
if (Enabled
|
||||
&& m_controllingPrim.IsPhysicallyActive
|
||||
&& TryExperimentalLockAxisCode
|
||||
&& m_controllingPrim.LockedAxis != m_controllingPrim.LockedAxisFree)
|
||||
if (isActive)
|
||||
{
|
||||
if (LockAxisConstraint == null)
|
||||
AddAxisLockConstraint();
|
||||
AddAxisLockConstraint();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -99,7 +93,7 @@ public class BSActorLockAxis : BSActor
|
|||
// If a constraint is set up, remove it from the physical scene
|
||||
RemoveAxisLockConstraint();
|
||||
// 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();
|
||||
});
|
||||
|
@ -108,58 +102,61 @@ public class BSActorLockAxis : BSActor
|
|||
|
||||
private void AddAxisLockConstraint()
|
||||
{
|
||||
// Lock that axis by creating a 6DOF constraint that has one end in the world and
|
||||
// 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)
|
||||
if (LockAxisConstraint == null)
|
||||
{
|
||||
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);
|
||||
}
|
||||
// Lock that axis by creating a 6DOF constraint that has one end in the world and
|
||||
// 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
|
||||
|
||||
m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,create,linLow={1},linHi={2},angLow={3},angHi={4}",
|
||||
m_controllingPrim.LocalID, linearLow, linearHigh, angularLow, angularHigh);
|
||||
// Remove any existing axis constraint (just to be sure)
|
||||
RemoveAxisLockConstraint();
|
||||
|
||||
// Constants from one of the posts mentioned above and used in Bullet's ConstraintDemo.
|
||||
axisConstrainer.TranslationalLimitMotor(true /* enable */, 5.0f, 0.1f);
|
||||
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);
|
||||
|
||||
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()
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* 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 && 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},BSActorMoveToTarget,refresh", m_controllingPrim.LocalID);
|
||||
|
||||
// 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("BSPrim.PIDTarget",
|
||||
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},BSPrim.PIDTarget,zeroMovement,movePos={1},pos={2},mass={3}",
|
||||
m_controllingPrim.LocalID, movePosition, m_controllingPrim.RawPosition, m_controllingPrim.Mass);
|
||||
m_controllingPrim.ForcePosition = m_targetMotor.TargetValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_controllingPrim.ForcePosition = movePosition;
|
||||
}
|
||||
m_physicsScene.DetailLog("{0},BSPrim.PIDTarget,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
|
||||
{
|
||||
private BSScene PhysicsScene { get; set; }
|
||||
private BSScene m_physicsScene { get; set; }
|
||||
private Dictionary<string, BSActor> m_actors;
|
||||
|
||||
public BSActorCollection(BSScene physicsScene)
|
||||
{
|
||||
PhysicsScene = physicsScene;
|
||||
m_physicsScene = physicsScene;
|
||||
m_actors = new Dictionary<string, BSActor>();
|
||||
}
|
||||
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)
|
||||
{
|
||||
bool ret = false;
|
||||
if (m_actors.ContainsKey(name))
|
||||
lock (m_actors)
|
||||
{
|
||||
BSActor beingRemoved = m_actors[name];
|
||||
beingRemoved.Dispose();
|
||||
m_actors.Remove(name);
|
||||
ret = true;
|
||||
if (m_actors.ContainsKey(name))
|
||||
{
|
||||
BSActor beingRemoved = m_actors[name];
|
||||
m_actors.Remove(name);
|
||||
beingRemoved.Dispose();
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
public void Clear()
|
||||
{
|
||||
Release();
|
||||
m_actors.Clear();
|
||||
lock (m_actors)
|
||||
{
|
||||
Release();
|
||||
m_actors.Clear();
|
||||
}
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
public bool HasActor(string 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)
|
||||
{
|
||||
foreach (KeyValuePair<string, BSActor> kvp in m_actors)
|
||||
act(kvp.Value);
|
||||
lock (m_actors)
|
||||
{
|
||||
foreach (KeyValuePair<string, BSActor> kvp in m_actors)
|
||||
act(kvp.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public void Enable(bool enabl)
|
||||
{
|
||||
ForEachActor(a => a.SetEnabled(enabl));
|
||||
}
|
||||
public void Release()
|
||||
{
|
||||
ForEachActor(a => a.Dispose());
|
||||
|
@ -98,7 +125,7 @@ public abstract class BSActor
|
|||
{
|
||||
protected BSScene m_physicsScene { 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 BSActor(BSScene physicsScene, BSPhysObject pObj, string actorName)
|
||||
|
@ -114,8 +141,10 @@ public abstract class BSActor
|
|||
{
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -46,9 +46,6 @@ public sealed class BSCharacter : BSPhysObject
|
|||
private OMV.Vector3 _position;
|
||||
private float _mass;
|
||||
private float _avatarVolume;
|
||||
private OMV.Vector3 _force;
|
||||
private OMV.Vector3 _velocity;
|
||||
private OMV.Vector3 _torque;
|
||||
private float _collisionScore;
|
||||
private OMV.Vector3 _acceleration;
|
||||
private OMV.Quaternion _orientation;
|
||||
|
@ -61,17 +58,13 @@ public sealed class BSCharacter : BSPhysObject
|
|||
private OMV.Vector3 _rotationalVelocity;
|
||||
private bool _kinematic;
|
||||
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 bool _usePID;
|
||||
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)
|
||||
: base(parent_scene, localID, avName, "BSCharacter")
|
||||
|
@ -81,11 +74,10 @@ public sealed class BSCharacter : BSPhysObject
|
|||
|
||||
_flying = isFlying;
|
||||
_orientation = OMV.Quaternion.Identity;
|
||||
_velocity = OMV.Vector3.Zero;
|
||||
RawVelocity = OMV.Vector3.Zero;
|
||||
_buoyancy = ComputeBuoyancyFromFlying(isFlying);
|
||||
Friction = BSParam.AvatarStandingFriction;
|
||||
Density = BSParam.AvatarDensity / BSParam.DensityScaleFactor;
|
||||
_isStationaryStanding = false;
|
||||
|
||||
// Old versions of ScenePresence passed only the height. If width and/or depth are zero,
|
||||
// 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
|
||||
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}",
|
||||
LocalID, _size, Scale, Density, _avatarVolume, RawMass);
|
||||
|
@ -139,10 +136,10 @@ public sealed class BSCharacter : BSPhysObject
|
|||
ForcePosition = _position;
|
||||
|
||||
// Set the velocity
|
||||
_velocityMotor.Reset();
|
||||
_velocityMotor.SetTarget(_velocity);
|
||||
_velocityMotor.SetCurrent(_velocity);
|
||||
ForceVelocity = _velocity;
|
||||
if (m_moveActor != null)
|
||||
m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, false);
|
||||
|
||||
ForceVelocity = RawVelocity;
|
||||
|
||||
// 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.
|
||||
|
@ -163,6 +160,9 @@ public sealed class BSCharacter : BSPhysObject
|
|||
// Make so capsule does not fall over
|
||||
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.AddObjectToWorld(PhysicsScene.World, PhysBody);
|
||||
|
@ -176,162 +176,6 @@ public sealed class BSCharacter : BSPhysObject
|
|||
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()
|
||||
{
|
||||
|
@ -403,7 +247,7 @@ public sealed class BSCharacter : BSPhysObject
|
|||
// Called at taint time!
|
||||
public override void ZeroMotion(bool inTaintTime)
|
||||
{
|
||||
_velocity = OMV.Vector3.Zero;
|
||||
RawVelocity = OMV.Vector3.Zero;
|
||||
_acceleration = OMV.Vector3.Zero;
|
||||
_rotationalVelocity = OMV.Vector3.Zero;
|
||||
|
||||
|
@ -542,15 +386,15 @@ public sealed class BSCharacter : BSPhysObject
|
|||
}
|
||||
|
||||
public override OMV.Vector3 Force {
|
||||
get { return _force; }
|
||||
get { return RawForce; }
|
||||
set {
|
||||
_force = value;
|
||||
RawForce = value;
|
||||
// m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
|
||||
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)
|
||||
PhysicsScene.PE.SetObjectForce(PhysBody, _force);
|
||||
PhysicsScene.PE.SetObjectForce(PhysBody, RawForce);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -573,7 +417,7 @@ public sealed class BSCharacter : BSPhysObject
|
|||
{
|
||||
get
|
||||
{
|
||||
return m_targetVelocity;
|
||||
return base.m_targetVelocity;
|
||||
}
|
||||
set
|
||||
{
|
||||
|
@ -583,51 +427,39 @@ public sealed class BSCharacter : BSPhysObject
|
|||
if (_setAlwaysRun)
|
||||
targetVel *= new OMV.Vector3(BSParam.AvatarAlwaysRunFactor, BSParam.AvatarAlwaysRunFactor, 0f);
|
||||
|
||||
PhysicsScene.TaintedObject("BSCharacter.setTargetVelocity", delegate()
|
||||
{
|
||||
_velocityMotor.Reset();
|
||||
_velocityMotor.SetTarget(targetVel);
|
||||
_velocityMotor.SetCurrent(_velocity);
|
||||
_velocityMotor.Enabled = true;
|
||||
});
|
||||
if (m_moveActor != null)
|
||||
m_moveActor.SetVelocityAndTarget(RawVelocity, targetVel, false /* inTaintTime */);
|
||||
}
|
||||
}
|
||||
public override OMV.Vector3 RawVelocity
|
||||
{
|
||||
get { return _velocity; }
|
||||
set { _velocity = value; }
|
||||
}
|
||||
// Directly setting velocity means this is what the user really wants now.
|
||||
public override OMV.Vector3 Velocity {
|
||||
get { return _velocity; }
|
||||
get { return RawVelocity; }
|
||||
set {
|
||||
_velocity = value;
|
||||
// m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
|
||||
RawVelocity = value;
|
||||
// m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, RawVelocity);
|
||||
PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate()
|
||||
{
|
||||
_velocityMotor.Reset();
|
||||
_velocityMotor.SetCurrent(_velocity);
|
||||
_velocityMotor.SetTarget(_velocity);
|
||||
_velocityMotor.Enabled = false;
|
||||
if (m_moveActor != null)
|
||||
m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, true /* inTaintTime */);
|
||||
|
||||
DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
|
||||
ForceVelocity = _velocity;
|
||||
DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, RawVelocity);
|
||||
ForceVelocity = RawVelocity;
|
||||
});
|
||||
}
|
||||
}
|
||||
public override OMV.Vector3 ForceVelocity {
|
||||
get { return _velocity; }
|
||||
get { return RawVelocity; }
|
||||
set {
|
||||
PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity");
|
||||
|
||||
_velocity = value;
|
||||
PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity);
|
||||
RawVelocity = value;
|
||||
PhysicsScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
|
||||
PhysicsScene.PE.Activate(PhysBody, true);
|
||||
}
|
||||
}
|
||||
public override OMV.Vector3 Torque {
|
||||
get { return _torque; }
|
||||
set { _torque = value;
|
||||
get { return RawTorque; }
|
||||
set { RawTorque = value;
|
||||
}
|
||||
}
|
||||
public override float CollisionScore {
|
||||
|
@ -783,27 +615,6 @@ public sealed class BSCharacter : BSPhysObject
|
|||
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)
|
||||
{
|
||||
// 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) {
|
||||
}
|
||||
|
@ -887,7 +698,7 @@ public sealed class BSCharacter : BSPhysObject
|
|||
public override void UpdateProperties(EntityProperties entprop)
|
||||
{
|
||||
// Don't change position if standing on a stationary object.
|
||||
if (!_isStationaryStanding)
|
||||
if (!IsStationary)
|
||||
_position = entprop.Position;
|
||||
|
||||
_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
|
||||
// 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many
|
||||
// extra updates.
|
||||
if (!entprop.Velocity.ApproxEquals(_velocity, 0.1f))
|
||||
_velocity = entprop.Velocity;
|
||||
if (!entprop.Velocity.ApproxEquals(RawVelocity, 0.1f))
|
||||
RawVelocity = entprop.Velocity;
|
||||
|
||||
_acceleration = entprop.Acceleration;
|
||||
_rotationalVelocity = entprop.RotationalVelocity;
|
||||
|
@ -920,7 +731,7 @@ public sealed class BSCharacter : BSPhysObject
|
|||
// base.RequestPhysicsterseUpdate();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
* VariableName: used by the simulator and performs taint operations, etc
|
||||
* RawVariableName: direct reference to the BulletSim storage for the variable value
|
||||
* 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.
|
||||
GravModifier = 1.0f;
|
||||
Gravity = new OMV.Vector3(0f, 0f, BSParam.Gravity);
|
||||
HoverActive = false;
|
||||
|
||||
// We don't have any physical representation yet.
|
||||
PhysBody = new BulletBody(localID);
|
||||
|
@ -110,11 +111,10 @@ public abstract class BSPhysObject : PhysicsActor
|
|||
// Tell the object to clean up.
|
||||
public virtual void Destroy()
|
||||
{
|
||||
UnRegisterAllPreStepActions();
|
||||
UnRegisterAllPostStepActions();
|
||||
PhysicalActors.Enable(false);
|
||||
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 ForceOrientation { get; set; }
|
||||
|
||||
public abstract OMV.Vector3 RawVelocity { get; set; }
|
||||
public OMV.Vector3 RawVelocity { 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 float ForceBuoyancy { get; set; }
|
||||
|
||||
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
|
||||
public virtual float ForwardSpeed
|
||||
{
|
||||
|
@ -237,7 +270,45 @@ public abstract class BSPhysObject : PhysicsActor
|
|||
|
||||
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 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
|
||||
theActor.Enabled = enableActor;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The actor does not exist. If it should, create it.
|
||||
if (enableActor)
|
||||
{
|
||||
theActor = creator();
|
||||
PhysicalActors.Add(actorName, theActor);
|
||||
theActor.Enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Collisions
|
||||
|
||||
|
@ -255,7 +326,9 @@ public abstract class BSPhysObject : PhysicsActor
|
|||
protected CollisionFlags CurrentCollisionFlags { get; set; }
|
||||
// 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)
|
||||
protected bool ColliderIsMoving;
|
||||
public bool ColliderIsMoving;
|
||||
// Used by BSCharacter to manage standing (and not slipping)
|
||||
public bool IsStationary;
|
||||
|
||||
// Count of collisions for this object
|
||||
protected long CollisionAccumulation { get; set; }
|
||||
|
@ -293,7 +366,7 @@ public abstract class BSPhysObject : PhysicsActor
|
|||
protected CollisionEventUpdate CollisionCollection;
|
||||
// Remember collisions from last tick for fancy collision based actions
|
||||
// (like a BSCharacter walking up stairs).
|
||||
protected CollisionEventUpdate CollisionsLastTick;
|
||||
public CollisionEventUpdate CollisionsLastTick;
|
||||
|
||||
// The simulation step is telling this object about a collision.
|
||||
// Return 'true' if a collision was processed and should be sent up.
|
||||
|
@ -424,104 +497,6 @@ public abstract class BSPhysObject : PhysicsActor
|
|||
|
||||
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
|
||||
// different actors to modify the update before it is passed around
|
||||
public delegate void PreUpdatePropertyAction(ref EntityProperties entprop);
|
||||
|
@ -533,46 +508,6 @@ public abstract class BSPhysObject : PhysicsActor
|
|||
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
|
||||
|
||||
// High performance detailed logging routine used by the physical objects.
|
||||
|
|
|
@ -55,9 +55,6 @@ public class BSPrim : BSPhysObject
|
|||
private OMV.Vector3 _position;
|
||||
|
||||
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.Quaternion _orientation;
|
||||
private int _physicsActorType;
|
||||
|
@ -73,16 +70,13 @@ public class BSPrim : BSPhysObject
|
|||
private int CrossingFailures { get; set; }
|
||||
|
||||
public BSDynamics VehicleActor;
|
||||
public string VehicleActorName = "BasicVehicle";
|
||||
public const string VehicleActorName = "BasicVehicle";
|
||||
|
||||
private BSVMotor _targetMotor;
|
||||
private OMV.Vector3 _PIDTarget;
|
||||
private float _PIDTau;
|
||||
|
||||
private BSFMotor _hoverMotor;
|
||||
private float _PIDHoverHeight;
|
||||
private PIDHoverType _PIDHoverType;
|
||||
private float _PIDHoverTau;
|
||||
public const string HoverActorName = "HoverActor";
|
||||
public const String LockedAxisActorName = "BSPrim.LockedAxis";
|
||||
public const string MoveToTargetActorName = "MoveToTargetActor";
|
||||
public const string SetForceActorName = "SetForceActor";
|
||||
public const string SetTorqueActorName = "SetTorqueActor";
|
||||
|
||||
public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
|
||||
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).
|
||||
_orientation = rotation;
|
||||
_buoyancy = 0f;
|
||||
_velocity = OMV.Vector3.Zero;
|
||||
RawVelocity = OMV.Vector3.Zero;
|
||||
_rotationalVelocity = OMV.Vector3.Zero;
|
||||
BaseShape = pbs;
|
||||
_isPhysical = pisPhysical;
|
||||
_isVolumeDetect = false;
|
||||
|
||||
// We keep a handle to the vehicle actor so we can set vehicle parameters later.
|
||||
VehicleActor = new BSDynamics(PhysicsScene, this, VehicleActorName);
|
||||
PhysicalActors.Add(VehicleActorName, VehicleActor);
|
||||
|
||||
|
@ -233,7 +228,7 @@ public class BSPrim : BSPhysObject
|
|||
// Called at taint time!
|
||||
public override void ZeroMotion(bool inTaintTime)
|
||||
{
|
||||
_velocity = OMV.Vector3.Zero;
|
||||
RawVelocity = OMV.Vector3.Zero;
|
||||
_acceleration = OMV.Vector3.Zero;
|
||||
_rotationalVelocity = OMV.Vector3.Zero;
|
||||
|
||||
|
@ -270,19 +265,17 @@ public class BSPrim : BSPhysObject
|
|||
if (axis.Z != 1) locking.Z = 0f;
|
||||
LockedAxis = locking;
|
||||
|
||||
if (LockedAxis != LockedAxisFree)
|
||||
EnableActor(LockedAxis != LockedAxisFree, LockedAxisActorName, delegate()
|
||||
{
|
||||
PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate()
|
||||
{
|
||||
// If there is not already an axis locker, make one
|
||||
if (!PhysicalActors.HasActor(LockedAxisActorName))
|
||||
{
|
||||
DetailLog("{0},BSPrim.LockAngularMotion,taint,registeringLockAxisActor", LocalID);
|
||||
PhysicalActors.Add(LockedAxisActorName, new BSActorLockAxis(PhysicsScene, this, LockedAxisActorName));
|
||||
}
|
||||
UpdatePhysicalParameters();
|
||||
});
|
||||
}
|
||||
return new BSActorLockAxis(PhysicsScene, this, LockedAxisActorName);
|
||||
});
|
||||
|
||||
// Update parameters so the new actor's Refresh() action is called at the right time.
|
||||
PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate()
|
||||
{
|
||||
UpdatePhysicalParameters();
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -407,9 +400,9 @@ public class BSPrim : BSPhysObject
|
|||
ZeroMotion(inTaintTime);
|
||||
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;
|
||||
}
|
||||
if (_rotationalVelocity.LengthSquared() > BSParam.MaxAngularVelocitySquared)
|
||||
|
@ -506,48 +499,25 @@ public class BSPrim : BSPhysObject
|
|||
}
|
||||
|
||||
public override OMV.Vector3 Force {
|
||||
get { return _force; }
|
||||
get { return RawForce; }
|
||||
set {
|
||||
_force = value;
|
||||
if (_force != OMV.Vector3.Zero)
|
||||
RawForce = value;
|
||||
EnableActor(RawForce != OMV.Vector3.Zero, SetForceActorName, delegate()
|
||||
{
|
||||
// If the force is non-zero, it must be reapplied each tick because
|
||||
// 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);
|
||||
}
|
||||
return new BSActorSetForce(PhysicsScene, this, SetForceActorName);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public override int VehicleType {
|
||||
get {
|
||||
return (int)VehicleActor.Type; // if we are a vehicle, return that type
|
||||
return (int)VehicleActor.Type;
|
||||
}
|
||||
set {
|
||||
Vehicle type = (Vehicle)value;
|
||||
|
||||
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.
|
||||
VehicleActor.ProcessTypeChange(type);
|
||||
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 {
|
||||
get { return _velocity; }
|
||||
get { return RawVelocity; }
|
||||
set {
|
||||
_velocity = value;
|
||||
RawVelocity = value;
|
||||
PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate()
|
||||
{
|
||||
// DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
|
||||
ForceVelocity = _velocity;
|
||||
// DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, RawVelocity);
|
||||
ForceVelocity = RawVelocity;
|
||||
});
|
||||
}
|
||||
}
|
||||
public override OMV.Vector3 ForceVelocity {
|
||||
get { return _velocity; }
|
||||
get { return RawVelocity; }
|
||||
set {
|
||||
PhysicsScene.AssertInTaintTime("BSPrim.ForceVelocity");
|
||||
|
||||
_velocity = Util.ClampV(value, BSParam.MaxLinearVelocity);
|
||||
RawVelocity = Util.ClampV(value, BSParam.MaxLinearVelocity);
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
{
|
||||
DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, _velocity);
|
||||
PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity);
|
||||
DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, RawVelocity);
|
||||
PhysicsScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
|
||||
ActivateIfPhysical(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
public override OMV.Vector3 Torque {
|
||||
get { return _torque; }
|
||||
get { return RawTorque; }
|
||||
set {
|
||||
_torque = value;
|
||||
if (_torque != OMV.Vector3.Zero)
|
||||
RawTorque = value;
|
||||
EnableActor(RawTorque != OMV.Vector3.Zero, SetTorqueActorName, delegate()
|
||||
{
|
||||
// If the torque is non-zero, it must be reapplied each tick because
|
||||
// Bullet clears the forces applied last frame.
|
||||
RegisterPreStepAction("BSPrim.setTorque", LocalID,
|
||||
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);
|
||||
return new BSActorSetTorque(PhysicsScene, this, SetTorqueActorName);
|
||||
});
|
||||
DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, RawTorque);
|
||||
}
|
||||
}
|
||||
public override OMV.Vector3 Acceleration {
|
||||
|
@ -839,7 +786,6 @@ public class BSPrim : BSPhysObject
|
|||
MakeDynamic(IsStatic);
|
||||
|
||||
// Update vehicle specific parameters (after MakeDynamic() so can change physical parameters)
|
||||
VehicleActor.Refresh();
|
||||
PhysicalActors.Refresh();
|
||||
|
||||
// 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
|
||||
ForcePosition = _position;
|
||||
ForceVelocity = _velocity;
|
||||
ForceVelocity = RawVelocity;
|
||||
ForceRotationalVelocity = _rotationalVelocity;
|
||||
|
||||
// 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.
|
||||
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 {
|
||||
set {
|
||||
if (value)
|
||||
base.MoveToTargetActive = value;
|
||||
EnableActor(MoveToTargetActive, MoveToTargetActorName, delegate()
|
||||
{
|
||||
// We're taking over after this.
|
||||
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);
|
||||
}
|
||||
return new BSActorMoveToTarget(PhysicsScene, this, MoveToTargetActorName);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1175,87 +1047,13 @@ public class BSPrim : BSPhysObject
|
|||
// Hover Height will override MoveTo target's Z
|
||||
public override bool PIDHoverActive {
|
||||
set {
|
||||
if (value)
|
||||
base.HoverActive = value;
|
||||
EnableActor(HoverActive, HoverActorName, delegate()
|
||||
{
|
||||
// Turning the target on
|
||||
_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);
|
||||
}
|
||||
return new BSActorHover(PhysicsScene, this, HoverActorName);
|
||||
});
|
||||
}
|
||||
}
|
||||
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) {
|
||||
// Per documentation, max force is limited.
|
||||
|
@ -1324,10 +1122,8 @@ public class BSPrim : BSPhysObject
|
|||
}
|
||||
}
|
||||
|
||||
public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
|
||||
AddAngularForce(force, pushforce, false);
|
||||
}
|
||||
public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime)
|
||||
// BSPhysObject.AddAngularForce()
|
||||
public override void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime)
|
||||
{
|
||||
if (force.IsFinite())
|
||||
{
|
||||
|
@ -1661,7 +1457,7 @@ public class BSPrim : BSPhysObject
|
|||
{
|
||||
// Create the correct physical representation for this type of object.
|
||||
// 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)
|
||||
{
|
||||
// Called if the current prim body is about to be destroyed.
|
||||
|
@ -1675,9 +1471,9 @@ public class BSPrim : BSPhysObject
|
|||
return;
|
||||
}
|
||||
|
||||
// Called at taint-time
|
||||
protected virtual void RemoveBodyDependencies()
|
||||
{
|
||||
VehicleActor.RemoveBodyDependencies();
|
||||
PhysicalActors.RemoveBodyDependencies();
|
||||
}
|
||||
|
||||
|
@ -1685,6 +1481,7 @@ public class BSPrim : BSPhysObject
|
|||
// the world that things have changed.
|
||||
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);
|
||||
|
||||
// DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG
|
||||
|
@ -1694,8 +1491,8 @@ public class BSPrim : BSPhysObject
|
|||
_orientation = entprop.Rotation;
|
||||
// DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be
|
||||
// very sensitive to velocity changes.
|
||||
if (entprop.Velocity == OMV.Vector3.Zero || !entprop.Velocity.ApproxEquals(_velocity, BSParam.UpdateVelocityChangeThreshold))
|
||||
_velocity = entprop.Velocity;
|
||||
if (entprop.Velocity == OMV.Vector3.Zero || !entprop.Velocity.ApproxEquals(RawVelocity, BSParam.UpdateVelocityChangeThreshold))
|
||||
RawVelocity = entprop.Velocity;
|
||||
_acceleration = entprop.Acceleration;
|
||||
_rotationalVelocity = entprop.RotationalVelocity;
|
||||
|
||||
|
@ -1705,7 +1502,7 @@ public class BSPrim : BSPhysObject
|
|||
if (PositionSanityCheck(true /* inTaintTime */ ))
|
||||
{
|
||||
entprop.Position = _position;
|
||||
entprop.Velocity = _velocity;
|
||||
entprop.Velocity = RawVelocity;
|
||||
entprop.RotationalVelocity = _rotationalVelocity;
|
||||
entprop.Acceleration = _acceleration;
|
||||
}
|
||||
|
@ -1717,16 +1514,8 @@ public class BSPrim : BSPhysObject
|
|||
LastEntityProperties = CurrentEntityProperties;
|
||||
CurrentEntityProperties = entprop;
|
||||
|
||||
// Note that BSPrim can be overloaded by BSPrimLinkable which controls updates from root and children prims.
|
||||
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.
|
||||
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
|
||||
Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ Enable vehicle border crossings (at least as poorly as ODE)
|
|||
Terrain skirts
|
||||
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)
|
||||
Lock axis
|
||||
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.
|
||||
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.
|
||||
DONE 20130120: BulletSim properly applies force in vehicle relative coordinates.
|
||||
Nebadon vehicles turning funny in arena (DONE)
|
||||
Lock axis (DONE 20130401)
|
||||
|
||||
|
|
|
@ -137,10 +137,11 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
|||
userID, sessionID, secureSessionID);
|
||||
|
||||
NameValueCollection requestArgs = new NameValueCollection
|
||||
{
|
||||
{ "RequestMethod", "AddSession" },
|
||||
{ "UserID", userID.ToString() }
|
||||
};
|
||||
{
|
||||
{ "RequestMethod", "AddSession" },
|
||||
{ "UserID", userID.ToString() }
|
||||
};
|
||||
|
||||
if (sessionID != UUID.Zero)
|
||||
{
|
||||
requestArgs["SessionID"] = sessionID.ToString();
|
||||
|
@ -158,13 +159,13 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
|||
|
||||
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
|
||||
{
|
||||
{ "RequestMethod", "RemoveSession" },
|
||||
{ "SessionID", sessionID.ToString() }
|
||||
};
|
||||
{
|
||||
{ "RequestMethod", "RemoveSession" },
|
||||
{ "SessionID", sessionID.ToString() }
|
||||
};
|
||||
|
||||
OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
|
||||
bool success = response["Success"].AsBoolean();
|
||||
|
@ -177,13 +178,13 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
|||
|
||||
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
|
||||
{
|
||||
{ "RequestMethod", "RemoveSessions" },
|
||||
{ "SceneID", regionID.ToString() }
|
||||
};
|
||||
{
|
||||
{ "RequestMethod", "RemoveSessions" },
|
||||
{ "SceneID", regionID.ToString() }
|
||||
};
|
||||
|
||||
OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
|
||||
bool success = response["Success"].AsBoolean();
|
||||
|
@ -202,49 +203,46 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
|||
|
||||
public PresenceInfo GetAgent(UUID sessionID)
|
||||
{
|
||||
// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting session data for agent with sessionID " + sessionID);
|
||||
|
||||
NameValueCollection requestArgs = new NameValueCollection
|
||||
OSDMap sessionResponse = GetSessionDataFromSessionID(sessionID);
|
||||
if (sessionResponse == null)
|
||||
{
|
||||
{ "RequestMethod", "GetSession" },
|
||||
{ "SessionID", sessionID.ToString() }
|
||||
};
|
||||
|
||||
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());
|
||||
m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve session {0}: {1}",sessionID.ToString(),sessionResponse["Message"].AsString());
|
||||
return null;
|
||||
}
|
||||
else
|
||||
|
||||
UUID userID = sessionResponse["UserID"].AsUUID();
|
||||
OSDMap userResponse = GetUserData(userID);
|
||||
if (userResponse == null)
|
||||
{
|
||||
m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve session " + sessionID + ": " + sessionResponse["Message"].AsString());
|
||||
m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for {0}: {1}",userID.ToString(),userResponse["Message"].AsString());
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
return ResponseToPresenceInfo(sessionResponse);
|
||||
}
|
||||
|
||||
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;
|
||||
if (UUID.TryParse(userIDs[i], out userID) && userID != UUID.Zero)
|
||||
presences.AddRange(GetSessions(userID));
|
||||
{ "RequestMethod", "GetSessions" },
|
||||
{ "UserIDList", String.Join(",",userIDs) }
|
||||
};
|
||||
|
||||
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();
|
||||
|
@ -262,7 +260,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
|||
|
||||
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
|
||||
if (!LogoutAgent(sessionID))
|
||||
|
@ -270,11 +268,11 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
|||
|
||||
// Save our last position as user data
|
||||
NameValueCollection requestArgs = new NameValueCollection
|
||||
{
|
||||
{ "RequestMethod", "AddUserData" },
|
||||
{ "UserID", userID.ToString() },
|
||||
{ "LastLocation", SerializeLocation(regionID, lastPosition, lastLookAt) }
|
||||
};
|
||||
{
|
||||
{ "RequestMethod", "AddUserData" },
|
||||
{ "UserID", userID.ToString() },
|
||||
{ "LastLocation", SerializeLocation(regionID, lastPosition, lastLookAt) }
|
||||
};
|
||||
|
||||
OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
|
||||
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)
|
||||
{
|
||||
// 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
|
||||
{
|
||||
{ "RequestMethod", "AddUserData" },
|
||||
{ "UserID", userID.ToString() },
|
||||
{ "HomeLocation", SerializeLocation(regionID, position, lookAt) }
|
||||
};
|
||||
{
|
||||
{ "RequestMethod", "AddUserData" },
|
||||
{ "UserID", userID.ToString() },
|
||||
{ "HomeLocation", SerializeLocation(regionID, position, lookAt) }
|
||||
};
|
||||
|
||||
OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
|
||||
bool success = response["Success"].AsBoolean();
|
||||
|
@ -312,23 +310,14 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
|||
|
||||
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);
|
||||
// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting user data for " + userID);
|
||||
|
||||
NameValueCollection requestArgs = new NameValueCollection
|
||||
{
|
||||
{ "RequestMethod", "GetUser" },
|
||||
{ "UserID", userID.ToString() }
|
||||
};
|
||||
|
||||
OSDMap userResponse = WebUtil.PostToService(m_serverUrl, requestArgs);
|
||||
if (userResponse["Success"].AsBoolean())
|
||||
OSDMap userResponse = GetUserData(userID);
|
||||
if (userResponse != null)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -338,65 +327,49 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
|||
|
||||
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
|
||||
{
|
||||
{ "RequestMethod", "GetUser" },
|
||||
{ "UserID", userID.ToString() }
|
||||
};
|
||||
{
|
||||
{ "RequestMethod", "GetUser" },
|
||||
{ "UserID", userID.ToString() }
|
||||
};
|
||||
|
||||
OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
|
||||
if (response["Success"].AsBoolean() && response["User"] is OSDMap)
|
||||
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;
|
||||
}
|
||||
|
||||
private List<PresenceInfo> GetSessions(UUID userID)
|
||||
private OSDMap GetSessionDataFromSessionID(UUID sessionID)
|
||||
{
|
||||
List<PresenceInfo> presences = new List<PresenceInfo>(1);
|
||||
|
||||
OSDMap userResponse = GetUserData(userID);
|
||||
if (userResponse != null)
|
||||
{
|
||||
// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting sessions for " + userID);
|
||||
|
||||
NameValueCollection requestArgs = new NameValueCollection
|
||||
NameValueCollection requestArgs = new NameValueCollection
|
||||
{
|
||||
{ "RequestMethod", "GetSession" },
|
||||
{ "UserID", userID.ToString() }
|
||||
{ "RequestMethod", "GetSession" },
|
||||
{ "SessionID", sessionID.ToString() }
|
||||
};
|
||||
|
||||
OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
|
||||
if (response["Success"].AsBoolean())
|
||||
{
|
||||
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());
|
||||
// }
|
||||
}
|
||||
OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
|
||||
if (response["Success"].AsBoolean())
|
||||
return response;
|
||||
|
||||
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)
|
||||
{
|
||||
// Save our current location as session data
|
||||
NameValueCollection requestArgs = new NameValueCollection
|
||||
{
|
||||
{ "RequestMethod", "UpdateSession" },
|
||||
{ "SessionID", sessionID.ToString() },
|
||||
{ "SceneID", regionID.ToString() },
|
||||
{ "ScenePosition", lastPosition.ToString() },
|
||||
{ "SceneLookAt", lastLookAt.ToString() }
|
||||
};
|
||||
{
|
||||
{ "RequestMethod", "UpdateSession" },
|
||||
{ "SessionID", sessionID.ToString() },
|
||||
{ "SceneID", regionID.ToString() },
|
||||
{ "ScenePosition", lastPosition.ToString() },
|
||||
{ "SceneLookAt", lastLookAt.ToString() }
|
||||
};
|
||||
|
||||
OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
|
||||
bool success = response["Success"].AsBoolean();
|
||||
|
@ -407,7 +380,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
|||
return success;
|
||||
}
|
||||
|
||||
private PresenceInfo ResponseToPresenceInfo(OSDMap sessionResponse, OSDMap userResponse)
|
||||
private PresenceInfo ResponseToPresenceInfo(OSDMap sessionResponse)
|
||||
{
|
||||
if (sessionResponse == null)
|
||||
return null;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<configuration>
|
||||
<dllmap os="windows" cpu="x86" dll="BulletSim" target="lib32/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-64,ia64" dll="BulletSim" target="lib64/libBulletSim.so" />
|
||||
</configuration>
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue