Merge branch 'master' into careminster
Conflicts: OpenSim/Data/MySQL/MySQLAssetData.cs OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.csavinationmerge
commit
7cf377fff0
|
@ -101,6 +101,7 @@ what it is today.
|
|||
* jhurliman
|
||||
* John R Sohn (XenReborn)
|
||||
* jonc
|
||||
* Jon Cundill
|
||||
* Junta Kohime
|
||||
* Kayne
|
||||
* Kevin Cozens
|
||||
|
|
|
@ -142,7 +142,8 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error("[ASSETS DB]: MySql failure fetching asset " + assetID + ": " + e.Message);
|
||||
m_log.Error(
|
||||
string.Format("[ASSETS DB]: MySql failure fetching asset {0}. Exception ", assetID), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -243,10 +244,11 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[ASSETS DB]: " +
|
||||
"MySql failure updating access_time for asset {0} with name {1}" + Environment.NewLine + e.ToString()
|
||||
+ Environment.NewLine + "Attempting reconnection", asset.FullID, asset.Name);
|
||||
m_log.Error(
|
||||
string.Format(
|
||||
"[ASSETS DB]: Failure updating access_time for asset {0} with name {1}. Exception ",
|
||||
asset.FullID, asset.Name),
|
||||
e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -286,8 +288,8 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[ASSETS DB]: MySql failure fetching asset {0}" + Environment.NewLine + e.ToString(), uuid);
|
||||
m_log.Error(
|
||||
string.Format("[ASSETS DB]: MySql failure fetching asset {0}. Exception ", uuid), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -346,7 +348,11 @@ namespace OpenSim.Data.MySQL
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error("[ASSETS DB]: MySql failure fetching asset set" + Environment.NewLine + e.ToString());
|
||||
m_log.Error(
|
||||
string.Format(
|
||||
"[ASSETS DB]: MySql failure fetching asset set from {0}, count {1}. Exception ",
|
||||
start, count),
|
||||
e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,6 +76,11 @@ namespace OpenSim.Framework.Servers
|
|||
|
||||
protected void CreatePIDFile(string path)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
m_log.ErrorFormat(
|
||||
"[SERVER BASE]: Previous pid file {0} still exists on startup. Possibly previously unclean shutdown.",
|
||||
path);
|
||||
|
||||
try
|
||||
{
|
||||
string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
|
||||
|
|
|
@ -358,7 +358,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
|||
bool asAttachment)
|
||||
{
|
||||
CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero);
|
||||
Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>();
|
||||
// Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>();
|
||||
|
||||
foreach (SceneObjectGroup objectGroup in objlist)
|
||||
{
|
||||
|
@ -379,7 +379,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
|||
objectGroup.AbsolutePosition.Z);
|
||||
|
||||
Quaternion inventoryStoredRotation = objectGroup.GroupRotation;
|
||||
originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition;
|
||||
//originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition;
|
||||
|
||||
// Restore attachment data after trip through the sim
|
||||
if (objectGroup.RootPart.AttachPoint > 0)
|
||||
|
@ -418,9 +418,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
|||
else
|
||||
itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment);
|
||||
|
||||
// Restore the position of each group now that it has been stored to inventory.
|
||||
foreach (SceneObjectGroup objectGroup in objlist)
|
||||
objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID];
|
||||
// // Restore the position of each group now that it has been stored to inventory.
|
||||
// foreach (SceneObjectGroup objectGroup in objlist)
|
||||
// objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID];
|
||||
|
||||
InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID);
|
||||
|
||||
|
@ -866,7 +866,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
|||
return null;
|
||||
}
|
||||
|
||||
if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, attachment))
|
||||
if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment))
|
||||
return null;
|
||||
|
||||
for (int i = 0; i < objlist.Count; i++)
|
||||
|
@ -965,10 +965,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
|||
/// <param name="item"></param>
|
||||
/// <param name="objlist"></param>
|
||||
/// <param name="pos"></param>
|
||||
/// <param name="veclist">
|
||||
/// List of vector position adjustments for a coalesced objects. For ordinary objects
|
||||
/// this list will contain just Vector3.Zero. The order of adjustments must match the order of objlist
|
||||
/// </param>
|
||||
/// <param name="isAttachment"></param>
|
||||
/// <returns>true if we can processed with rezzing, false if we need to abort</returns>
|
||||
private bool DoPreRezWhenFromItem(
|
||||
IClientAPI remoteClient, InventoryItemBase item, List<SceneObjectGroup> objlist, Vector3 pos, bool isAttachment)
|
||||
IClientAPI remoteClient, InventoryItemBase item, List<SceneObjectGroup> objlist,
|
||||
Vector3 pos, List<Vector3> veclist, bool isAttachment)
|
||||
{
|
||||
UUID fromUserInventoryItemId = UUID.Zero;
|
||||
|
||||
|
@ -991,28 +996,29 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
|||
}
|
||||
}
|
||||
|
||||
int primcount = 0;
|
||||
foreach (SceneObjectGroup g in objlist)
|
||||
primcount += g.PrimCount;
|
||||
|
||||
if (!m_Scene.Permissions.CanRezObject(
|
||||
primcount, remoteClient.AgentId, pos)
|
||||
&& !isAttachment)
|
||||
for (int i = 0; i < objlist.Count; i++)
|
||||
{
|
||||
// The client operates in no fail mode. It will
|
||||
// have already removed the item from the folder
|
||||
// if it's no copy.
|
||||
// Put it back if it's not an attachment
|
||||
//
|
||||
if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment))
|
||||
remoteClient.SendBulkUpdateInventory(item);
|
||||
SceneObjectGroup g = objlist[i];
|
||||
|
||||
ILandObject land = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y);
|
||||
remoteClient.SendAlertMessage(string.Format(
|
||||
"Can't rez object '{0}' at <{1:F3}, {2:F3}, {3:F3}> on parcel '{4}' in region {5}.",
|
||||
item.Name, pos.X, pos.Y, pos.Z, land != null ? land.LandData.Name : "Unknown", m_Scene.RegionInfo.RegionName));
|
||||
if (!m_Scene.Permissions.CanRezObject(
|
||||
g.PrimCount, remoteClient.AgentId, pos + veclist[i])
|
||||
&& !isAttachment)
|
||||
{
|
||||
// The client operates in no fail mode. It will
|
||||
// have already removed the item from the folder
|
||||
// if it's no copy.
|
||||
// Put it back if it's not an attachment
|
||||
//
|
||||
if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment))
|
||||
remoteClient.SendBulkUpdateInventory(item);
|
||||
|
||||
return false;
|
||||
ILandObject land = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y);
|
||||
remoteClient.SendAlertMessage(string.Format(
|
||||
"Can't rez object '{0}' at <{1:F3}, {2:F3}, {3:F3}> on parcel '{4}' in region {5}.",
|
||||
item.Name, pos.X, pos.Y, pos.Z, land != null ? land.LandData.Name : "Unknown", m_Scene.Name));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < objlist.Count; i++)
|
||||
|
|
|
@ -412,7 +412,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
|||
//public bool HttpVerboseThrottle = true; // not implemented
|
||||
public List<string> HttpCustomHeaders = null;
|
||||
public bool HttpPragmaNoCache = true;
|
||||
private Thread httpThread;
|
||||
|
||||
// Request info
|
||||
private UUID _itemID;
|
||||
|
|
|
@ -1453,6 +1453,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions
|
|||
|
||||
bool permission = false;
|
||||
|
||||
// m_log.DebugFormat("[PERMISSIONS MODULE]: Checking rez object at {0} in {1}", objectPosition, m_scene.Name);
|
||||
|
||||
ILandObject land = m_scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y);
|
||||
if (land == null) return false;
|
||||
|
||||
|
|
|
@ -5647,12 +5647,12 @@ Environment.Exit(1);
|
|||
List<SceneObjectGroup> objects,
|
||||
out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
|
||||
{
|
||||
minX = 256;
|
||||
maxX = -256;
|
||||
minY = 256;
|
||||
maxY = -256;
|
||||
minZ = 8192;
|
||||
maxZ = -256;
|
||||
minX = float.MaxValue;
|
||||
maxX = float.MinValue;
|
||||
minY = float.MaxValue;
|
||||
maxY = float.MinValue;
|
||||
minZ = float.MaxValue;
|
||||
maxZ = float.MinValue;
|
||||
|
||||
List<Vector3> offsets = new List<Vector3>();
|
||||
|
||||
|
|
|
@ -0,0 +1,285 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyrightD
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using OpenSim.Region.Physics.Manager;
|
||||
|
||||
using OMV = OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
public class BSActorAvatarMove : BSActor
|
||||
{
|
||||
BSVMotor m_velocityMotor;
|
||||
|
||||
public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName)
|
||||
: base(physicsScene, pObj, actorName)
|
||||
{
|
||||
m_velocityMotor = null;
|
||||
m_physicsScene.DetailLog("{0},BSActorAvatarMove,constructor", m_controllingPrim.LocalID);
|
||||
}
|
||||
|
||||
// BSActor.isActive
|
||||
public override bool isActive
|
||||
{
|
||||
get { return Enabled && m_controllingPrim.IsPhysicallyActive; }
|
||||
}
|
||||
|
||||
// Release any connections and resources used by the actor.
|
||||
// BSActor.Dispose()
|
||||
public override void Dispose()
|
||||
{
|
||||
Enabled = false;
|
||||
}
|
||||
|
||||
// Called when physical parameters (properties set in Bullet) need to be re-applied.
|
||||
// Called at taint-time.
|
||||
// BSActor.Refresh()
|
||||
public override void Refresh()
|
||||
{
|
||||
m_physicsScene.DetailLog("{0},BSActorAvatarMove,refresh", m_controllingPrim.LocalID);
|
||||
|
||||
// If the object is physically active, add the hoverer prestep action
|
||||
if (isActive)
|
||||
{
|
||||
ActivateAvatarMove();
|
||||
}
|
||||
else
|
||||
{
|
||||
DeactivateAvatarMove();
|
||||
}
|
||||
}
|
||||
|
||||
// The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
|
||||
// Register a prestep action to restore physical requirements before the next simulation step.
|
||||
// Called at taint-time.
|
||||
// BSActor.RemoveBodyDependencies()
|
||||
public override void RemoveBodyDependencies()
|
||||
{
|
||||
// Nothing to do for the hoverer since it is all software at pre-step action time.
|
||||
}
|
||||
|
||||
// Usually called when target velocity changes to set the current velocity and the target
|
||||
// into the movement motor.
|
||||
public void SetVelocityAndTarget(OMV.Vector3 vel, OMV.Vector3 targ, bool inTaintTime)
|
||||
{
|
||||
m_physicsScene.TaintedObject(inTaintTime, "BSActorAvatarMove.setVelocityAndTarget", delegate()
|
||||
{
|
||||
if (m_velocityMotor != null)
|
||||
{
|
||||
m_velocityMotor.Reset();
|
||||
m_velocityMotor.SetTarget(targ);
|
||||
m_velocityMotor.SetCurrent(vel);
|
||||
m_velocityMotor.Enabled = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// If a hover motor has not been created, create one and start the hovering.
|
||||
private void ActivateAvatarMove()
|
||||
{
|
||||
if (m_velocityMotor == null)
|
||||
{
|
||||
// Infinite decay and timescale values so motor only changes current to target values.
|
||||
m_velocityMotor = new BSVMotor("BSCharacter.Velocity",
|
||||
0.2f, // time scale
|
||||
BSMotor.Infinite, // decay time scale
|
||||
BSMotor.InfiniteVector, // friction timescale
|
||||
1f // efficiency
|
||||
);
|
||||
// _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
|
||||
SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity, true /* inTaintTime */);
|
||||
|
||||
m_physicsScene.BeforeStep += Mover;
|
||||
}
|
||||
}
|
||||
|
||||
private void DeactivateAvatarMove()
|
||||
{
|
||||
if (m_velocityMotor != null)
|
||||
{
|
||||
m_physicsScene.BeforeStep -= Mover;
|
||||
m_velocityMotor = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Called just before the simulation step. Update the vertical position for hoverness.
|
||||
private void Mover(float timeStep)
|
||||
{
|
||||
// Don't do movement while the object is selected.
|
||||
if (!isActive)
|
||||
return;
|
||||
|
||||
// TODO: Decide if the step parameters should be changed depending on the avatar's
|
||||
// state (flying, colliding, ...). There is code in ODE to do this.
|
||||
|
||||
// COMMENTARY: when the user is making the avatar walk, except for falling, the velocity
|
||||
// specified for the avatar is the one that should be used. For falling, if the avatar
|
||||
// is not flying and is not colliding then it is presumed to be falling and the Z
|
||||
// component is not fooled with (thus allowing gravity to do its thing).
|
||||
// When the avatar is standing, though, the user has specified a velocity of zero and
|
||||
// the avatar should be standing. But if the avatar is pushed by something in the world
|
||||
// (raising elevator platform, moving vehicle, ...) the avatar should be allowed to
|
||||
// move. Thus, the velocity cannot be forced to zero. The problem is that small velocity
|
||||
// errors can creap in and the avatar will slowly float off in some direction.
|
||||
// So, the problem is that, when an avatar is standing, we cannot tell creaping error
|
||||
// from real pushing.
|
||||
// The code below uses whether the collider is static or moving to decide whether to zero motion.
|
||||
|
||||
m_velocityMotor.Step(timeStep);
|
||||
m_controllingPrim.IsStationary = false;
|
||||
|
||||
// If we're not supposed to be moving, make sure things are zero.
|
||||
if (m_velocityMotor.ErrorIsZero() && m_velocityMotor.TargetValue == OMV.Vector3.Zero)
|
||||
{
|
||||
// The avatar shouldn't be moving
|
||||
m_velocityMotor.Zero();
|
||||
|
||||
if (m_controllingPrim.IsColliding)
|
||||
{
|
||||
// If we are colliding with a stationary object, presume we're standing and don't move around
|
||||
if (!m_controllingPrim.ColliderIsMoving)
|
||||
{
|
||||
m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", m_controllingPrim.LocalID);
|
||||
m_controllingPrim.IsStationary = true;
|
||||
m_controllingPrim.ZeroMotion(true /* inTaintTime */);
|
||||
}
|
||||
|
||||
// Standing has more friction on the ground
|
||||
if (m_controllingPrim.Friction != BSParam.AvatarStandingFriction)
|
||||
{
|
||||
m_controllingPrim.Friction = BSParam.AvatarStandingFriction;
|
||||
m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_controllingPrim.Flying)
|
||||
{
|
||||
// Flying and not collising and velocity nearly zero.
|
||||
m_controllingPrim.ZeroMotion(true /* inTaintTime */);
|
||||
}
|
||||
}
|
||||
|
||||
m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}",
|
||||
m_controllingPrim.LocalID, m_velocityMotor.TargetValue, m_controllingPrim.IsColliding);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Supposed to be moving.
|
||||
OMV.Vector3 stepVelocity = m_velocityMotor.CurrentValue;
|
||||
|
||||
if (m_controllingPrim.Friction != BSParam.AvatarFriction)
|
||||
{
|
||||
// Probably starting up walking. Set friction to moving friction.
|
||||
m_controllingPrim.Friction = BSParam.AvatarFriction;
|
||||
m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction);
|
||||
}
|
||||
|
||||
// If falling, we keep the world's downward vector no matter what the other axis specify.
|
||||
// The check for RawVelocity.Z < 0 makes jumping work (temporary upward force).
|
||||
if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding)
|
||||
{
|
||||
if (m_controllingPrim.RawVelocity.Z < 0)
|
||||
stepVelocity.Z = m_controllingPrim.RawVelocity.Z;
|
||||
// DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity);
|
||||
}
|
||||
|
||||
// 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force.
|
||||
OMV.Vector3 moveForce = (stepVelocity - m_controllingPrim.RawVelocity) * m_controllingPrim.Mass;
|
||||
|
||||
// Should we check for move force being small and forcing velocity to zero?
|
||||
|
||||
// Add special movement force to allow avatars to walk up stepped surfaces.
|
||||
moveForce += WalkUpStairs();
|
||||
|
||||
m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}",
|
||||
m_controllingPrim.LocalID, stepVelocity, m_controllingPrim.RawVelocity, m_controllingPrim.Mass, moveForce);
|
||||
m_physicsScene.PE.ApplyCentralImpulse(m_controllingPrim.PhysBody, moveForce);
|
||||
}
|
||||
}
|
||||
|
||||
// Decide if the character is colliding with a low object and compute a force to pop the
|
||||
// avatar up so it can walk up and over the low objects.
|
||||
private OMV.Vector3 WalkUpStairs()
|
||||
{
|
||||
OMV.Vector3 ret = OMV.Vector3.Zero;
|
||||
|
||||
// This test is done if moving forward, not flying and is colliding with something.
|
||||
// DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}",
|
||||
// LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count);
|
||||
if (m_controllingPrim.IsColliding && !m_controllingPrim.Flying && m_controllingPrim.TargetVelocitySpeed > 0.1f /* && ForwardSpeed < 0.1f */)
|
||||
{
|
||||
// The range near the character's feet where we will consider stairs
|
||||
float nearFeetHeightMin = m_controllingPrim.RawPosition.Z - (m_controllingPrim.Size.Z / 2f) + 0.05f;
|
||||
float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight;
|
||||
|
||||
// Look for a collision point that is near the character's feet and is oriented the same as the charactor is
|
||||
foreach (KeyValuePair<uint, ContactPoint> kvp in m_controllingPrim.CollisionsLastTick.m_objCollisionList)
|
||||
{
|
||||
// Don't care about collisions with the terrain
|
||||
if (kvp.Key > m_physicsScene.TerrainManager.HighestTerrainID)
|
||||
{
|
||||
OMV.Vector3 touchPosition = kvp.Value.Position;
|
||||
// DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}",
|
||||
// LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition);
|
||||
if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax)
|
||||
{
|
||||
// This contact is within the 'near the feet' range.
|
||||
// The normal should be our contact point to the object so it is pointing away
|
||||
// thus the difference between our facing orientation and the normal should be small.
|
||||
OMV.Vector3 directionFacing = OMV.Vector3.UnitX * m_controllingPrim.RawOrientation;
|
||||
OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal);
|
||||
float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal));
|
||||
if (diff < BSParam.AvatarStepApproachFactor)
|
||||
{
|
||||
// Found the stairs contact point. Push up a little to raise the character.
|
||||
float upForce = (touchPosition.Z - nearFeetHeightMin) * m_controllingPrim.Mass * BSParam.AvatarStepForceFactor;
|
||||
ret = new OMV.Vector3(0f, 0f, upForce);
|
||||
|
||||
// Also move the avatar up for the new height
|
||||
OMV.Vector3 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight / 2f);
|
||||
m_controllingPrim.ForcePosition = m_controllingPrim.RawPosition + displacement;
|
||||
}
|
||||
m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},faceDir={3},norm={4},diff={5},ret={6}",
|
||||
m_controllingPrim.LocalID, touchPosition, nearFeetHeightMin, directionFacing, touchNormal, diff, ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyrightD
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using OpenSim.Region.Physics.Manager;
|
||||
|
||||
using OMV = OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
public class BSActorHover : BSActor
|
||||
{
|
||||
private BSFMotor m_hoverMotor;
|
||||
|
||||
public BSActorHover(BSScene physicsScene, BSPhysObject pObj, string actorName)
|
||||
: base(physicsScene, pObj, actorName)
|
||||
{
|
||||
m_hoverMotor = null;
|
||||
m_physicsScene.DetailLog("{0},BSActorHover,constructor", m_controllingPrim.LocalID);
|
||||
}
|
||||
|
||||
// BSActor.isActive
|
||||
public override bool isActive
|
||||
{
|
||||
get { return Enabled; }
|
||||
}
|
||||
|
||||
// Release any connections and resources used by the actor.
|
||||
// BSActor.Dispose()
|
||||
public override void Dispose()
|
||||
{
|
||||
Enabled = false;
|
||||
}
|
||||
|
||||
// Called when physical parameters (properties set in Bullet) need to be re-applied.
|
||||
// Called at taint-time.
|
||||
// BSActor.Refresh()
|
||||
public override void Refresh()
|
||||
{
|
||||
m_physicsScene.DetailLog("{0},BSActorHover,refresh", m_controllingPrim.LocalID);
|
||||
|
||||
// If not active any more, turn me off
|
||||
if (!m_controllingPrim.HoverActive)
|
||||
{
|
||||
SetEnabled(false);
|
||||
}
|
||||
|
||||
// If the object is physically active, add the hoverer prestep action
|
||||
if (isActive)
|
||||
{
|
||||
ActivateHover();
|
||||
}
|
||||
else
|
||||
{
|
||||
DeactivateHover();
|
||||
}
|
||||
}
|
||||
|
||||
// The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
|
||||
// Register a prestep action to restore physical requirements before the next simulation step.
|
||||
// Called at taint-time.
|
||||
// BSActor.RemoveBodyDependencies()
|
||||
public override void RemoveBodyDependencies()
|
||||
{
|
||||
// Nothing to do for the hoverer since it is all software at pre-step action time.
|
||||
}
|
||||
|
||||
// If a hover motor has not been created, create one and start the hovering.
|
||||
private void ActivateHover()
|
||||
{
|
||||
if (m_hoverMotor == null)
|
||||
{
|
||||
// Turning the target on
|
||||
m_hoverMotor = new BSFMotor("BSActorHover",
|
||||
m_controllingPrim.HoverTau, // timeScale
|
||||
BSMotor.Infinite, // decay time scale
|
||||
BSMotor.Infinite, // friction timescale
|
||||
1f // efficiency
|
||||
);
|
||||
m_hoverMotor.SetTarget(ComputeCurrentHoverHeight());
|
||||
m_hoverMotor.SetCurrent(m_controllingPrim.RawPosition.Z);
|
||||
m_hoverMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG so motor will output detail log messages.
|
||||
|
||||
m_physicsScene.BeforeStep += Hoverer;
|
||||
}
|
||||
}
|
||||
|
||||
private void DeactivateHover()
|
||||
{
|
||||
if (m_hoverMotor != null)
|
||||
{
|
||||
m_physicsScene.BeforeStep -= Hoverer;
|
||||
m_hoverMotor = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Called just before the simulation step. Update the vertical position for hoverness.
|
||||
private void Hoverer(float timeStep)
|
||||
{
|
||||
// Don't do hovering while the object is selected.
|
||||
if (!isActive)
|
||||
return;
|
||||
|
||||
m_hoverMotor.SetCurrent(m_controllingPrim.RawPosition.Z);
|
||||
m_hoverMotor.SetTarget(ComputeCurrentHoverHeight());
|
||||
float targetHeight = m_hoverMotor.Step(timeStep);
|
||||
|
||||
// 'targetHeight' is where we'd like the Z of the prim to be at this moment.
|
||||
// Compute the amount of force to push us there.
|
||||
float moveForce = (targetHeight - m_controllingPrim.RawPosition.Z) * m_controllingPrim.RawMass;
|
||||
// Undo anything the object thinks it's doing at the moment
|
||||
moveForce = -m_controllingPrim.RawVelocity.Z * m_controllingPrim.Mass;
|
||||
|
||||
m_physicsScene.PE.ApplyCentralImpulse(m_controllingPrim.PhysBody, new OMV.Vector3(0f, 0f, moveForce));
|
||||
m_physicsScene.DetailLog("{0},BSPrim.Hover,move,targHt={1},moveForce={2},mass={3}",
|
||||
m_controllingPrim.LocalID, targetHeight, moveForce, m_controllingPrim.RawMass);
|
||||
}
|
||||
|
||||
// Based on current position, determine what we should be hovering at now.
|
||||
// Must recompute often. What if we walked offa cliff>
|
||||
private float ComputeCurrentHoverHeight()
|
||||
{
|
||||
float ret = m_controllingPrim.HoverHeight;
|
||||
float groundHeight = m_physicsScene.TerrainManager.GetTerrainHeightAtXYZ(m_controllingPrim.RawPosition);
|
||||
|
||||
switch (m_controllingPrim.HoverType)
|
||||
{
|
||||
case PIDHoverType.Ground:
|
||||
ret = groundHeight + m_controllingPrim.HoverHeight;
|
||||
break;
|
||||
case PIDHoverType.GroundAndWater:
|
||||
float waterHeight = m_physicsScene.TerrainManager.GetWaterLevelAtXYZ(m_controllingPrim.RawPosition);
|
||||
if (groundHeight > waterHeight)
|
||||
{
|
||||
ret = groundHeight + m_controllingPrim.HoverHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = waterHeight + m_controllingPrim.HoverHeight;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -36,11 +36,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
{
|
||||
public class BSActorLockAxis : BSActor
|
||||
{
|
||||
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,158 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyrightD
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using OpenSim.Region.Physics.Manager;
|
||||
|
||||
using OMV = OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
public class BSActorMoveToTarget : BSActor
|
||||
{
|
||||
private BSVMotor m_targetMotor;
|
||||
|
||||
public BSActorMoveToTarget(BSScene physicsScene, BSPhysObject pObj, string actorName)
|
||||
: base(physicsScene, pObj, actorName)
|
||||
{
|
||||
m_targetMotor = null;
|
||||
m_physicsScene.DetailLog("{0},BSActorMoveToTarget,constructor", m_controllingPrim.LocalID);
|
||||
}
|
||||
|
||||
// BSActor.isActive
|
||||
public override bool isActive
|
||||
{
|
||||
get { return Enabled; }
|
||||
}
|
||||
|
||||
// Release any connections and resources used by the actor.
|
||||
// BSActor.Dispose()
|
||||
public override void Dispose()
|
||||
{
|
||||
Enabled = false;
|
||||
}
|
||||
|
||||
// Called when physical parameters (properties set in Bullet) need to be re-applied.
|
||||
// Called at taint-time.
|
||||
// BSActor.Refresh()
|
||||
public override void Refresh()
|
||||
{
|
||||
m_physicsScene.DetailLog("{0},BSActorMoveToTarget,refresh,enabled={1},active={2},target={3},tau={4}",
|
||||
m_controllingPrim.LocalID, Enabled, m_controllingPrim.MoveToTargetActive,
|
||||
m_controllingPrim.MoveToTargetTarget, m_controllingPrim.MoveToTargetTau );
|
||||
|
||||
// If not active any more...
|
||||
if (!m_controllingPrim.MoveToTargetActive)
|
||||
{
|
||||
Enabled = false;
|
||||
}
|
||||
|
||||
if (isActive)
|
||||
{
|
||||
ActivateMoveToTarget();
|
||||
}
|
||||
else
|
||||
{
|
||||
DeactivateMoveToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
// The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
|
||||
// Register a prestep action to restore physical requirements before the next simulation step.
|
||||
// Called at taint-time.
|
||||
// BSActor.RemoveBodyDependencies()
|
||||
public override void RemoveBodyDependencies()
|
||||
{
|
||||
// Nothing to do for the moveToTarget since it is all software at pre-step action time.
|
||||
}
|
||||
|
||||
// If a hover motor has not been created, create one and start the hovering.
|
||||
private void ActivateMoveToTarget()
|
||||
{
|
||||
if (m_targetMotor == null)
|
||||
{
|
||||
// We're taking over after this.
|
||||
m_controllingPrim.ZeroMotion(true);
|
||||
|
||||
m_targetMotor = new BSVMotor("BSActorMoveToTargget.Activate",
|
||||
m_controllingPrim.MoveToTargetTau, // timeScale
|
||||
BSMotor.Infinite, // decay time scale
|
||||
BSMotor.InfiniteVector, // friction timescale
|
||||
1f // efficiency
|
||||
);
|
||||
m_targetMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG so motor will output detail log messages.
|
||||
m_targetMotor.SetTarget(m_controllingPrim.MoveToTargetTarget);
|
||||
m_targetMotor.SetCurrent(m_controllingPrim.RawPosition);
|
||||
|
||||
m_physicsScene.BeforeStep += Mover;
|
||||
}
|
||||
}
|
||||
|
||||
private void DeactivateMoveToTarget()
|
||||
{
|
||||
if (m_targetMotor != null)
|
||||
{
|
||||
m_physicsScene.BeforeStep -= Mover;
|
||||
m_targetMotor = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Called just before the simulation step. Update the vertical position for hoverness.
|
||||
private void Mover(float timeStep)
|
||||
{
|
||||
// Don't do hovering while the object is selected.
|
||||
if (!isActive)
|
||||
return;
|
||||
|
||||
OMV.Vector3 origPosition = m_controllingPrim.RawPosition; // DEBUG DEBUG (for printout below)
|
||||
|
||||
// 'movePosition' is where we'd like the prim to be at this moment.
|
||||
OMV.Vector3 movePosition = m_controllingPrim.RawPosition + m_targetMotor.Step(timeStep);
|
||||
|
||||
// If we are very close to our target, turn off the movement motor.
|
||||
if (m_targetMotor.ErrorIsZero())
|
||||
{
|
||||
m_physicsScene.DetailLog("{0},BSActorMoveToTarget.Mover,zeroMovement,movePos={1},pos={2},mass={3}",
|
||||
m_controllingPrim.LocalID, movePosition, m_controllingPrim.RawPosition, m_controllingPrim.Mass);
|
||||
m_controllingPrim.ForcePosition = m_targetMotor.TargetValue;
|
||||
// Setting the position does not cause the physics engine to generate a property update. Force it.
|
||||
m_physicsScene.PE.PushUpdate(m_controllingPrim.PhysBody);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_controllingPrim.ForcePosition = movePosition;
|
||||
// Setting the position does not cause the physics engine to generate a property update. Force it.
|
||||
m_physicsScene.PE.PushUpdate(m_controllingPrim.PhysBody);
|
||||
}
|
||||
m_physicsScene.DetailLog("{0},BSActorMoveToTarget.Mover,move,fromPos={1},movePos={2}", m_controllingPrim.LocalID, origPosition, movePosition);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyrightD
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using OpenSim.Region.Physics.Manager;
|
||||
|
||||
using OMV = OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
public class BSActorSetForce : BSActor
|
||||
{
|
||||
BSFMotor m_forceMotor;
|
||||
|
||||
public BSActorSetForce(BSScene physicsScene, BSPhysObject pObj, string actorName)
|
||||
: base(physicsScene, pObj, actorName)
|
||||
{
|
||||
m_forceMotor = null;
|
||||
m_physicsScene.DetailLog("{0},BSActorSetForce,constructor", m_controllingPrim.LocalID);
|
||||
}
|
||||
|
||||
// BSActor.isActive
|
||||
public override bool isActive
|
||||
{
|
||||
get { return Enabled && m_controllingPrim.IsPhysicallyActive; }
|
||||
}
|
||||
|
||||
// Release any connections and resources used by the actor.
|
||||
// BSActor.Dispose()
|
||||
public override void Dispose()
|
||||
{
|
||||
Enabled = false;
|
||||
}
|
||||
|
||||
// Called when physical parameters (properties set in Bullet) need to be re-applied.
|
||||
// Called at taint-time.
|
||||
// BSActor.Refresh()
|
||||
public override void Refresh()
|
||||
{
|
||||
m_physicsScene.DetailLog("{0},BSActorSetForce,refresh", m_controllingPrim.LocalID);
|
||||
|
||||
// If not active any more, get rid of me (shouldn't ever happen, but just to be safe)
|
||||
if (m_controllingPrim.RawForce == OMV.Vector3.Zero)
|
||||
{
|
||||
m_physicsScene.DetailLog("{0},BSActorSetForce,refresh,notSetForce,removing={1}", m_controllingPrim.LocalID, ActorName);
|
||||
Enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// If the object is physically active, add the hoverer prestep action
|
||||
if (isActive)
|
||||
{
|
||||
ActivateSetForce();
|
||||
}
|
||||
else
|
||||
{
|
||||
DeactivateSetForce();
|
||||
}
|
||||
}
|
||||
|
||||
// The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
|
||||
// Register a prestep action to restore physical requirements before the next simulation step.
|
||||
// Called at taint-time.
|
||||
// BSActor.RemoveBodyDependencies()
|
||||
public override void RemoveBodyDependencies()
|
||||
{
|
||||
// Nothing to do for the hoverer since it is all software at pre-step action time.
|
||||
}
|
||||
|
||||
// If a hover motor has not been created, create one and start the hovering.
|
||||
private void ActivateSetForce()
|
||||
{
|
||||
if (m_forceMotor == null)
|
||||
{
|
||||
// A fake motor that might be used someday
|
||||
m_forceMotor = new BSFMotor("setForce", 1f, 1f, 1f, 1f);
|
||||
|
||||
m_physicsScene.BeforeStep += Mover;
|
||||
}
|
||||
}
|
||||
|
||||
private void DeactivateSetForce()
|
||||
{
|
||||
if (m_forceMotor != null)
|
||||
{
|
||||
m_physicsScene.BeforeStep -= Mover;
|
||||
m_forceMotor = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Called just before the simulation step. Update the vertical position for hoverness.
|
||||
private void Mover(float timeStep)
|
||||
{
|
||||
// Don't do force while the object is selected.
|
||||
if (!isActive)
|
||||
return;
|
||||
|
||||
m_physicsScene.DetailLog("{0},BSActorSetForce,preStep,force={1}", m_controllingPrim.LocalID, m_controllingPrim.RawForce);
|
||||
if (m_controllingPrim.PhysBody.HasPhysicalBody)
|
||||
{
|
||||
m_physicsScene.PE.ApplyCentralForce(m_controllingPrim.PhysBody, m_controllingPrim.RawForce);
|
||||
m_controllingPrim.ActivateIfPhysical(false);
|
||||
}
|
||||
|
||||
// TODO:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyrightD
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using OpenSim.Region.Physics.Manager;
|
||||
|
||||
using OMV = OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
public class BSActorSetTorque : BSActor
|
||||
{
|
||||
BSFMotor m_torqueMotor;
|
||||
|
||||
public BSActorSetTorque(BSScene physicsScene, BSPhysObject pObj, string actorName)
|
||||
: base(physicsScene, pObj, actorName)
|
||||
{
|
||||
m_torqueMotor = null;
|
||||
m_physicsScene.DetailLog("{0},BSActorSetTorque,constructor", m_controllingPrim.LocalID);
|
||||
}
|
||||
|
||||
// BSActor.isActive
|
||||
public override bool isActive
|
||||
{
|
||||
get { return Enabled && m_controllingPrim.IsPhysicallyActive; }
|
||||
}
|
||||
|
||||
// Release any connections and resources used by the actor.
|
||||
// BSActor.Dispose()
|
||||
public override void Dispose()
|
||||
{
|
||||
Enabled = false;
|
||||
}
|
||||
|
||||
// Called when physical parameters (properties set in Bullet) need to be re-applied.
|
||||
// Called at taint-time.
|
||||
// BSActor.Refresh()
|
||||
public override void Refresh()
|
||||
{
|
||||
m_physicsScene.DetailLog("{0},BSActorSetTorque,refresh,torque={1}", m_controllingPrim.LocalID, m_controllingPrim.RawTorque);
|
||||
|
||||
// If not active any more, get rid of me (shouldn't ever happen, but just to be safe)
|
||||
if (m_controllingPrim.RawTorque == OMV.Vector3.Zero)
|
||||
{
|
||||
m_physicsScene.DetailLog("{0},BSActorSetTorque,refresh,notSetTorque,disabling={1}", m_controllingPrim.LocalID, ActorName);
|
||||
Enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// If the object is physically active, add the hoverer prestep action
|
||||
if (isActive)
|
||||
{
|
||||
ActivateSetTorque();
|
||||
}
|
||||
else
|
||||
{
|
||||
DeactivateSetTorque();
|
||||
}
|
||||
}
|
||||
|
||||
// The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
|
||||
// Register a prestep action to restore physical requirements before the next simulation step.
|
||||
// Called at taint-time.
|
||||
// BSActor.RemoveBodyDependencies()
|
||||
public override void RemoveBodyDependencies()
|
||||
{
|
||||
// Nothing to do for the hoverer since it is all software at pre-step action time.
|
||||
}
|
||||
|
||||
// If a hover motor has not been created, create one and start the hovering.
|
||||
private void ActivateSetTorque()
|
||||
{
|
||||
if (m_torqueMotor == null)
|
||||
{
|
||||
// A fake motor that might be used someday
|
||||
m_torqueMotor = new BSFMotor("setTorque", 1f, 1f, 1f, 1f);
|
||||
|
||||
m_physicsScene.BeforeStep += Mover;
|
||||
}
|
||||
}
|
||||
|
||||
private void DeactivateSetTorque()
|
||||
{
|
||||
if (m_torqueMotor != null)
|
||||
{
|
||||
m_physicsScene.BeforeStep -= Mover;
|
||||
m_torqueMotor = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Called just before the simulation step. Update the vertical position for hoverness.
|
||||
private void Mover(float timeStep)
|
||||
{
|
||||
// Don't do force while the object is selected.
|
||||
if (!isActive)
|
||||
return;
|
||||
|
||||
m_physicsScene.DetailLog("{0},BSActorSetTorque,preStep,force={1}", m_controllingPrim.LocalID, m_controllingPrim.RawTorque);
|
||||
if (m_controllingPrim.PhysBody.HasPhysicalBody)
|
||||
{
|
||||
m_controllingPrim.AddAngularForce(m_controllingPrim.RawTorque, false, true);
|
||||
m_controllingPrim.ActivateIfPhysical(false);
|
||||
}
|
||||
|
||||
// TODO:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -32,45 +32,72 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
{
|
||||
public class BSActorCollection
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1358,6 +1358,35 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
// If vertical attaction timescale is reasonable
|
||||
if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
|
||||
{
|
||||
//Another formula to try got from :
|
||||
//http://answers.unity3d.com/questions/10425/how-to-stabilize-angular-motion-alignment-of-hover.html
|
||||
|
||||
Vector3 VehicleUpAxis = Vector3.UnitZ * VehicleOrientation;
|
||||
|
||||
// Flipping what was originally a timescale into a speed variable and then multiplying it by 2
|
||||
// since only computing half the distance between the angles.
|
||||
float VerticalAttractionSpeed = (1 / m_verticalAttractionTimescale) * 2.0f;
|
||||
|
||||
// Make a prediction of where the up axis will be when this is applied rather then where it is now as
|
||||
// this makes for a smoother adjustment and less fighting between the various forces.
|
||||
Vector3 predictedUp = VehicleUpAxis * Quaternion.CreateFromAxisAngle(VehicleRotationalVelocity, 0f);
|
||||
|
||||
// This is only half the distance to the target so it will take 2 seconds to complete the turn.
|
||||
Vector3 torqueVector = Vector3.Cross(predictedUp, Vector3.UnitZ);
|
||||
|
||||
// Scale vector by our timescale since it is an acceleration it is r/s^2 or radians a timescale squared
|
||||
Vector3 vertContributionV = torqueVector * VerticalAttractionSpeed * VerticalAttractionSpeed;
|
||||
|
||||
VehicleRotationalVelocity += vertContributionV;
|
||||
|
||||
VDetailLog("{0}, MoveAngular,verticalAttraction,UpAxis={1},PredictedUp={2},torqueVector={3},contrib={4}",
|
||||
ControllingPrim.LocalID,
|
||||
VehicleUpAxis,
|
||||
predictedUp,
|
||||
torqueVector,
|
||||
vertContributionV);
|
||||
//=====================================================================
|
||||
/*
|
||||
// Possible solution derived from a discussion at:
|
||||
// http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no
|
||||
|
||||
|
@ -1392,6 +1421,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
differenceAngle,
|
||||
correctionRotation,
|
||||
vertContributionV);
|
||||
*/
|
||||
|
||||
// ===================================================================
|
||||
/*
|
||||
|
|
|
@ -86,6 +86,7 @@ public static class BSParam
|
|||
public static bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
|
||||
public static bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects
|
||||
public static bool ShouldRemoveZeroWidthTriangles { get; private set; }
|
||||
public static bool ShouldUseBulletHACD { get; set; }
|
||||
|
||||
public static float TerrainImplementation { get; private set; }
|
||||
public static int TerrainMeshMagnification { get; private set; }
|
||||
|
@ -149,6 +150,15 @@ public static class BSParam
|
|||
public static float CSHullVolumeConservationThresholdPercent { get; private set; }
|
||||
public static int CSHullMaxVertices { get; private set; }
|
||||
public static float CSHullMaxSkinWidth { get; private set; }
|
||||
public static float BHullMaxVerticesPerHull { get; private set; } // 100
|
||||
public static float BHullMinClusters { get; private set; } // 2
|
||||
public static float BHullCompacityWeight { get; private set; } // 0.1
|
||||
public static float BHullVolumeWeight { get; private set; } // 0.0
|
||||
public static float BHullConcavity { get; private set; } // 100
|
||||
public static bool BHullAddExtraDistPoints { get; private set; } // false
|
||||
public static bool BHullAddNeighboursDistPoints { get; private set; } // false
|
||||
public static bool BHullAddFacesPoints { get; private set; } // false
|
||||
public static bool BHullShouldAdjustCollisionMargin { get; private set; } // false
|
||||
|
||||
// Linkset implementation parameters
|
||||
public static float LinksetImplementation { get; private set; }
|
||||
|
@ -325,6 +335,10 @@ public static class BSParam
|
|||
true,
|
||||
(s) => { return ShouldRemoveZeroWidthTriangles; },
|
||||
(s,v) => { ShouldRemoveZeroWidthTriangles = v; } ),
|
||||
new ParameterDefn<bool>("ShouldUseBulletHACD", "If true, use the Bullet version of HACD",
|
||||
false,
|
||||
(s) => { return ShouldUseBulletHACD; },
|
||||
(s,v) => { ShouldUseBulletHACD = v; } ),
|
||||
|
||||
new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions",
|
||||
5,
|
||||
|
@ -663,10 +677,47 @@ public static class BSParam
|
|||
(s) => { return CSHullMaxVertices; },
|
||||
(s,v) => { CSHullMaxVertices = v; } ),
|
||||
new ParameterDefn<float>("CSHullMaxSkinWidth", "CS impl: skin width to apply to output hulls.",
|
||||
0,
|
||||
0f,
|
||||
(s) => { return CSHullMaxSkinWidth; },
|
||||
(s,v) => { CSHullMaxSkinWidth = v; } ),
|
||||
|
||||
new ParameterDefn<float>("BHullMaxVerticesPerHull", "Bullet impl: max number of vertices per created hull",
|
||||
100f,
|
||||
(s) => { return BHullMaxVerticesPerHull; },
|
||||
(s,v) => { BHullMaxVerticesPerHull = v; } ),
|
||||
new ParameterDefn<float>("BHullMinClusters", "Bullet impl: minimum number of hulls to create per mesh",
|
||||
2f,
|
||||
(s) => { return BHullMinClusters; },
|
||||
(s,v) => { BHullMinClusters = v; } ),
|
||||
new ParameterDefn<float>("BHullCompacityWeight", "Bullet impl: weight factor for how compact to make hulls",
|
||||
2f,
|
||||
(s) => { return BHullCompacityWeight; },
|
||||
(s,v) => { BHullCompacityWeight = v; } ),
|
||||
new ParameterDefn<float>("BHullVolumeWeight", "Bullet impl: weight factor for volume in created hull",
|
||||
0.1f,
|
||||
(s) => { return BHullVolumeWeight; },
|
||||
(s,v) => { BHullVolumeWeight = v; } ),
|
||||
new ParameterDefn<float>("BHullConcavity", "Bullet impl: weight factor for how convex a created hull can be",
|
||||
100f,
|
||||
(s) => { return BHullConcavity; },
|
||||
(s,v) => { BHullConcavity = v; } ),
|
||||
new ParameterDefn<bool>("BHullAddExtraDistPoints", "Bullet impl: whether to add extra vertices for long distance vectors",
|
||||
false,
|
||||
(s) => { return BHullAddExtraDistPoints; },
|
||||
(s,v) => { BHullAddExtraDistPoints = v; } ),
|
||||
new ParameterDefn<bool>("BHullAddNeighboursDistPoints", "Bullet impl: whether to add extra vertices between neighbor hulls",
|
||||
false,
|
||||
(s) => { return BHullAddNeighboursDistPoints; },
|
||||
(s,v) => { BHullAddNeighboursDistPoints = v; } ),
|
||||
new ParameterDefn<bool>("BHullAddFacesPoints", "Bullet impl: whether to add extra vertices to break up hull faces",
|
||||
false,
|
||||
(s) => { return BHullAddFacesPoints; },
|
||||
(s,v) => { BHullAddFacesPoints = v; } ),
|
||||
new ParameterDefn<bool>("BHullShouldAdjustCollisionMargin", "Bullet impl: whether to shrink resulting hulls to account for collision margin",
|
||||
false,
|
||||
(s) => { return BHullShouldAdjustCollisionMargin; },
|
||||
(s,v) => { BHullShouldAdjustCollisionMargin = v; } ),
|
||||
|
||||
new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
|
||||
(float)BSLinkset.LinksetImplementation.Compound,
|
||||
(s) => { return LinksetImplementation; },
|
||||
|
|
|
@ -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,51 @@ 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
|
||||
DetailLog("{0},BSPhysObject.EnableActor,enablingExistingActor,name={1},enable={2}", LocalID, actorName, enableActor);
|
||||
theActor.Enabled = enableActor;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The actor does not exist. If it should, create it.
|
||||
if (enableActor)
|
||||
{
|
||||
DetailLog("{0},BSPhysObject.EnableActor,creatingActor,name={1}", LocalID, actorName);
|
||||
theActor = creator();
|
||||
PhysicalActors.Add(actorName, theActor);
|
||||
theActor.Enabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
DetailLog("{0},BSPhysObject.EnableActor,notCreatingActorSinceNotEnabled,name={1}", LocalID, actorName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Collisions
|
||||
|
||||
|
@ -255,7 +332,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 +372,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 +503,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 +514,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);
|
||||
}
|
||||
|
|
|
@ -316,6 +316,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
|||
break;
|
||||
case "bulletxna":
|
||||
ret = new BSAPIXNA(engineName, this);
|
||||
BSParam.ShouldUseBulletHACD = false;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -722,7 +722,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
// Remove usage of the previous shape.
|
||||
DereferenceShape(prim.PhysShape, shapeCallback);
|
||||
|
||||
newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod);
|
||||
newShape = CreatePhysicalHull(prim, newHullKey, prim.BaseShape, prim.Size, lod);
|
||||
// It might not have been created if we're waiting for an asset.
|
||||
newShape = VerifyMeshCreated(newShape, prim);
|
||||
|
||||
|
@ -733,7 +733,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
}
|
||||
|
||||
List<ConvexResult> m_hulls;
|
||||
private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
|
||||
private BulletShape CreatePhysicalHull(BSPhysObject prim, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
|
||||
{
|
||||
|
||||
BulletShape newShape = new BulletShape();
|
||||
|
@ -747,115 +747,152 @@ public sealed class BSShapeCollection : IDisposable
|
|||
}
|
||||
else
|
||||
{
|
||||
// Build a new hull in the physical world.
|
||||
// Pass true for physicalness as this prevents the creation of bounding box which is not needed
|
||||
IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false, false, false);
|
||||
if (meshData != null)
|
||||
if (BSParam.ShouldUseBulletHACD)
|
||||
{
|
||||
|
||||
int[] indices = meshData.getIndexListAsInt();
|
||||
List<OMV.Vector3> vertices = meshData.getVertexList();
|
||||
|
||||
//format conversion from IMesh format to DecompDesc format
|
||||
List<int> convIndices = new List<int>();
|
||||
List<float3> convVertices = new List<float3>();
|
||||
for (int ii = 0; ii < indices.GetLength(0); ii++)
|
||||
DetailLog("{0},BSShapeCollection.CreatePhysicalHull,shouldUseBulletHACD,entry", prim.LocalID);
|
||||
MeshDesc meshDesc;
|
||||
if (!Meshes.TryGetValue(newHullKey, out meshDesc))
|
||||
{
|
||||
convIndices.Add(indices[ii]);
|
||||
}
|
||||
foreach (OMV.Vector3 vv in vertices)
|
||||
{
|
||||
convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
|
||||
}
|
||||
// That's odd because the mesh should have been created before the hull
|
||||
// but, since it doesn't exist, create it.
|
||||
newShape = CreatePhysicalMesh(prim, newHullKey, prim.BaseShape, prim.Size, lod);
|
||||
DetailLog("{0},BSShapeCollection.CreatePhysicalHull,noMeshBuiltNew,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
|
||||
|
||||
uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
|
||||
if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
|
||||
{
|
||||
// Simple primitive shapes we know are convex so they are better implemented with
|
||||
// fewer hulls.
|
||||
// Check for simple shape (prim without cuts) and reduce split parameter if so.
|
||||
if (PrimHasNoCuts(pbs))
|
||||
if (newShape.HasPhysicalShape)
|
||||
{
|
||||
maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
|
||||
ReferenceShape(newShape);
|
||||
Meshes.TryGetValue(newHullKey, out meshDesc);
|
||||
}
|
||||
}
|
||||
|
||||
// setup and do convex hull conversion
|
||||
m_hulls = new List<ConvexResult>();
|
||||
DecompDesc dcomp = new DecompDesc();
|
||||
dcomp.mIndices = convIndices;
|
||||
dcomp.mVertices = convVertices;
|
||||
dcomp.mDepth = maxDepthSplit;
|
||||
dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
|
||||
dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
|
||||
dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
|
||||
dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
|
||||
ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
|
||||
// create the hull into the _hulls variable
|
||||
convexBuilder.process(dcomp);
|
||||
|
||||
DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
|
||||
BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
|
||||
|
||||
// Convert the vertices and indices for passing to unmanaged.
|
||||
// The hull information is passed as a large floating point array.
|
||||
// The format is:
|
||||
// convHulls[0] = number of hulls
|
||||
// convHulls[1] = number of vertices in first hull
|
||||
// convHulls[2] = hull centroid X coordinate
|
||||
// convHulls[3] = hull centroid Y coordinate
|
||||
// convHulls[4] = hull centroid Z coordinate
|
||||
// convHulls[5] = first hull vertex X
|
||||
// convHulls[6] = first hull vertex Y
|
||||
// convHulls[7] = first hull vertex Z
|
||||
// convHulls[8] = second hull vertex X
|
||||
// ...
|
||||
// convHulls[n] = number of vertices in second hull
|
||||
// convHulls[n+1] = second hull centroid X coordinate
|
||||
// ...
|
||||
//
|
||||
// TODO: is is very inefficient. Someday change the convex hull generator to return
|
||||
// data structures that do not need to be converted in order to pass to Bullet.
|
||||
// And maybe put the values directly into pinned memory rather than marshaling.
|
||||
int hullCount = m_hulls.Count;
|
||||
int totalVertices = 1; // include one for the count of the hulls
|
||||
foreach (ConvexResult cr in m_hulls)
|
||||
if (meshDesc.shape.HasPhysicalShape)
|
||||
{
|
||||
totalVertices += 4; // add four for the vertex count and centroid
|
||||
totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
|
||||
}
|
||||
float[] convHulls = new float[totalVertices];
|
||||
HACDParams parms;
|
||||
parms.maxVerticesPerHull = BSParam.BHullMaxVerticesPerHull;
|
||||
parms.minClusters = BSParam.BHullMinClusters;
|
||||
parms.compacityWeight = BSParam.BHullCompacityWeight;
|
||||
parms.volumeWeight = BSParam.BHullVolumeWeight;
|
||||
parms.concavity = BSParam.BHullConcavity;
|
||||
parms.addExtraDistPoints = BSParam.NumericBool(BSParam.BHullAddExtraDistPoints);
|
||||
parms.addNeighboursDistPoints = BSParam.NumericBool(BSParam.BHullAddNeighboursDistPoints);
|
||||
parms.addFacesPoints = BSParam.NumericBool(BSParam.BHullAddFacesPoints);
|
||||
parms.shouldAdjustCollisionMargin = BSParam.NumericBool(BSParam.BHullShouldAdjustCollisionMargin);
|
||||
|
||||
convHulls[0] = (float)hullCount;
|
||||
int jj = 1;
|
||||
foreach (ConvexResult cr in m_hulls)
|
||||
{
|
||||
// copy vertices for index access
|
||||
float3[] verts = new float3[cr.HullVertices.Count];
|
||||
int kk = 0;
|
||||
foreach (float3 ff in cr.HullVertices)
|
||||
{
|
||||
verts[kk++] = ff;
|
||||
}
|
||||
|
||||
// add to the array one hull's worth of data
|
||||
convHulls[jj++] = cr.HullIndices.Count;
|
||||
convHulls[jj++] = 0f; // centroid x,y,z
|
||||
convHulls[jj++] = 0f;
|
||||
convHulls[jj++] = 0f;
|
||||
foreach (int ind in cr.HullIndices)
|
||||
{
|
||||
convHulls[jj++] = verts[ind].x;
|
||||
convHulls[jj++] = verts[ind].y;
|
||||
convHulls[jj++] = verts[ind].z;
|
||||
}
|
||||
DetailLog("{0},BSShapeCollection.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
|
||||
newShape = PhysicsScene.PE.BuildHullShapeFromMesh(PhysicsScene.World, meshDesc.shape, parms);
|
||||
DetailLog("{0},BSShapeCollection.CreatePhysicalHull,hullFromMesh,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
|
||||
}
|
||||
// create the hull data structure in Bullet
|
||||
newShape = PhysicsScene.PE.CreateHullShape(PhysicsScene.World, hullCount, convHulls);
|
||||
DetailLog("{0},BSShapeCollection.CreatePhysicalHull,shouldUseBulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
|
||||
}
|
||||
}
|
||||
if (!newShape.HasPhysicalShape)
|
||||
{
|
||||
// Build a new hull in the physical world.
|
||||
// Pass true for physicalness as this prevents the creation of bounding box which is not needed
|
||||
IMesh meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */, false, false);
|
||||
if (meshData != null)
|
||||
{
|
||||
int[] indices = meshData.getIndexListAsInt();
|
||||
List<OMV.Vector3> vertices = meshData.getVertexList();
|
||||
|
||||
newShape.shapeKey = newHullKey;
|
||||
//format conversion from IMesh format to DecompDesc format
|
||||
List<int> convIndices = new List<int>();
|
||||
List<float3> convVertices = new List<float3>();
|
||||
for (int ii = 0; ii < indices.GetLength(0); ii++)
|
||||
{
|
||||
convIndices.Add(indices[ii]);
|
||||
}
|
||||
foreach (OMV.Vector3 vv in vertices)
|
||||
{
|
||||
convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
|
||||
}
|
||||
|
||||
uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
|
||||
if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
|
||||
{
|
||||
// Simple primitive shapes we know are convex so they are better implemented with
|
||||
// fewer hulls.
|
||||
// Check for simple shape (prim without cuts) and reduce split parameter if so.
|
||||
if (PrimHasNoCuts(pbs))
|
||||
{
|
||||
maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
|
||||
}
|
||||
}
|
||||
|
||||
// setup and do convex hull conversion
|
||||
m_hulls = new List<ConvexResult>();
|
||||
DecompDesc dcomp = new DecompDesc();
|
||||
dcomp.mIndices = convIndices;
|
||||
dcomp.mVertices = convVertices;
|
||||
dcomp.mDepth = maxDepthSplit;
|
||||
dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
|
||||
dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
|
||||
dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
|
||||
dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
|
||||
ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
|
||||
// create the hull into the _hulls variable
|
||||
convexBuilder.process(dcomp);
|
||||
|
||||
DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
|
||||
BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
|
||||
|
||||
// Convert the vertices and indices for passing to unmanaged.
|
||||
// The hull information is passed as a large floating point array.
|
||||
// The format is:
|
||||
// convHulls[0] = number of hulls
|
||||
// convHulls[1] = number of vertices in first hull
|
||||
// convHulls[2] = hull centroid X coordinate
|
||||
// convHulls[3] = hull centroid Y coordinate
|
||||
// convHulls[4] = hull centroid Z coordinate
|
||||
// convHulls[5] = first hull vertex X
|
||||
// convHulls[6] = first hull vertex Y
|
||||
// convHulls[7] = first hull vertex Z
|
||||
// convHulls[8] = second hull vertex X
|
||||
// ...
|
||||
// convHulls[n] = number of vertices in second hull
|
||||
// convHulls[n+1] = second hull centroid X coordinate
|
||||
// ...
|
||||
//
|
||||
// TODO: is is very inefficient. Someday change the convex hull generator to return
|
||||
// data structures that do not need to be converted in order to pass to Bullet.
|
||||
// And maybe put the values directly into pinned memory rather than marshaling.
|
||||
int hullCount = m_hulls.Count;
|
||||
int totalVertices = 1; // include one for the count of the hulls
|
||||
foreach (ConvexResult cr in m_hulls)
|
||||
{
|
||||
totalVertices += 4; // add four for the vertex count and centroid
|
||||
totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
|
||||
}
|
||||
float[] convHulls = new float[totalVertices];
|
||||
|
||||
convHulls[0] = (float)hullCount;
|
||||
int jj = 1;
|
||||
foreach (ConvexResult cr in m_hulls)
|
||||
{
|
||||
// copy vertices for index access
|
||||
float3[] verts = new float3[cr.HullVertices.Count];
|
||||
int kk = 0;
|
||||
foreach (float3 ff in cr.HullVertices)
|
||||
{
|
||||
verts[kk++] = ff;
|
||||
}
|
||||
|
||||
// add to the array one hull's worth of data
|
||||
convHulls[jj++] = cr.HullIndices.Count;
|
||||
convHulls[jj++] = 0f; // centroid x,y,z
|
||||
convHulls[jj++] = 0f;
|
||||
convHulls[jj++] = 0f;
|
||||
foreach (int ind in cr.HullIndices)
|
||||
{
|
||||
convHulls[jj++] = verts[ind].x;
|
||||
convHulls[jj++] = verts[ind].y;
|
||||
convHulls[jj++] = verts[ind].z;
|
||||
}
|
||||
}
|
||||
// create the hull data structure in Bullet
|
||||
newShape = PhysicsScene.PE.CreateHullShape(PhysicsScene.World, hullCount, convHulls);
|
||||
}
|
||||
}
|
||||
newShape.shapeKey = newHullKey;
|
||||
}
|
||||
|
||||
return newShape;
|
||||
}
|
||||
|
|
|
@ -213,13 +213,13 @@ public sealed class BSTerrainManager : IDisposable
|
|||
});
|
||||
}
|
||||
|
||||
// Another region is calling this region passing a terrain.
|
||||
// Another region is calling this region and passing a terrain.
|
||||
// A region that is not the mega-region root will pass its terrain to the root region so the root region
|
||||
// physics engine will have all the terrains.
|
||||
private void AddMegaRegionChildTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
|
||||
{
|
||||
// Since we are called by another region's thread, the action must be rescheduled onto our processing thread.
|
||||
PhysicsScene.PostTaintObject("TerrainManager.AddMegaRegionChild" + m_worldOffset.ToString(), 0, delegate()
|
||||
PhysicsScene.PostTaintObject("TerrainManager.AddMegaRegionChild" + minCoords.ToString(), id, delegate()
|
||||
{
|
||||
UpdateTerrain(id, heightMap, minCoords, maxCoords);
|
||||
});
|
||||
|
@ -306,7 +306,7 @@ public sealed class BSTerrainManager : IDisposable
|
|||
newTerrainID = ++m_terrainCount;
|
||||
|
||||
DetailLog("{0},BSTerrainManager.UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}",
|
||||
BSScene.DetailLogZero, newTerrainID, minCoords, minCoords);
|
||||
BSScene.DetailLogZero, newTerrainID, minCoords, maxCoords);
|
||||
BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
|
||||
m_terrains.Add(terrainRegionBase, newTerrainPhys);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
|
@ -34,10 +36,10 @@ using OpenSim.Region.CoreModules.World.Land;
|
|||
|
||||
namespace OpenSim.Region.RegionCombinerModule
|
||||
{
|
||||
public class RegionCombinerLargeLandChannel : ILandChannel
|
||||
public class RegionCombinerLargeLandChannel : ILandChannel
|
||||
{
|
||||
// private static readonly ILog m_log =
|
||||
// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private RegionData RegData;
|
||||
private ILandChannel RootRegionLandChannel;
|
||||
private readonly List<RegionData> RegionConnections;
|
||||
|
@ -75,40 +77,51 @@ public class RegionCombinerLargeLandChannel : ILandChannel
|
|||
|
||||
public ILandObject GetLandObject(int x, int y)
|
||||
{
|
||||
//m_log.DebugFormat("[BIGLANDTESTINT]: <{0},{1}>", x, y);
|
||||
return GetLandObject((float)x, (float)y);
|
||||
|
||||
if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize)
|
||||
{
|
||||
return RootRegionLandChannel.GetLandObject(x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
int offsetX = (x / (int)Constants.RegionSize);
|
||||
int offsetY = (y / (int)Constants.RegionSize);
|
||||
offsetX *= (int)Constants.RegionSize;
|
||||
offsetY *= (int)Constants.RegionSize;
|
||||
|
||||
foreach (RegionData regionData in RegionConnections)
|
||||
{
|
||||
if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY)
|
||||
{
|
||||
return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY);
|
||||
}
|
||||
}
|
||||
ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene);
|
||||
obj.LandData.Name = "NO LAND";
|
||||
return obj;
|
||||
}
|
||||
// m_log.DebugFormat("[BIGLANDTESTINT]: <{0},{1}>", x, y);
|
||||
//
|
||||
// if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize)
|
||||
// {
|
||||
// return RootRegionLandChannel.GetLandObject(x, y);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// int offsetX = (x / (int)Constants.RegionSize);
|
||||
// int offsetY = (y / (int)Constants.RegionSize);
|
||||
// offsetX *= (int)Constants.RegionSize;
|
||||
// offsetY *= (int)Constants.RegionSize;
|
||||
//
|
||||
// foreach (RegionData regionData in RegionConnections)
|
||||
// {
|
||||
// if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY)
|
||||
// {
|
||||
// m_log.DebugFormat(
|
||||
// "[REGION COMBINER LARGE LAND CHANNEL]: Found region {0} at offset {1},{2}",
|
||||
// regionData.RegionScene.Name, offsetX, offsetY);
|
||||
//
|
||||
// return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY);
|
||||
// }
|
||||
// }
|
||||
// //ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene);
|
||||
// //obj.LandData.Name = "NO LAND";
|
||||
// //return obj;
|
||||
// }
|
||||
//
|
||||
// m_log.DebugFormat("[REGION COMBINER LARGE LAND CHANNEL]: No region found at {0},{1}, returning null", x, y);
|
||||
//
|
||||
// return null;
|
||||
}
|
||||
|
||||
public ILandObject GetLandObject(int localID)
|
||||
{
|
||||
// XXX: Possibly should be looking in every land channel, not just the root.
|
||||
return RootRegionLandChannel.GetLandObject(localID);
|
||||
}
|
||||
|
||||
public ILandObject GetLandObject(float x, float y)
|
||||
{
|
||||
//m_log.DebugFormat("[BIGLANDTESTFLOAT]: <{0},{1}>", x, y);
|
||||
// m_log.DebugFormat("[BIGLANDTESTFLOAT]: <{0},{1}>", x, y);
|
||||
|
||||
if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize)
|
||||
{
|
||||
|
@ -125,14 +138,22 @@ public class RegionCombinerLargeLandChannel : ILandChannel
|
|||
{
|
||||
if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[REGION COMBINER LARGE LAND CHANNEL]: Found region {0} at offset {1},{2}",
|
||||
// regionData.RegionScene.Name, offsetX, offsetY);
|
||||
|
||||
return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY);
|
||||
}
|
||||
}
|
||||
|
||||
ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene);
|
||||
obj.LandData.Name = "NO LAND";
|
||||
return obj;
|
||||
// ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene);
|
||||
// obj.LandData.Name = "NO LAND";
|
||||
// return obj;
|
||||
}
|
||||
|
||||
// m_log.DebugFormat("[REGION COMBINER LARGE LAND CHANNEL]: No region found at {0},{1}, returning null", x, y);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsForcefulBansAllowed()
|
||||
|
|
|
@ -528,8 +528,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
|||
{
|
||||
File.Delete(savedState);
|
||||
}
|
||||
catch(Exception)
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Warn(
|
||||
string.Format(
|
||||
"[SCRIPT INSTANCE]: Could not delete script state {0} for script {1} (id {2}) in part {3} (id {4}) in object {5} in {6}. Exception ",
|
||||
ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name),
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -137,10 +137,11 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
|||
userID, sessionID, secureSessionID);
|
||||
|
||||
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;
|
||||
|
|
|
@ -43,9 +43,14 @@
|
|||
; Sets the method that OpenSim will use to fire asynchronous
|
||||
; events. Valid values are UnsafeQueueUserWorkItem,
|
||||
; QueueUserWorkItem, BeginInvoke, SmartThreadPool, and Thread.
|
||||
;
|
||||
; SmartThreadPool is reported to work well on Mono/Linux, but
|
||||
; UnsafeQueueUserWorkItem has been benchmarked with better
|
||||
; performance on .NET/Windows
|
||||
;
|
||||
; UnsafeQueueUserWorkItem refers to the fact that the code creating the event could elevate its security
|
||||
; privileges. However, as calling code is trusted anyway this is safe (if you set
|
||||
; TrustedBinaries = true in the [XEngine] section then you already have to trust that incoming code for other reasons).
|
||||
async_call_method = SmartThreadPool
|
||||
|
||||
; Max threads to allocate on the FireAndForget thread pool
|
||||
|
|
|
@ -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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue