Adding BulletSim module
parent
b0173de7ec
commit
05dbf31567
addon-modules/BulletSPlugin
|
@ -0,0 +1,413 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011 Intel Corporation
|
||||||
|
*
|
||||||
|
* 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 copyright
|
||||||
|
* 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 Intel Corporation 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.Reflection;
|
||||||
|
using log4net;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
|
{
|
||||||
|
public class BSCharacter : PhysicsActor
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
private static readonly string LogHeader = "[BULLETS CHAR]";
|
||||||
|
|
||||||
|
private BSScene _scene;
|
||||||
|
private String _avName;
|
||||||
|
private bool _stopped;
|
||||||
|
private Vector3 _size;
|
||||||
|
private Vector3 _scale;
|
||||||
|
private PrimitiveBaseShape _pbs;
|
||||||
|
private uint _localID = 0;
|
||||||
|
private bool _grabbed;
|
||||||
|
private bool _selected;
|
||||||
|
private Vector3 _position;
|
||||||
|
private float _mass = 80f;
|
||||||
|
public float _density = 60f;
|
||||||
|
public float CAPSULE_RADIUS = 0.37f;
|
||||||
|
public float CAPSULE_LENGTH = 2.140599f;
|
||||||
|
private Vector3 _force;
|
||||||
|
private Vector3 _velocity;
|
||||||
|
private Vector3 _torque;
|
||||||
|
private float _collisionScore;
|
||||||
|
private Vector3 _acceleration;
|
||||||
|
private Quaternion _orientation;
|
||||||
|
private int _physicsActorType;
|
||||||
|
private bool _isPhysical;
|
||||||
|
private bool _flying;
|
||||||
|
private bool _setAlwaysRun;
|
||||||
|
private bool _throttleUpdates;
|
||||||
|
private bool _isColliding;
|
||||||
|
private long _collidingStep;
|
||||||
|
private bool _collidingGround;
|
||||||
|
private long _collidingGroundStep;
|
||||||
|
private bool _collidingObj;
|
||||||
|
private bool _floatOnWater;
|
||||||
|
private Vector3 _rotationalVelocity;
|
||||||
|
private bool _kinematic;
|
||||||
|
private float _buoyancy;
|
||||||
|
|
||||||
|
private int _subscribedEventsMs = 0;
|
||||||
|
|
||||||
|
private 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, Vector3 pos, Vector3 size, bool isFlying)
|
||||||
|
{
|
||||||
|
_localID = localID;
|
||||||
|
_avName = avName;
|
||||||
|
_scene = parent_scene;
|
||||||
|
_position = pos;
|
||||||
|
_size = size;
|
||||||
|
_orientation = Quaternion.Identity;
|
||||||
|
_velocity = Vector3.Zero;
|
||||||
|
_scale = new Vector3(1f, 1f, 1f);
|
||||||
|
float AVvolume = (float) (Math.PI*Math.Pow(CAPSULE_RADIUS, 2)*CAPSULE_LENGTH);
|
||||||
|
_mass = _density*AVvolume;
|
||||||
|
|
||||||
|
ShapeData shapeData = new ShapeData();
|
||||||
|
shapeData.ID = _localID;
|
||||||
|
shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR;
|
||||||
|
shapeData.Position = _position;
|
||||||
|
shapeData.Rotation = _orientation;
|
||||||
|
shapeData.Velocity = _velocity;
|
||||||
|
shapeData.Scale = _scale;
|
||||||
|
shapeData.Mass = _mass;
|
||||||
|
shapeData.Flying = isFlying ? ShapeData.numericTrue : ShapeData.numericFalse;
|
||||||
|
shapeData.Dynamic = ShapeData.numericFalse;
|
||||||
|
|
||||||
|
BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// called when this character is being destroyed and the resources should be released
|
||||||
|
public void Destroy()
|
||||||
|
{
|
||||||
|
_scene.TaintedObject(delegate()
|
||||||
|
{
|
||||||
|
BulletSimAPI.DestroyObject(_scene.WorldID, _localID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void RequestPhysicsterseUpdate()
|
||||||
|
{
|
||||||
|
base.RequestPhysicsterseUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Stopped {
|
||||||
|
get { return _stopped; }
|
||||||
|
}
|
||||||
|
public override Vector3 Size {
|
||||||
|
get { return _size; }
|
||||||
|
set { _size = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override PrimitiveBaseShape Shape {
|
||||||
|
set { _pbs = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override uint LocalID {
|
||||||
|
set { _localID = value;
|
||||||
|
}
|
||||||
|
get { return _localID; }
|
||||||
|
}
|
||||||
|
public override bool Grabbed {
|
||||||
|
set { _grabbed = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override bool Selected {
|
||||||
|
set { _selected = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override void CrossingFailure() { return; }
|
||||||
|
public override void link(PhysicsActor obj) { return; }
|
||||||
|
public override void delink() { return; }
|
||||||
|
public override void LockAngularMotion(Vector3 axis) { return; }
|
||||||
|
|
||||||
|
public override Vector3 Position {
|
||||||
|
get {
|
||||||
|
_position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
|
||||||
|
return _position;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
_position = value;
|
||||||
|
_scene.TaintedObject(delegate()
|
||||||
|
{
|
||||||
|
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override float Mass {
|
||||||
|
get {
|
||||||
|
return _mass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override Vector3 Force {
|
||||||
|
get { return _force; }
|
||||||
|
set {
|
||||||
|
_force = value;
|
||||||
|
m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
|
||||||
|
_scene.TaintedObject(delegate()
|
||||||
|
{
|
||||||
|
BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int VehicleType {
|
||||||
|
get { return 0; }
|
||||||
|
set { return; }
|
||||||
|
}
|
||||||
|
public override void VehicleFloatParam(int param, float value) { }
|
||||||
|
public override void VehicleVectorParam(int param, Vector3 value) {}
|
||||||
|
public override void VehicleRotationParam(int param, Quaternion rotation) { }
|
||||||
|
public override void VehicleFlags(int param, bool remove) { }
|
||||||
|
|
||||||
|
// Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
|
||||||
|
public override void SetVolumeDetect(int param) { return; }
|
||||||
|
|
||||||
|
public override Vector3 GeometricCenter { get { return Vector3.Zero; } }
|
||||||
|
public override Vector3 CenterOfMass { get { return Vector3.Zero; } }
|
||||||
|
public override Vector3 Velocity {
|
||||||
|
get { return _velocity; }
|
||||||
|
set {
|
||||||
|
_velocity = value;
|
||||||
|
_scene.TaintedObject(delegate()
|
||||||
|
{
|
||||||
|
BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override Vector3 Torque {
|
||||||
|
get { return _torque; }
|
||||||
|
set { _torque = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override float CollisionScore {
|
||||||
|
get { return _collisionScore; }
|
||||||
|
set { _collisionScore = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override Vector3 Acceleration {
|
||||||
|
get { return _acceleration; }
|
||||||
|
}
|
||||||
|
public override Quaternion Orientation {
|
||||||
|
get { return _orientation; }
|
||||||
|
set {
|
||||||
|
_orientation = value;
|
||||||
|
_scene.TaintedObject(delegate()
|
||||||
|
{
|
||||||
|
_position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
|
||||||
|
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override int PhysicsActorType {
|
||||||
|
get { return _physicsActorType; }
|
||||||
|
set { _physicsActorType = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override bool IsPhysical {
|
||||||
|
get { return _isPhysical; }
|
||||||
|
set { _isPhysical = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override bool Flying {
|
||||||
|
get { return _flying; }
|
||||||
|
set {
|
||||||
|
_flying = value;
|
||||||
|
_scene.TaintedObject(delegate()
|
||||||
|
{
|
||||||
|
BulletSimAPI.SetObjectFlying(_scene.WorldID, LocalID, _flying);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override bool
|
||||||
|
SetAlwaysRun {
|
||||||
|
get { return _setAlwaysRun; }
|
||||||
|
set { _setAlwaysRun = value; }
|
||||||
|
}
|
||||||
|
public override bool ThrottleUpdates {
|
||||||
|
get { return _throttleUpdates; }
|
||||||
|
set { _throttleUpdates = value; }
|
||||||
|
}
|
||||||
|
public override bool IsColliding {
|
||||||
|
get { return (_collidingStep == _scene.SimulationStep); }
|
||||||
|
set { _isColliding = value; }
|
||||||
|
}
|
||||||
|
public override bool CollidingGround {
|
||||||
|
get { return (_collidingGroundStep == _scene.SimulationStep); }
|
||||||
|
set { _collidingGround = value; }
|
||||||
|
}
|
||||||
|
public override bool CollidingObj {
|
||||||
|
get { return _collidingObj; }
|
||||||
|
set { _collidingObj = value; }
|
||||||
|
}
|
||||||
|
public override bool FloatOnWater {
|
||||||
|
set { _floatOnWater = value; }
|
||||||
|
}
|
||||||
|
public override Vector3 RotationalVelocity {
|
||||||
|
get { return _rotationalVelocity; }
|
||||||
|
set { _rotationalVelocity = value; }
|
||||||
|
}
|
||||||
|
public override bool Kinematic {
|
||||||
|
get { return _kinematic; }
|
||||||
|
set { _kinematic = value; }
|
||||||
|
}
|
||||||
|
public override float Buoyancy {
|
||||||
|
get { return _buoyancy; }
|
||||||
|
set { _buoyancy = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used for MoveTo
|
||||||
|
public override Vector3 PIDTarget {
|
||||||
|
set { _PIDTarget = value; }
|
||||||
|
}
|
||||||
|
public override bool PIDActive {
|
||||||
|
set { _usePID = value; }
|
||||||
|
}
|
||||||
|
public override float PIDTau {
|
||||||
|
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 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(Vector3 force, bool pushforce) {
|
||||||
|
if (force.IsFinite())
|
||||||
|
{
|
||||||
|
_force.X += force.X;
|
||||||
|
_force.Y += force.Y;
|
||||||
|
_force.Z += force.Z;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader);
|
||||||
|
}
|
||||||
|
_scene.TaintedObject(delegate()
|
||||||
|
{
|
||||||
|
BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
|
||||||
|
});
|
||||||
|
//m_lastUpdateSent = false;
|
||||||
|
}
|
||||||
|
public override void AddAngularForce(Vector3 force, bool pushforce) {
|
||||||
|
}
|
||||||
|
public override void SetMomentum(Vector3 momentum) {
|
||||||
|
}
|
||||||
|
public override void SubscribeEvents(int ms) {
|
||||||
|
_subscribedEventsMs = ms;
|
||||||
|
}
|
||||||
|
public override void UnSubscribeEvents() {
|
||||||
|
_subscribedEventsMs = 0;
|
||||||
|
}
|
||||||
|
public override bool SubscribedEvents() {
|
||||||
|
return (_subscribedEventsMs > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The physics engine says that properties have updated. Update same and inform
|
||||||
|
// the world that things have changed.
|
||||||
|
public void UpdateProperties(EntityProperties entprop)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
// we assign to the local variables so the normal set action does not happen
|
||||||
|
if (_position != entprop.Position)
|
||||||
|
{
|
||||||
|
_position = entprop.Position;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (_orientation != entprop.Rotation)
|
||||||
|
{
|
||||||
|
_orientation = entprop.Rotation;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (_velocity != entprop.Velocity)
|
||||||
|
{
|
||||||
|
_velocity = entprop.Velocity;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (_acceleration != entprop.Acceleration)
|
||||||
|
{
|
||||||
|
_acceleration = entprop.Acceleration;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (_rotationalVelocity != entprop.AngularVelocity)
|
||||||
|
{
|
||||||
|
_rotationalVelocity = entprop.AngularVelocity;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (changed)
|
||||||
|
{
|
||||||
|
base.RequestPhysicsterseUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
|
||||||
|
if (_subscribedEventsMs == 0) return; // don't want collisions
|
||||||
|
|
||||||
|
// The following says we're colliding this simulation step
|
||||||
|
_collidingStep = _scene.SimulationStep;
|
||||||
|
if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID)
|
||||||
|
{
|
||||||
|
_collidingGroundStep = _scene.SimulationStep;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<uint, ContactPoint> contactPoints = new Dictionary<uint, ContactPoint>();
|
||||||
|
contactPoints.Add(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
|
||||||
|
CollisionEventUpdate args = new CollisionEventUpdate(LocalID, (int)type, 1, contactPoints);
|
||||||
|
base.SendCollisionUpdate(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Intel Corporation
|
||||||
|
*
|
||||||
|
* 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 copyright
|
||||||
|
* 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 Intel Corporation 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 OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
|
{
|
||||||
|
public class BSPlugin : IPhysicsPlugin
|
||||||
|
{
|
||||||
|
//private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private BSScene _mScene;
|
||||||
|
|
||||||
|
public BSPlugin()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Init()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PhysicsScene GetScene(String sceneIdentifier)
|
||||||
|
{
|
||||||
|
if (_mScene == null)
|
||||||
|
{
|
||||||
|
_mScene = new BSScene(sceneIdentifier);
|
||||||
|
}
|
||||||
|
return (_mScene);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetName()
|
||||||
|
{
|
||||||
|
return ("BulletSim");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,471 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011 Intel Corporation
|
||||||
|
*
|
||||||
|
* 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 copyright
|
||||||
|
* 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 Intel Corporation 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.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using Nini.Config;
|
||||||
|
using log4net;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Region.Framework;
|
||||||
|
|
||||||
|
// TODOs for BulletSim (both BSScene and BSPrim)
|
||||||
|
// Does NeedsMeshing() really need to exclude all the different shapes?
|
||||||
|
// Based on material, set density and friction
|
||||||
|
// More efficient memory usage in passing hull information from BSPrim to BulletSim
|
||||||
|
// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly?
|
||||||
|
// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions)
|
||||||
|
// Need three states for objects: sense and report collisions, have physical effects, affects other objects
|
||||||
|
// LinkSets
|
||||||
|
// Freeing of memory of linksets in BulletSim::DestroyObject
|
||||||
|
// Should prim.link() and prim.delink() be done at taint time?
|
||||||
|
// Pass collision enable flags to BulletSim code so collisions are not reported up unless they are really needed
|
||||||
|
// Set child prims phantom since the physicality is handled by the parent prim
|
||||||
|
// Linked children need rotation relative to parent (passed as world rotation)
|
||||||
|
//
|
||||||
|
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
|
{
|
||||||
|
public class BSScene : PhysicsScene
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
private static readonly string LogHeader = "[BULLETS SCENE]";
|
||||||
|
|
||||||
|
private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>();
|
||||||
|
private Dictionary<uint, BSPrim> m_prims = new Dictionary<uint, BSPrim>();
|
||||||
|
private float[] m_heightMap;
|
||||||
|
private uint m_worldID;
|
||||||
|
public uint WorldID { get { return m_worldID; } }
|
||||||
|
|
||||||
|
public IMesher mesher;
|
||||||
|
public int meshLOD = 32;
|
||||||
|
|
||||||
|
private int m_maxSubSteps = 10;
|
||||||
|
private float m_fixedTimeStep = 1f / 60f;
|
||||||
|
private long m_simulationStep = 0;
|
||||||
|
public long SimulationStep { get { return m_simulationStep; } }
|
||||||
|
|
||||||
|
private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed
|
||||||
|
private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes
|
||||||
|
public float maximumMassObject = 10000.01f;
|
||||||
|
|
||||||
|
public const uint TERRAIN_ID = 0;
|
||||||
|
public const uint GROUNDPLANE_ID = 1;
|
||||||
|
|
||||||
|
public float DefaultFriction = 0.70f;
|
||||||
|
public float DefaultDensity = 10.000006836f; // Aluminum g/cm3; TODO: compute based on object material
|
||||||
|
|
||||||
|
public delegate void TaintCallback();
|
||||||
|
private List<TaintCallback> _taintedObjects;
|
||||||
|
|
||||||
|
private BulletSimAPI.DebugLogCallback debugLogCallbackHandle;
|
||||||
|
|
||||||
|
public BSScene(string identifier)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Initialise(IMesher meshmerizer, IConfigSource config)
|
||||||
|
{
|
||||||
|
if (config != null)
|
||||||
|
{
|
||||||
|
IConfig pConfig = config.Configs["BulletSim"];
|
||||||
|
if (pConfig != null)
|
||||||
|
{
|
||||||
|
DefaultFriction = pConfig.GetFloat("Friction", DefaultFriction);
|
||||||
|
DefaultDensity = pConfig.GetFloat("Density", DefaultDensity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if Debug, enable logging from the unmanaged code
|
||||||
|
if (m_log.IsDebugEnabled)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader);
|
||||||
|
debugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger);
|
||||||
|
BulletSimAPI.SetDebugLogCallback(debugLogCallbackHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
_meshSculptedPrim = true; // mesh sculpted prims
|
||||||
|
_forceSimplePrimMeshing = false; // use complex meshing if called for
|
||||||
|
|
||||||
|
_taintedObjects = new List<TaintCallback>();
|
||||||
|
|
||||||
|
mesher = meshmerizer;
|
||||||
|
// m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader);
|
||||||
|
m_worldID = BulletSimAPI.Initialize(new Vector3(Constants.RegionSize, Constants.RegionSize, 1000f));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BulletLogger(string msg)
|
||||||
|
{
|
||||||
|
m_log.Debug("[BULLETS UNMANAGED]:" + msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("{0}: CALL TO AddAvatar in BSScene. NOT IMPLEMENTED", LogHeader);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override PhysicsActor AddAvatar(uint localID, string avName, Vector3 position, Vector3 size, bool isFlying)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("{0}: AddAvatar: {1}", LogHeader, avName);
|
||||||
|
BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying);
|
||||||
|
lock (m_avatars) m_avatars.Add(localID, actor);
|
||||||
|
return actor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void RemoveAvatar(PhysicsActor actor)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("{0}: RemoveAvatar", LogHeader);
|
||||||
|
if (actor is BSCharacter)
|
||||||
|
{
|
||||||
|
((BSCharacter)actor).Destroy();
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (m_avatars) m_avatars.Remove(actor.LocalID);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0}: Attempt to remove avatar that is not in physics scene: {1}", LogHeader, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void RemovePrim(PhysicsActor prim)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("{0}: RemovePrim", LogHeader);
|
||||||
|
if (prim is BSPrim)
|
||||||
|
{
|
||||||
|
((BSPrim)prim).Destroy();
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (m_prims) m_prims.Remove(prim.LocalID);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0}: Attempt to remove prim that is not in physics scene: {1}", LogHeader, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
|
||||||
|
Vector3 size, Quaternion rotation) // deprecated
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
|
||||||
|
Vector3 size, Quaternion rotation, bool isPhysical)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("{0}: CALL TO AddPrimShape in BSScene. NOT IMPLEMENTED", LogHeader);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override PhysicsActor AddPrimShape(uint localID, string primName, PrimitiveBaseShape pbs, Vector3 position,
|
||||||
|
Vector3 size, Quaternion rotation, bool isPhysical)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("{0}: AddPrimShape2: {1}", LogHeader, primName);
|
||||||
|
IMesh mesh = null;
|
||||||
|
if (NeedsMeshing(pbs))
|
||||||
|
{
|
||||||
|
// if the prim is complex, create the mesh for it.
|
||||||
|
// If simple (box or sphere) leave 'mesh' null and physics will do a native shape.
|
||||||
|
// m_log.DebugFormat("{0}: AddPrimShape2: creating mesh", LogHeader);
|
||||||
|
mesh = mesher.CreateMesh(primName, pbs, size, this.meshLOD, isPhysical);
|
||||||
|
}
|
||||||
|
BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, mesh, pbs, isPhysical);
|
||||||
|
lock (m_prims) m_prims.Add(localID, prim);
|
||||||
|
return prim;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void AddPhysicsActorTaint(PhysicsActor prim) { }
|
||||||
|
|
||||||
|
public override float Simulate(float timeStep)
|
||||||
|
{
|
||||||
|
int updatedEntityCount;
|
||||||
|
IntPtr updatedEntitiesPtr;
|
||||||
|
IntPtr[] updatedEntities;
|
||||||
|
int collidersCount;
|
||||||
|
IntPtr collidersPtr;
|
||||||
|
int[] colliders; // should be uint but Marshal.Copy does not have that overload
|
||||||
|
|
||||||
|
// update the prim states while we know the physics engine is not busy
|
||||||
|
ProcessTaints();
|
||||||
|
|
||||||
|
// step the physical world one interval
|
||||||
|
m_simulationStep++;
|
||||||
|
int numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep,
|
||||||
|
out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
|
||||||
|
|
||||||
|
// if there were collisions, they show up here
|
||||||
|
if (collidersCount > 0)
|
||||||
|
{
|
||||||
|
colliders = new int[collidersCount];
|
||||||
|
Marshal.Copy(collidersPtr, colliders, 0, collidersCount);
|
||||||
|
for (int ii = 0; ii < collidersCount; ii+=2)
|
||||||
|
{
|
||||||
|
uint cA = (uint)colliders[ii];
|
||||||
|
uint cB = (uint)colliders[ii+1];
|
||||||
|
SendCollision(cA, cB);
|
||||||
|
SendCollision(cB, cA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if any of the objects had updated properties, they are returned in the updatedEntity structure
|
||||||
|
if (updatedEntityCount > 0)
|
||||||
|
{
|
||||||
|
updatedEntities = new IntPtr[updatedEntityCount];
|
||||||
|
Marshal.Copy(updatedEntitiesPtr, updatedEntities, 0, updatedEntityCount);
|
||||||
|
for (int ii = 0; ii < updatedEntityCount; ii++)
|
||||||
|
{
|
||||||
|
IntPtr updatePointer = updatedEntities[ii];
|
||||||
|
EntityProperties entprop = (EntityProperties)Marshal.PtrToStructure(updatePointer, typeof(EntityProperties));
|
||||||
|
// m_log.DebugFormat("{0}: entprop: id={1}, pos={2}", LogHeader, entprop.ID, entprop.Position);
|
||||||
|
if (m_avatars.ContainsKey(entprop.ID))
|
||||||
|
{
|
||||||
|
BSCharacter actor = m_avatars[entprop.ID];
|
||||||
|
actor.UpdateProperties(entprop);
|
||||||
|
}
|
||||||
|
if (m_prims.ContainsKey(entprop.ID))
|
||||||
|
{
|
||||||
|
BSPrim prim = m_prims[entprop.ID];
|
||||||
|
prim.UpdateProperties(entprop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 11f; // returns frames per second
|
||||||
|
}
|
||||||
|
|
||||||
|
// Something has collided
|
||||||
|
private void SendCollision(uint localID, uint collidingWith)
|
||||||
|
{
|
||||||
|
if (localID == TERRAIN_ID || localID == GROUNDPLANE_ID)
|
||||||
|
{
|
||||||
|
// we never send collisions to the terrain
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ActorTypes type = ActorTypes.Prim;
|
||||||
|
if (m_avatars.ContainsKey(collidingWith))
|
||||||
|
type = ActorTypes.Agent;
|
||||||
|
else if (collidingWith == TERRAIN_ID || collidingWith == GROUNDPLANE_ID)
|
||||||
|
type = ActorTypes.Ground;
|
||||||
|
|
||||||
|
if (m_prims.ContainsKey(localID))
|
||||||
|
{
|
||||||
|
BSPrim prim = m_prims[localID];
|
||||||
|
prim.Collide(collidingWith, type, Vector3.Zero, Vector3.UnitZ, 0.01f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_avatars.ContainsKey(localID))
|
||||||
|
{
|
||||||
|
BSCharacter actor = m_avatars[localID];
|
||||||
|
actor.Collide(collidingWith, type, Vector3.Zero, Vector3.UnitZ, 0.01f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void GetResults() { }
|
||||||
|
|
||||||
|
public override void SetTerrain(float[] heightMap) {
|
||||||
|
m_log.DebugFormat("{0}: SetTerrain", LogHeader);
|
||||||
|
m_heightMap = heightMap;
|
||||||
|
this.TaintedObject(delegate()
|
||||||
|
{
|
||||||
|
BulletSimAPI.SetHeightmap(m_worldID, m_heightMap);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetWaterLevel(float baseheight) { }
|
||||||
|
|
||||||
|
public override void DeleteTerrain()
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("{0}: Dispose()", LogHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Dictionary<uint, float> GetTopColliders()
|
||||||
|
{
|
||||||
|
return new Dictionary<uint, float>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsThreaded { get { return false; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Routine to figure out if we need to mesh this prim with our mesher
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pbs"></param>
|
||||||
|
/// <returns>true if the prim needs meshing</returns>
|
||||||
|
public bool NeedsMeshing(PrimitiveBaseShape pbs)
|
||||||
|
{
|
||||||
|
// most of this is redundant now as the mesher will return null if it cant mesh a prim
|
||||||
|
// but we still need to check for sculptie meshing being enabled so this is the most
|
||||||
|
// convenient place to do it for now...
|
||||||
|
|
||||||
|
// int iPropertiesNotSupportedDefault = 0;
|
||||||
|
|
||||||
|
if (pbs.SculptEntry && !_meshSculptedPrim)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("{0}: NeedsMeshing: scultpy mesh", LogHeader);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since Bullet
|
||||||
|
// can use an internal representation for the prim
|
||||||
|
if (!_forceSimplePrimMeshing)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("{0}: NeedsMeshing: simple mesh: profshape={1}, curve={2}", LogHeader, pbs.ProfileShape, pbs.PathCurve);
|
||||||
|
if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
|
||||||
|
|| (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
|
||||||
|
&& pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
|
||||||
|
{
|
||||||
|
|
||||||
|
if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
|
||||||
|
&& pbs.ProfileHollow == 0
|
||||||
|
&& pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
|
||||||
|
&& pbs.PathBegin == 0 && pbs.PathEnd == 0
|
||||||
|
&& pbs.PathTaperX == 0 && pbs.PathTaperY == 0
|
||||||
|
&& pbs.PathScaleX == 100 && pbs.PathScaleY == 100
|
||||||
|
&& pbs.PathShearX == 0 && pbs.PathShearY == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: verify that the mesher will now do all these shapes
|
||||||
|
if (pbs.ProfileHollow != 0)
|
||||||
|
iPropertiesNotSupportedDefault++;
|
||||||
|
|
||||||
|
if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
|
||||||
|
iPropertiesNotSupportedDefault++;
|
||||||
|
|
||||||
|
if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
|
||||||
|
iPropertiesNotSupportedDefault++;
|
||||||
|
|
||||||
|
if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
|
||||||
|
iPropertiesNotSupportedDefault++;
|
||||||
|
|
||||||
|
if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
|
||||||
|
iPropertiesNotSupportedDefault++;
|
||||||
|
|
||||||
|
if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
|
||||||
|
iPropertiesNotSupportedDefault++;
|
||||||
|
|
||||||
|
if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
|
||||||
|
iPropertiesNotSupportedDefault++;
|
||||||
|
|
||||||
|
if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X))
|
||||||
|
iPropertiesNotSupportedDefault++;
|
||||||
|
|
||||||
|
if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte) Extrusion.Curve1)
|
||||||
|
iPropertiesNotSupportedDefault++;
|
||||||
|
|
||||||
|
// test for torus
|
||||||
|
if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
|
||||||
|
{
|
||||||
|
if (pbs.PathCurve == (byte)Extrusion.Curve1)
|
||||||
|
{
|
||||||
|
iPropertiesNotSupportedDefault++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
|
||||||
|
{
|
||||||
|
if (pbs.PathCurve == (byte)Extrusion.Straight)
|
||||||
|
{
|
||||||
|
iPropertiesNotSupportedDefault++;
|
||||||
|
}
|
||||||
|
// ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
|
||||||
|
else if (pbs.PathCurve == (byte)Extrusion.Curve1)
|
||||||
|
{
|
||||||
|
iPropertiesNotSupportedDefault++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
|
||||||
|
{
|
||||||
|
if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
|
||||||
|
{
|
||||||
|
iPropertiesNotSupportedDefault++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
|
||||||
|
{
|
||||||
|
if (pbs.PathCurve == (byte)Extrusion.Straight)
|
||||||
|
{
|
||||||
|
iPropertiesNotSupportedDefault++;
|
||||||
|
}
|
||||||
|
else if (pbs.PathCurve == (byte)Extrusion.Curve1)
|
||||||
|
{
|
||||||
|
iPropertiesNotSupportedDefault++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (iPropertiesNotSupportedDefault == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The calls to the PhysicsActors can't directly call into the physics engine
|
||||||
|
// because it might be busy. We we delay changes to a known time.
|
||||||
|
// We rely on C#'s closure to save and restore the context for the delegate.
|
||||||
|
public void TaintedObject(TaintCallback callback)
|
||||||
|
{
|
||||||
|
// do we need to lock?
|
||||||
|
_taintedObjects.Add(callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// When someone tries to change a property on a BSPrim or BSCharacter, the object queues
|
||||||
|
// a callback into itself to do the actual property change. That callback is called
|
||||||
|
// here just before the physics engine is called to step the simulation.
|
||||||
|
public void ProcessTaints()
|
||||||
|
{
|
||||||
|
// swizzle a new list into the list location so we can process what's there
|
||||||
|
List<TaintCallback> newList = new List<TaintCallback>();
|
||||||
|
List<TaintCallback> oldList = (List<TaintCallback>)Interlocked.Exchange(ref _taintedObjects, newList);
|
||||||
|
|
||||||
|
foreach (TaintCallback callback in oldList)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("{0}: ProcessTaints: Exception: {1}", LogHeader, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
oldList.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,171 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2011, Intel Corporation
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
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 copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
* Neither the name of Intel Corporation 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR 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.Runtime.InteropServices;
|
||||||
|
using System.Security;
|
||||||
|
using System.Text;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.BulletSPlugin {
|
||||||
|
|
||||||
|
public struct ConvexHull
|
||||||
|
{
|
||||||
|
Vector3 Offset;
|
||||||
|
int VertexCount;
|
||||||
|
Vector3[] Vertices;
|
||||||
|
}
|
||||||
|
public struct ShapeData
|
||||||
|
{
|
||||||
|
public enum PhysicsShapeType
|
||||||
|
{
|
||||||
|
SHAPE_AVATAR = 0,
|
||||||
|
SHAPE_BOX = 1,
|
||||||
|
SHAPE_CONE = 2,
|
||||||
|
SHAPE_CYLINDER = 3,
|
||||||
|
SHAPE_SPHERE = 4,
|
||||||
|
SHAPE_HULL = 5
|
||||||
|
};
|
||||||
|
public const int numericTrue = 1;
|
||||||
|
public const int numericFalse = 0;
|
||||||
|
public uint ID;
|
||||||
|
public PhysicsShapeType Type;
|
||||||
|
public Vector3 Position;
|
||||||
|
public Quaternion Rotation;
|
||||||
|
public Vector3 Velocity;
|
||||||
|
public Vector3 Scale;
|
||||||
|
public float Mass;
|
||||||
|
public System.UInt64 MeshKey;
|
||||||
|
public int Collidable;
|
||||||
|
public int Flying;
|
||||||
|
public float Friction;
|
||||||
|
public int Dynamic;
|
||||||
|
// note that bools are passed as ints since bool size changes by language
|
||||||
|
}
|
||||||
|
public struct SweepHit
|
||||||
|
{
|
||||||
|
public uint ID;
|
||||||
|
public float Fraction;
|
||||||
|
public Vector3 Normal;
|
||||||
|
public Vector3 Point;
|
||||||
|
}
|
||||||
|
public struct RaycastHit
|
||||||
|
{
|
||||||
|
public uint ID;
|
||||||
|
public float Fraction;
|
||||||
|
public Vector3 Normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct EntityProperties
|
||||||
|
{
|
||||||
|
public uint ID;
|
||||||
|
public Vector3 Position;
|
||||||
|
public Quaternion Rotation;
|
||||||
|
public Vector3 Velocity;
|
||||||
|
public Vector3 Acceleration;
|
||||||
|
public Vector3 AngularVelocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class BulletSimAPI {
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern uint Initialize(Vector3 maxPosition);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern void Shutdown(uint worldID);
|
||||||
|
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep,
|
||||||
|
out int updatedEntityCount,
|
||||||
|
out IntPtr updatedEntitiesPtr,
|
||||||
|
out int collidersCount,
|
||||||
|
out IntPtr collidersPtr);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern bool CreateHull(uint worldID, System.UInt64 meshKey, int hullCount,
|
||||||
|
[MarshalAs(UnmanagedType.LPArray)] float[] hulls
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern bool DestroyHull(uint worldID, System.UInt64 meshKey);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern bool CreateObject(uint worldID, ShapeData shapeData);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern Vector3 GetObjectPosition(uint WorldID, uint id);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern bool SetObjectTranslation(uint worldID, uint id, Vector3 position, Quaternion rotation);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern bool SetObjectVelocity(uint worldID, uint id, Vector3 velocity);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern bool SetObjectForce(uint worldID, uint id, Vector3 force);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern bool SetObjectScaleMass(uint worldID, uint id, Vector3 scale, float mass, bool isDynamic);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern bool SetObjectCollidable(uint worldID, uint id, bool phantom);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern bool SetObjectDynamic(uint worldID, uint id, bool isDynamic, float mass);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern bool SetObjectFlying(uint worldID, uint id, bool flying);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern bool HasObject(uint worldID, uint id);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern bool DestroyObject(uint worldID, uint id);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern SweepHit ConvexSweepTest(uint worldID, uint id, Vector3 to, float extraMargin);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern RaycastHit RayTest(uint worldID, uint id, Vector3 from, Vector3 to);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern Vector3 RecoverFromPenetration(uint worldID, uint id);
|
||||||
|
|
||||||
|
// Log a debug message
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern void SetDebugLogCallback(DebugLogCallback callback);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
<Project frameworkVersion="v3_5" name="OpenSim.Region.Physics.BulletSPlugin" path="addon-modules/BulletSPlugin" type="Library">
|
||||||
|
<Configuration name="Debug">
|
||||||
|
<Options>
|
||||||
|
<OutputPath>../../bin/Physics/</OutputPath>
|
||||||
|
</Options>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration name="Release">
|
||||||
|
<Options>
|
||||||
|
<OutputPath>../../bin/Physics/</OutputPath>
|
||||||
|
</Options>
|
||||||
|
</Configuration>
|
||||||
|
|
||||||
|
<ReferencePath>../../bin/</ReferencePath>
|
||||||
|
<Reference name="System"/>
|
||||||
|
<Reference name="System.Core"/>
|
||||||
|
<Reference name="System.Xml"/>
|
||||||
|
<Reference name="OpenMetaverseTypes" path="../../bin/"/>
|
||||||
|
<Reference name="Nini.dll" path="../../bin/"/>
|
||||||
|
<Reference name="OpenSim.Framework"/>
|
||||||
|
<Reference name="OpenSim.Region.Framework"/>
|
||||||
|
<Reference name="OpenSim.Region.CoreModules"/>
|
||||||
|
<Reference name="OpenSim.Framework.Console"/>
|
||||||
|
<Reference name="OpenSim.Region.Physics.Manager"/>
|
||||||
|
<Reference name="OpenSim.Region.Physics.ConvexDecompositionDotNet"/>
|
||||||
|
<Reference name="log4net.dll" path="../../bin/"/>
|
||||||
|
|
||||||
|
<Files>
|
||||||
|
<Match pattern="*.cs" recurse="true">
|
||||||
|
<Exclude name="Tests" pattern="Tests"/>
|
||||||
|
</Match>
|
||||||
|
</Files>
|
||||||
|
</Project>
|
Loading…
Reference in New Issue