Merge branch 'dev' into dev_attachment
commit
ef4caa2c75
|
@ -342,7 +342,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
{
|
{
|
||||||
UUID uuid = data["uuid"].AsUUID();
|
UUID uuid = data["uuid"].AsUUID();
|
||||||
string actorID = data["actorID"].AsString();
|
string actorID = data["actorID"].AsString();
|
||||||
m_log.DebugFormat("{0}: HandlPhysUpdateAttributes for {1}", LogHeader, uuid);
|
// m_log.DebugFormat("{0}: HandlPhysUpdateAttributes for {1}", LogHeader, uuid);
|
||||||
PhysicsActor pa = FindPhysicsActor(uuid);
|
PhysicsActor pa = FindPhysicsActor(uuid);
|
||||||
if (pa != null)
|
if (pa != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -373,7 +373,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
pa.Kinematic = data["kinematic"].AsBoolean(); // receive??
|
pa.Kinematic = data["kinematic"].AsBoolean(); // receive??
|
||||||
pa.Buoyancy = (float)(data["buoyancy"].AsReal());
|
pa.Buoyancy = (float)(data["buoyancy"].AsReal());
|
||||||
pa.CollidingGround = data["isCollidingGround"].AsBoolean();
|
pa.CollidingGround = data["isCollidingGround"].AsBoolean();
|
||||||
pa.IsColliding = data["isCollidingGround"].AsBoolean();
|
pa.IsColliding = data["isColliding"].AsBoolean();
|
||||||
pa.ChangingActorID = actorID;
|
pa.ChangingActorID = actorID;
|
||||||
|
|
||||||
pa.RequestPhysicsterseUpdate(); // tell the system the values have changed
|
pa.RequestPhysicsterseUpdate(); // tell the system the values have changed
|
||||||
|
@ -431,8 +431,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
data["isPhysical"] = OSD.FromBoolean(pa.IsPhysical);
|
data["isPhysical"] = OSD.FromBoolean(pa.IsPhysical);
|
||||||
data["flying"] = OSD.FromBoolean(pa.Flying);
|
data["flying"] = OSD.FromBoolean(pa.Flying);
|
||||||
data["buoyancy"] = OSD.FromReal(pa.Buoyancy);
|
data["buoyancy"] = OSD.FromReal(pa.Buoyancy);
|
||||||
// data["isColliding"] = OSD.FromBoolean(pa.IsColliding);
|
data["isColliding"] = OSD.FromBoolean(pa.IsColliding);
|
||||||
// data["isCollidingGround"] = OSD.FromBoolean(pa.CollidingGround);
|
data["isCollidingGround"] = OSD.FromBoolean(pa.CollidingGround);
|
||||||
|
|
||||||
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.PhysUpdateAttributes,
|
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.PhysUpdateAttributes,
|
||||||
OSDParser.SerializeJsonString(data));
|
OSDParser.SerializeJsonString(data));
|
||||||
|
|
|
@ -1751,6 +1751,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// Check that we have a physics actor or we're sitting on something
|
// Check that we have a physics actor or we're sitting on something
|
||||||
if (sp.ParentID == 0 && sp.PhysicsActor != null || sp.ParentID != 0)
|
if (sp.ParentID == 0 && sp.PhysicsActor != null || sp.ParentID != 0)
|
||||||
{
|
{
|
||||||
|
if(!sp.IsSyncedAvatar)
|
||||||
sp.CheckForBorderCrossing();
|
sp.CheckForBorderCrossing();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1627,6 +1627,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible))
|
if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible))
|
||||||
{
|
{
|
||||||
PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape(
|
PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape(
|
||||||
|
LocalId,
|
||||||
string.Format("{0}/{1}", Name, UUID),
|
string.Format("{0}/{1}", Name, UUID),
|
||||||
Shape,
|
Shape,
|
||||||
AbsolutePosition,
|
AbsolutePosition,
|
||||||
|
@ -2794,7 +2795,12 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
//m_parentGroup.RootPart.m_groupPosition = newpos;
|
//m_parentGroup.RootPart.m_groupPosition = newpos;
|
||||||
}
|
}
|
||||||
//ScheduleTerseUpdate();
|
//ScheduleTerseUpdate();
|
||||||
ScheduleTerseUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.Position});
|
ScheduleTerseUpdate(new List<SceneObjectPartSyncProperties>(){
|
||||||
|
SceneObjectPartSyncProperties.Position,
|
||||||
|
SceneObjectPartSyncProperties.Orientation,
|
||||||
|
SceneObjectPartSyncProperties.Velocity,
|
||||||
|
SceneObjectPartSyncProperties.RotationalVelocity
|
||||||
|
});
|
||||||
|
|
||||||
//SendTerseUpdateToAllClients();
|
//SendTerseUpdateToAllClients();
|
||||||
}
|
}
|
||||||
|
@ -4490,6 +4496,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
// It's not phantom anymore. So make sure the physics engine get's knowledge of it
|
// It's not phantom anymore. So make sure the physics engine get's knowledge of it
|
||||||
PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape(
|
PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape(
|
||||||
|
LocalId,
|
||||||
string.Format("{0}/{1}", Name, UUID),
|
string.Format("{0}/{1}", Name, UUID),
|
||||||
Shape,
|
Shape,
|
||||||
AbsolutePosition,
|
AbsolutePosition,
|
||||||
|
|
|
@ -3405,7 +3405,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
Vector3 pVec = AbsolutePosition;
|
Vector3 pVec = AbsolutePosition;
|
||||||
|
|
||||||
// Old bug where the height was in centimeters instead of meters
|
// Old bug where the height was in centimeters instead of meters
|
||||||
m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec,
|
m_physicsActor = scene.AddAvatar(LocalId, Firstname + "." + Lastname, pVec,
|
||||||
new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying);
|
new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying);
|
||||||
|
|
||||||
scene.AddPhysicsActorTaint(m_physicsActor);
|
scene.AddPhysicsActorTaint(m_physicsActor);
|
||||||
|
|
|
@ -66,6 +66,11 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
|
|
||||||
public abstract PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying);
|
public abstract PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying);
|
||||||
|
|
||||||
|
public virtual PhysicsActor AddAvatar(uint localID, string avName, Vector3 position, Vector3 size, bool isFlying)
|
||||||
|
{
|
||||||
|
return AddAvatar(avName, position, size, isFlying);
|
||||||
|
}
|
||||||
|
|
||||||
public abstract void RemoveAvatar(PhysicsActor actor);
|
public abstract void RemoveAvatar(PhysicsActor actor);
|
||||||
|
|
||||||
public abstract void RemovePrim(PhysicsActor prim);
|
public abstract void RemovePrim(PhysicsActor prim);
|
||||||
|
@ -75,6 +80,12 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
|
public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
|
||||||
Vector3 size, Quaternion rotation, bool isPhysical);
|
Vector3 size, Quaternion rotation, bool isPhysical);
|
||||||
|
|
||||||
|
public virtual PhysicsActor AddPrimShape(uint localId, string primName, PrimitiveBaseShape pbs, Vector3 position,
|
||||||
|
Vector3 size, Quaternion rotation, bool isPhysical)
|
||||||
|
{
|
||||||
|
return AddPrimShape(primName, pbs, position, size, rotation, isPhysical);
|
||||||
|
}
|
||||||
|
|
||||||
public virtual float TimeDilation
|
public virtual float TimeDilation
|
||||||
{
|
{
|
||||||
get { return 1.0f; }
|
get { return 1.0f; }
|
||||||
|
|
|
@ -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>
|
|
@ -0,0 +1,341 @@
|
||||||
|
/* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Based on the convexdecomposition library from
|
||||||
|
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
|
||||||
|
{
|
||||||
|
public class Wpoint
|
||||||
|
{
|
||||||
|
public float3 mPoint;
|
||||||
|
public float mWeight;
|
||||||
|
|
||||||
|
public Wpoint(float3 p, float w)
|
||||||
|
{
|
||||||
|
mPoint = p;
|
||||||
|
mWeight = w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CTri
|
||||||
|
{
|
||||||
|
private const int WSCALE = 4;
|
||||||
|
|
||||||
|
public float3 mP1;
|
||||||
|
public float3 mP2;
|
||||||
|
public float3 mP3;
|
||||||
|
public float3 mNear1;
|
||||||
|
public float3 mNear2;
|
||||||
|
public float3 mNear3;
|
||||||
|
public float3 mNormal;
|
||||||
|
public float mPlaneD;
|
||||||
|
public float mConcavity;
|
||||||
|
public float mC1;
|
||||||
|
public float mC2;
|
||||||
|
public float mC3;
|
||||||
|
public int mI1;
|
||||||
|
public int mI2;
|
||||||
|
public int mI3;
|
||||||
|
public int mProcessed; // already been added...
|
||||||
|
|
||||||
|
public CTri(float3 p1, float3 p2, float3 p3, int i1, int i2, int i3)
|
||||||
|
{
|
||||||
|
mProcessed = 0;
|
||||||
|
mI1 = i1;
|
||||||
|
mI2 = i2;
|
||||||
|
mI3 = i3;
|
||||||
|
|
||||||
|
mP1 = new float3(p1);
|
||||||
|
mP2 = new float3(p2);
|
||||||
|
mP3 = new float3(p3);
|
||||||
|
|
||||||
|
mNear1 = new float3();
|
||||||
|
mNear2 = new float3();
|
||||||
|
mNear3 = new float3();
|
||||||
|
|
||||||
|
mNormal = new float3();
|
||||||
|
mPlaneD = mNormal.ComputePlane(mP1, mP2, mP3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Facing(CTri t)
|
||||||
|
{
|
||||||
|
return float3.dot(mNormal, t.mNormal);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool clip(float3 start, ref float3 end)
|
||||||
|
{
|
||||||
|
float3 sect = new float3();
|
||||||
|
bool hit = lineIntersectsTriangle(start, end, mP1, mP2, mP3, ref sect);
|
||||||
|
|
||||||
|
if (hit)
|
||||||
|
end = sect;
|
||||||
|
return hit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Concave(float3 p, ref float distance, ref float3 n)
|
||||||
|
{
|
||||||
|
n.NearestPointInTriangle(p, mP1, mP2, mP3);
|
||||||
|
distance = p.Distance(n);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTri(int[] indices, int i1, int i2, int i3, ref int tcount)
|
||||||
|
{
|
||||||
|
indices[tcount * 3 + 0] = i1;
|
||||||
|
indices[tcount * 3 + 1] = i2;
|
||||||
|
indices[tcount * 3 + 2] = i3;
|
||||||
|
tcount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getVolume()
|
||||||
|
{
|
||||||
|
int[] indices = new int[8 * 3];
|
||||||
|
|
||||||
|
int tcount = 0;
|
||||||
|
|
||||||
|
addTri(indices, 0, 1, 2, ref tcount);
|
||||||
|
addTri(indices, 3, 4, 5, ref tcount);
|
||||||
|
|
||||||
|
addTri(indices, 0, 3, 4, ref tcount);
|
||||||
|
addTri(indices, 0, 4, 1, ref tcount);
|
||||||
|
|
||||||
|
addTri(indices, 1, 4, 5, ref tcount);
|
||||||
|
addTri(indices, 1, 5, 2, ref tcount);
|
||||||
|
|
||||||
|
addTri(indices, 0, 3, 5, ref tcount);
|
||||||
|
addTri(indices, 0, 5, 2, ref tcount);
|
||||||
|
|
||||||
|
List<float3> vertices = new List<float3> { mP1, mP2, mP3, mNear1, mNear2, mNear3 };
|
||||||
|
List<int> indexList = new List<int>(indices);
|
||||||
|
|
||||||
|
float v = Concavity.computeMeshVolume(vertices, indexList);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float raySect(float3 p, float3 dir, ref float3 sect)
|
||||||
|
{
|
||||||
|
float4 plane = new float4();
|
||||||
|
|
||||||
|
plane.x = mNormal.x;
|
||||||
|
plane.y = mNormal.y;
|
||||||
|
plane.z = mNormal.z;
|
||||||
|
plane.w = mPlaneD;
|
||||||
|
|
||||||
|
float3 dest = p + dir * 100000f;
|
||||||
|
|
||||||
|
intersect(p, dest, ref sect, plane);
|
||||||
|
|
||||||
|
return sect.Distance(p); // return the intersection distance
|
||||||
|
}
|
||||||
|
|
||||||
|
public float planeDistance(float3 p)
|
||||||
|
{
|
||||||
|
float4 plane = new float4();
|
||||||
|
|
||||||
|
plane.x = mNormal.x;
|
||||||
|
plane.y = mNormal.y;
|
||||||
|
plane.z = mNormal.z;
|
||||||
|
plane.w = mPlaneD;
|
||||||
|
|
||||||
|
return DistToPt(p, plane);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool samePlane(CTri t)
|
||||||
|
{
|
||||||
|
const float THRESH = 0.001f;
|
||||||
|
float dd = Math.Abs(t.mPlaneD - mPlaneD);
|
||||||
|
if (dd > THRESH)
|
||||||
|
return false;
|
||||||
|
dd = Math.Abs(t.mNormal.x - mNormal.x);
|
||||||
|
if (dd > THRESH)
|
||||||
|
return false;
|
||||||
|
dd = Math.Abs(t.mNormal.y - mNormal.y);
|
||||||
|
if (dd > THRESH)
|
||||||
|
return false;
|
||||||
|
dd = Math.Abs(t.mNormal.z - mNormal.z);
|
||||||
|
if (dd > THRESH)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool hasIndex(int i)
|
||||||
|
{
|
||||||
|
if (i == mI1 || i == mI2 || i == mI3)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool sharesEdge(CTri t)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
uint count = 0;
|
||||||
|
|
||||||
|
if (t.hasIndex(mI1))
|
||||||
|
count++;
|
||||||
|
if (t.hasIndex(mI2))
|
||||||
|
count++;
|
||||||
|
if (t.hasIndex(mI3))
|
||||||
|
count++;
|
||||||
|
|
||||||
|
if (count >= 2)
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float area()
|
||||||
|
{
|
||||||
|
float a = mConcavity * mP1.Area(mP2, mP3);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addWeighted(List<Wpoint> list)
|
||||||
|
{
|
||||||
|
Wpoint p1 = new Wpoint(mP1, mC1);
|
||||||
|
Wpoint p2 = new Wpoint(mP2, mC2);
|
||||||
|
Wpoint p3 = new Wpoint(mP3, mC3);
|
||||||
|
|
||||||
|
float3 d1 = mNear1 - mP1;
|
||||||
|
float3 d2 = mNear2 - mP2;
|
||||||
|
float3 d3 = mNear3 - mP3;
|
||||||
|
|
||||||
|
d1 *= WSCALE;
|
||||||
|
d2 *= WSCALE;
|
||||||
|
d3 *= WSCALE;
|
||||||
|
|
||||||
|
d1 = d1 + mP1;
|
||||||
|
d2 = d2 + mP2;
|
||||||
|
d3 = d3 + mP3;
|
||||||
|
|
||||||
|
Wpoint p4 = new Wpoint(d1, mC1);
|
||||||
|
Wpoint p5 = new Wpoint(d2, mC2);
|
||||||
|
Wpoint p6 = new Wpoint(d3, mC3);
|
||||||
|
|
||||||
|
list.Add(p1);
|
||||||
|
list.Add(p2);
|
||||||
|
list.Add(p3);
|
||||||
|
|
||||||
|
list.Add(p4);
|
||||||
|
list.Add(p5);
|
||||||
|
list.Add(p6);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float DistToPt(float3 p, float4 plane)
|
||||||
|
{
|
||||||
|
float x = p.x;
|
||||||
|
float y = p.y;
|
||||||
|
float z = p.z;
|
||||||
|
float d = x*plane.x + y*plane.y + z*plane.z + plane.w;
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void intersect(float3 p1, float3 p2, ref float3 split, float4 plane)
|
||||||
|
{
|
||||||
|
float dp1 = DistToPt(p1, plane);
|
||||||
|
|
||||||
|
float3 dir = new float3();
|
||||||
|
dir.x = p2[0] - p1[0];
|
||||||
|
dir.y = p2[1] - p1[1];
|
||||||
|
dir.z = p2[2] - p1[2];
|
||||||
|
|
||||||
|
float dot1 = dir[0] * plane[0] + dir[1] * plane[1] + dir[2] * plane[2];
|
||||||
|
float dot2 = dp1 - plane[3];
|
||||||
|
|
||||||
|
float t = -(plane[3] + dot2) / dot1;
|
||||||
|
|
||||||
|
split.x = (dir[0] * t) + p1[0];
|
||||||
|
split.y = (dir[1] * t) + p1[1];
|
||||||
|
split.z = (dir[2] * t) + p1[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool rayIntersectsTriangle(float3 p, float3 d, float3 v0, float3 v1, float3 v2, out float t)
|
||||||
|
{
|
||||||
|
t = 0f;
|
||||||
|
|
||||||
|
float3 e1, e2, h, s, q;
|
||||||
|
float a, f, u, v;
|
||||||
|
|
||||||
|
e1 = v1 - v0;
|
||||||
|
e2 = v2 - v0;
|
||||||
|
h = float3.cross(d, e2);
|
||||||
|
a = float3.dot(e1, h);
|
||||||
|
|
||||||
|
if (a > -0.00001f && a < 0.00001f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
f = 1f / a;
|
||||||
|
s = p - v0;
|
||||||
|
u = f * float3.dot(s, h);
|
||||||
|
|
||||||
|
if (u < 0.0f || u > 1.0f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
q = float3.cross(s, e1);
|
||||||
|
v = f * float3.dot(d, q);
|
||||||
|
if (v < 0.0f || u + v > 1.0f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// at this stage we can compute t to find out where
|
||||||
|
// the intersection point is on the line
|
||||||
|
t = f * float3.dot(e2, q);
|
||||||
|
if (t > 0f) // ray intersection
|
||||||
|
return true;
|
||||||
|
else // this means that there is a line intersection but not a ray intersection
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool lineIntersectsTriangle(float3 rayStart, float3 rayEnd, float3 p1, float3 p2, float3 p3, ref float3 sect)
|
||||||
|
{
|
||||||
|
float3 dir = rayEnd - rayStart;
|
||||||
|
|
||||||
|
float d = (float)Math.Sqrt(dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]);
|
||||||
|
float r = 1.0f / d;
|
||||||
|
|
||||||
|
dir *= r;
|
||||||
|
|
||||||
|
float t;
|
||||||
|
bool ret = rayIntersectsTriangle(rayStart, dir, p1, p2, p3, out t);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
if (t > d)
|
||||||
|
{
|
||||||
|
sect.x = rayStart.x + dir.x * t;
|
||||||
|
sect.y = rayStart.y + dir.y * t;
|
||||||
|
sect.z = rayStart.z + dir.z * t;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,233 @@
|
||||||
|
/* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Based on the convexdecomposition library from
|
||||||
|
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
|
||||||
|
{
|
||||||
|
public static class Concavity
|
||||||
|
{
|
||||||
|
// compute's how 'concave' this object is and returns the total volume of the
|
||||||
|
// convex hull as well as the volume of the 'concavity' which was found.
|
||||||
|
public static float computeConcavity(List<float3> vertices, List<int> indices, ref float4 plane, ref float volume)
|
||||||
|
{
|
||||||
|
float cret = 0f;
|
||||||
|
volume = 1f;
|
||||||
|
|
||||||
|
HullResult result = new HullResult();
|
||||||
|
HullDesc desc = new HullDesc();
|
||||||
|
|
||||||
|
desc.MaxFaces = 256;
|
||||||
|
desc.MaxVertices = 256;
|
||||||
|
desc.SetHullFlag(HullFlag.QF_TRIANGLES);
|
||||||
|
desc.Vertices = vertices;
|
||||||
|
|
||||||
|
HullError ret = HullUtils.CreateConvexHull(desc, ref result);
|
||||||
|
|
||||||
|
if (ret == HullError.QE_OK)
|
||||||
|
{
|
||||||
|
volume = computeMeshVolume2(result.OutputVertices, result.Indices);
|
||||||
|
|
||||||
|
// ok..now..for each triangle on the original mesh..
|
||||||
|
// we extrude the points to the nearest point on the hull.
|
||||||
|
List<CTri> tris = new List<CTri>();
|
||||||
|
|
||||||
|
for (int i = 0; i < result.Indices.Count / 3; i++)
|
||||||
|
{
|
||||||
|
int i1 = result.Indices[i * 3 + 0];
|
||||||
|
int i2 = result.Indices[i * 3 + 1];
|
||||||
|
int i3 = result.Indices[i * 3 + 2];
|
||||||
|
|
||||||
|
float3 p1 = result.OutputVertices[i1];
|
||||||
|
float3 p2 = result.OutputVertices[i2];
|
||||||
|
float3 p3 = result.OutputVertices[i3];
|
||||||
|
|
||||||
|
CTri t = new CTri(p1, p2, p3, i1, i2, i3);
|
||||||
|
tris.Add(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we have not pre-computed the plane equation for each triangle in the convex hull..
|
||||||
|
float totalVolume = 0;
|
||||||
|
|
||||||
|
List<CTri> ftris = new List<CTri>(); // 'feature' triangles.
|
||||||
|
List<CTri> input_mesh = new List<CTri>();
|
||||||
|
|
||||||
|
for (int i = 0; i < indices.Count / 3; i++)
|
||||||
|
{
|
||||||
|
int i1 = indices[i * 3 + 0];
|
||||||
|
int i2 = indices[i * 3 + 1];
|
||||||
|
int i3 = indices[i * 3 + 2];
|
||||||
|
|
||||||
|
float3 p1 = vertices[i1];
|
||||||
|
float3 p2 = vertices[i2];
|
||||||
|
float3 p3 = vertices[i3];
|
||||||
|
|
||||||
|
CTri t = new CTri(p1, p2, p3, i1, i2, i3);
|
||||||
|
input_mesh.Add(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < indices.Count / 3; i++)
|
||||||
|
{
|
||||||
|
int i1 = indices[i * 3 + 0];
|
||||||
|
int i2 = indices[i * 3 + 1];
|
||||||
|
int i3 = indices[i * 3 + 2];
|
||||||
|
|
||||||
|
float3 p1 = vertices[i1];
|
||||||
|
float3 p2 = vertices[i2];
|
||||||
|
float3 p3 = vertices[i3];
|
||||||
|
|
||||||
|
CTri t = new CTri(p1, p2, p3, i1, i2, i3);
|
||||||
|
|
||||||
|
featureMatch(t, tris, input_mesh);
|
||||||
|
|
||||||
|
if (t.mConcavity > 0.05f)
|
||||||
|
{
|
||||||
|
float v = t.getVolume();
|
||||||
|
totalVolume += v;
|
||||||
|
ftris.Add(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SplitPlane.computeSplitPlane(vertices, indices, ref plane);
|
||||||
|
cret = totalVolume;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool featureMatch(CTri m, List<CTri> tris, List<CTri> input_mesh)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
float neardot = 0.707f;
|
||||||
|
m.mConcavity = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < tris.Count; i++)
|
||||||
|
{
|
||||||
|
CTri t = tris[i];
|
||||||
|
|
||||||
|
if (t.samePlane(m))
|
||||||
|
{
|
||||||
|
ret = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
float dot = float3.dot(t.mNormal, m.mNormal);
|
||||||
|
|
||||||
|
if (dot > neardot)
|
||||||
|
{
|
||||||
|
float d1 = t.planeDistance(m.mP1);
|
||||||
|
float d2 = t.planeDistance(m.mP2);
|
||||||
|
float d3 = t.planeDistance(m.mP3);
|
||||||
|
|
||||||
|
if (d1 > 0.001f || d2 > 0.001f || d3 > 0.001f) // can't be near coplaner!
|
||||||
|
{
|
||||||
|
neardot = dot;
|
||||||
|
|
||||||
|
t.raySect(m.mP1, m.mNormal, ref m.mNear1);
|
||||||
|
t.raySect(m.mP2, m.mNormal, ref m.mNear2);
|
||||||
|
t.raySect(m.mP3, m.mNormal, ref m.mNear3);
|
||||||
|
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
m.mC1 = m.mP1.Distance(m.mNear1);
|
||||||
|
m.mC2 = m.mP2.Distance(m.mNear2);
|
||||||
|
m.mC3 = m.mP3.Distance(m.mNear3);
|
||||||
|
|
||||||
|
m.mConcavity = m.mC1;
|
||||||
|
|
||||||
|
if (m.mC2 > m.mConcavity)
|
||||||
|
m.mConcavity = m.mC2;
|
||||||
|
if (m.mC3 > m.mConcavity)
|
||||||
|
m.mConcavity = m.mC3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float det(float3 p1, float3 p2, float3 p3)
|
||||||
|
{
|
||||||
|
return p1.x * p2.y * p3.z + p2.x * p3.y * p1.z + p3.x * p1.y * p2.z - p1.x * p3.y * p2.z - p2.x * p1.y * p3.z - p3.x * p2.y * p1.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float computeMeshVolume(List<float3> vertices, List<int> indices)
|
||||||
|
{
|
||||||
|
float volume = 0f;
|
||||||
|
|
||||||
|
for (int i = 0; i < indices.Count / 3; i++)
|
||||||
|
{
|
||||||
|
float3 p1 = vertices[indices[i * 3 + 0]];
|
||||||
|
float3 p2 = vertices[indices[i * 3 + 1]];
|
||||||
|
float3 p3 = vertices[indices[i * 3 + 2]];
|
||||||
|
|
||||||
|
volume += det(p1, p2, p3); // compute the volume of the tetrahedran relative to the origin.
|
||||||
|
}
|
||||||
|
|
||||||
|
volume *= (1.0f / 6.0f);
|
||||||
|
if (volume < 0f)
|
||||||
|
return -volume;
|
||||||
|
return volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float computeMeshVolume2(List<float3> vertices, List<int> indices)
|
||||||
|
{
|
||||||
|
float volume = 0f;
|
||||||
|
|
||||||
|
float3 p0 = vertices[0];
|
||||||
|
for (int i = 0; i < indices.Count / 3; i++)
|
||||||
|
{
|
||||||
|
float3 p1 = vertices[indices[i * 3 + 0]];
|
||||||
|
float3 p2 = vertices[indices[i * 3 + 1]];
|
||||||
|
float3 p3 = vertices[indices[i * 3 + 2]];
|
||||||
|
|
||||||
|
volume += tetVolume(p0, p1, p2, p3); // compute the volume of the tetrahedron relative to the root vertice
|
||||||
|
}
|
||||||
|
|
||||||
|
return volume * (1.0f / 6.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float tetVolume(float3 p0, float3 p1, float3 p2, float3 p3)
|
||||||
|
{
|
||||||
|
float3 a = p1 - p0;
|
||||||
|
float3 b = p2 - p0;
|
||||||
|
float3 c = p3 - p0;
|
||||||
|
|
||||||
|
float3 cross = float3.cross(b, c);
|
||||||
|
float volume = float3.dot(a, cross);
|
||||||
|
|
||||||
|
if (volume < 0f)
|
||||||
|
return -volume;
|
||||||
|
return volume;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,411 @@
|
||||||
|
/* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Based on the convexdecomposition library from
|
||||||
|
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
|
||||||
|
{
|
||||||
|
public class DecompDesc
|
||||||
|
{
|
||||||
|
public List<float3> mVertices;
|
||||||
|
public List<int> mIndices;
|
||||||
|
|
||||||
|
// options
|
||||||
|
public uint mDepth; // depth to split, a maximum of 10, generally not over 7.
|
||||||
|
public float mCpercent; // the concavity threshold percentage. 0=20 is reasonable.
|
||||||
|
public float mPpercent; // the percentage volume conservation threshold to collapse hulls. 0-30 is reasonable.
|
||||||
|
|
||||||
|
// hull output limits.
|
||||||
|
public uint mMaxVertices; // maximum number of vertices in the output hull. Recommended 32 or less.
|
||||||
|
public float mSkinWidth; // a skin width to apply to the output hulls.
|
||||||
|
|
||||||
|
public ConvexDecompositionCallback mCallback; // the interface to receive back the results.
|
||||||
|
|
||||||
|
public DecompDesc()
|
||||||
|
{
|
||||||
|
mDepth = 5;
|
||||||
|
mCpercent = 5;
|
||||||
|
mPpercent = 5;
|
||||||
|
mMaxVertices = 32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CHull
|
||||||
|
{
|
||||||
|
public float[] mMin = new float[3];
|
||||||
|
public float[] mMax = new float[3];
|
||||||
|
public float mVolume;
|
||||||
|
public float mDiagonal;
|
||||||
|
public ConvexResult mResult;
|
||||||
|
|
||||||
|
public CHull(ConvexResult result)
|
||||||
|
{
|
||||||
|
mResult = new ConvexResult(result);
|
||||||
|
mVolume = Concavity.computeMeshVolume(result.HullVertices, result.HullIndices);
|
||||||
|
|
||||||
|
mDiagonal = getBoundingRegion(result.HullVertices, mMin, mMax);
|
||||||
|
|
||||||
|
float dx = mMax[0] - mMin[0];
|
||||||
|
float dy = mMax[1] - mMin[1];
|
||||||
|
float dz = mMax[2] - mMin[2];
|
||||||
|
|
||||||
|
dx *= 0.1f; // inflate 1/10th on each edge
|
||||||
|
dy *= 0.1f; // inflate 1/10th on each edge
|
||||||
|
dz *= 0.1f; // inflate 1/10th on each edge
|
||||||
|
|
||||||
|
mMin[0] -= dx;
|
||||||
|
mMin[1] -= dy;
|
||||||
|
mMin[2] -= dz;
|
||||||
|
|
||||||
|
mMax[0] += dx;
|
||||||
|
mMax[1] += dy;
|
||||||
|
mMax[2] += dz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
mResult = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool overlap(CHull h)
|
||||||
|
{
|
||||||
|
return overlapAABB(mMin, mMax, h.mMin, h.mMax);
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the d1Giagonal distance
|
||||||
|
private static float getBoundingRegion(List<float3> points, float[] bmin, float[] bmax)
|
||||||
|
{
|
||||||
|
float3 first = points[0];
|
||||||
|
|
||||||
|
bmin[0] = first.x;
|
||||||
|
bmin[1] = first.y;
|
||||||
|
bmin[2] = first.z;
|
||||||
|
|
||||||
|
bmax[0] = first.x;
|
||||||
|
bmax[1] = first.y;
|
||||||
|
bmax[2] = first.z;
|
||||||
|
|
||||||
|
for (int i = 1; i < points.Count; i++)
|
||||||
|
{
|
||||||
|
float3 p = points[i];
|
||||||
|
|
||||||
|
if (p[0] < bmin[0]) bmin[0] = p[0];
|
||||||
|
if (p[1] < bmin[1]) bmin[1] = p[1];
|
||||||
|
if (p[2] < bmin[2]) bmin[2] = p[2];
|
||||||
|
|
||||||
|
if (p[0] > bmax[0]) bmax[0] = p[0];
|
||||||
|
if (p[1] > bmax[1]) bmax[1] = p[1];
|
||||||
|
if (p[2] > bmax[2]) bmax[2] = p[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
float dx = bmax[0] - bmin[0];
|
||||||
|
float dy = bmax[1] - bmin[1];
|
||||||
|
float dz = bmax[2] - bmin[2];
|
||||||
|
|
||||||
|
return (float)Math.Sqrt(dx * dx + dy * dy + dz * dz);
|
||||||
|
}
|
||||||
|
|
||||||
|
// return true if the two AABB's overlap.
|
||||||
|
private static bool overlapAABB(float[] bmin1, float[] bmax1, float[] bmin2, float[] bmax2)
|
||||||
|
{
|
||||||
|
if (bmax2[0] < bmin1[0]) return false; // if the maximum is less than our minimum on any axis
|
||||||
|
if (bmax2[1] < bmin1[1]) return false;
|
||||||
|
if (bmax2[2] < bmin1[2]) return false;
|
||||||
|
|
||||||
|
if (bmin2[0] > bmax1[0]) return false; // if the minimum is greater than our maximum on any axis
|
||||||
|
if (bmin2[1] > bmax1[1]) return false; // if the minimum is greater than our maximum on any axis
|
||||||
|
if (bmin2[2] > bmax1[2]) return false; // if the minimum is greater than our maximum on any axis
|
||||||
|
|
||||||
|
return true; // the extents overlap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ConvexBuilder
|
||||||
|
{
|
||||||
|
public List<CHull> mChulls = new List<CHull>();
|
||||||
|
private ConvexDecompositionCallback mCallback;
|
||||||
|
|
||||||
|
private int MAXDEPTH = 8;
|
||||||
|
private float CONCAVE_PERCENT = 1f;
|
||||||
|
private float MERGE_PERCENT = 2f;
|
||||||
|
|
||||||
|
public ConvexBuilder(ConvexDecompositionCallback callback)
|
||||||
|
{
|
||||||
|
mCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < mChulls.Count; i++)
|
||||||
|
{
|
||||||
|
CHull cr = mChulls[i];
|
||||||
|
cr.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool isDuplicate(uint i1, uint i2, uint i3, uint ci1, uint ci2, uint ci3)
|
||||||
|
{
|
||||||
|
uint dcount = 0;
|
||||||
|
|
||||||
|
Debug.Assert(i1 != i2 && i1 != i3 && i2 != i3);
|
||||||
|
Debug.Assert(ci1 != ci2 && ci1 != ci3 && ci2 != ci3);
|
||||||
|
|
||||||
|
if (i1 == ci1 || i1 == ci2 || i1 == ci3)
|
||||||
|
dcount++;
|
||||||
|
if (i2 == ci1 || i2 == ci2 || i2 == ci3)
|
||||||
|
dcount++;
|
||||||
|
if (i3 == ci1 || i3 == ci2 || i3 == ci3)
|
||||||
|
dcount++;
|
||||||
|
|
||||||
|
return dcount == 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getMesh(ConvexResult cr, VertexPool vc, List<int> indices)
|
||||||
|
{
|
||||||
|
List<int> src = cr.HullIndices;
|
||||||
|
|
||||||
|
for (int i = 0; i < src.Count / 3; i++)
|
||||||
|
{
|
||||||
|
int i1 = src[i * 3 + 0];
|
||||||
|
int i2 = src[i * 3 + 1];
|
||||||
|
int i3 = src[i * 3 + 2];
|
||||||
|
|
||||||
|
float3 p1 = cr.HullVertices[i1];
|
||||||
|
float3 p2 = cr.HullVertices[i2];
|
||||||
|
float3 p3 = cr.HullVertices[i3];
|
||||||
|
|
||||||
|
i1 = vc.getIndex(p1);
|
||||||
|
i2 = vc.getIndex(p2);
|
||||||
|
i3 = vc.getIndex(p3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CHull canMerge(CHull a, CHull b)
|
||||||
|
{
|
||||||
|
if (!a.overlap(b)) // if their AABB's (with a little slop) don't overlap, then return.
|
||||||
|
return null;
|
||||||
|
|
||||||
|
CHull ret = null;
|
||||||
|
|
||||||
|
// ok..we are going to combine both meshes into a single mesh
|
||||||
|
// and then we are going to compute the concavity...
|
||||||
|
|
||||||
|
VertexPool vc = new VertexPool();
|
||||||
|
|
||||||
|
List<int> indices = new List<int>();
|
||||||
|
|
||||||
|
getMesh(a.mResult, vc, indices);
|
||||||
|
getMesh(b.mResult, vc, indices);
|
||||||
|
|
||||||
|
int vcount = vc.GetSize();
|
||||||
|
List<float3> vertices = vc.GetVertices();
|
||||||
|
int tcount = indices.Count / 3;
|
||||||
|
|
||||||
|
//don't do anything if hull is empty
|
||||||
|
if (tcount == 0)
|
||||||
|
{
|
||||||
|
vc.Clear();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
HullResult hresult = new HullResult();
|
||||||
|
HullDesc desc = new HullDesc();
|
||||||
|
|
||||||
|
desc.SetHullFlag(HullFlag.QF_TRIANGLES);
|
||||||
|
desc.Vertices = vertices;
|
||||||
|
|
||||||
|
HullError hret = HullUtils.CreateConvexHull(desc, ref hresult);
|
||||||
|
|
||||||
|
if (hret == HullError.QE_OK)
|
||||||
|
{
|
||||||
|
float combineVolume = Concavity.computeMeshVolume(hresult.OutputVertices, hresult.Indices);
|
||||||
|
float sumVolume = a.mVolume + b.mVolume;
|
||||||
|
|
||||||
|
float percent = (sumVolume * 100) / combineVolume;
|
||||||
|
if (percent >= (100.0f - MERGE_PERCENT))
|
||||||
|
{
|
||||||
|
ConvexResult cr = new ConvexResult(hresult.OutputVertices, hresult.Indices);
|
||||||
|
ret = new CHull(cr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vc.Clear();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool combineHulls()
|
||||||
|
{
|
||||||
|
bool combine = false;
|
||||||
|
|
||||||
|
sortChulls(mChulls); // sort the convex hulls, largest volume to least...
|
||||||
|
|
||||||
|
List<CHull> output = new List<CHull>(); // the output hulls...
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < mChulls.Count && !combine; ++i)
|
||||||
|
{
|
||||||
|
CHull cr = mChulls[i];
|
||||||
|
|
||||||
|
int j;
|
||||||
|
for (j = 0; j < mChulls.Count; j++)
|
||||||
|
{
|
||||||
|
CHull match = mChulls[j];
|
||||||
|
|
||||||
|
if (cr != match) // don't try to merge a hull with itself, that be stoopid
|
||||||
|
{
|
||||||
|
|
||||||
|
CHull merge = canMerge(cr, match); // if we can merge these two....
|
||||||
|
|
||||||
|
if (merge != null)
|
||||||
|
{
|
||||||
|
output.Add(merge);
|
||||||
|
|
||||||
|
++i;
|
||||||
|
while (i != mChulls.Count)
|
||||||
|
{
|
||||||
|
CHull cr2 = mChulls[i];
|
||||||
|
if (cr2 != match)
|
||||||
|
{
|
||||||
|
output.Add(cr2);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
cr.Dispose();
|
||||||
|
match.Dispose();
|
||||||
|
combine = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (combine)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
output.Add(cr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (combine)
|
||||||
|
{
|
||||||
|
mChulls.Clear();
|
||||||
|
mChulls = output;
|
||||||
|
output.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
return combine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int process(DecompDesc desc)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
MAXDEPTH = (int)desc.mDepth;
|
||||||
|
CONCAVE_PERCENT = desc.mCpercent;
|
||||||
|
MERGE_PERCENT = desc.mPpercent;
|
||||||
|
|
||||||
|
ConvexDecomposition.calcConvexDecomposition(desc.mVertices, desc.mIndices, ConvexDecompResult, 0f, 0, MAXDEPTH, CONCAVE_PERCENT, MERGE_PERCENT);
|
||||||
|
|
||||||
|
while (combineHulls()) // keep combinging hulls until I can't combine any more...
|
||||||
|
;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < mChulls.Count; i++)
|
||||||
|
{
|
||||||
|
CHull cr = mChulls[i];
|
||||||
|
|
||||||
|
// before we hand it back to the application, we need to regenerate the hull based on the
|
||||||
|
// limits given by the user.
|
||||||
|
|
||||||
|
ConvexResult c = cr.mResult; // the high resolution hull...
|
||||||
|
|
||||||
|
HullResult result = new HullResult();
|
||||||
|
HullDesc hdesc = new HullDesc();
|
||||||
|
|
||||||
|
hdesc.SetHullFlag(HullFlag.QF_TRIANGLES);
|
||||||
|
|
||||||
|
hdesc.Vertices = c.HullVertices;
|
||||||
|
hdesc.MaxVertices = desc.mMaxVertices; // maximum number of vertices allowed in the output
|
||||||
|
|
||||||
|
if (desc.mSkinWidth != 0f)
|
||||||
|
{
|
||||||
|
hdesc.SkinWidth = desc.mSkinWidth;
|
||||||
|
hdesc.SetHullFlag(HullFlag.QF_SKIN_WIDTH); // do skin width computation.
|
||||||
|
}
|
||||||
|
|
||||||
|
HullError ret2 = HullUtils.CreateConvexHull(hdesc, ref result);
|
||||||
|
|
||||||
|
if (ret2 == HullError.QE_OK)
|
||||||
|
{
|
||||||
|
ConvexResult r = new ConvexResult(result.OutputVertices, result.Indices);
|
||||||
|
|
||||||
|
r.mHullVolume = Concavity.computeMeshVolume(result.OutputVertices, result.Indices); // the volume of the hull.
|
||||||
|
|
||||||
|
// compute the best fit OBB
|
||||||
|
//computeBestFitOBB(result.mNumOutputVertices, result.mOutputVertices, sizeof(float) * 3, r.mOBBSides, r.mOBBTransform);
|
||||||
|
|
||||||
|
//r.mOBBVolume = r.mOBBSides[0] * r.mOBBSides[1] * r.mOBBSides[2]; // compute the OBB volume.
|
||||||
|
|
||||||
|
//fm_getTranslation(r.mOBBTransform, r.mOBBCenter); // get the translation component of the 4x4 matrix.
|
||||||
|
|
||||||
|
//fm_matrixToQuat(r.mOBBTransform, r.mOBBOrientation); // extract the orientation as a quaternion.
|
||||||
|
|
||||||
|
//r.mSphereRadius = computeBoundingSphere(result.mNumOutputVertices, result.mOutputVertices, r.mSphereCenter);
|
||||||
|
//r.mSphereVolume = fm_sphereVolume(r.mSphereRadius);
|
||||||
|
|
||||||
|
mCallback(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = null;
|
||||||
|
cr.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mChulls.Count;
|
||||||
|
|
||||||
|
mChulls.Clear();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ConvexDecompResult(ConvexResult result)
|
||||||
|
{
|
||||||
|
CHull ch = new CHull(result);
|
||||||
|
mChulls.Add(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sortChulls(List<CHull> hulls)
|
||||||
|
{
|
||||||
|
hulls.Sort(delegate(CHull a, CHull b) { return a.mVolume.CompareTo(b.mVolume); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,200 @@
|
||||||
|
/* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Based on the convexdecomposition library from
|
||||||
|
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
|
||||||
|
{
|
||||||
|
public delegate void ConvexDecompositionCallback(ConvexResult result);
|
||||||
|
|
||||||
|
public class FaceTri
|
||||||
|
{
|
||||||
|
public float3 P1;
|
||||||
|
public float3 P2;
|
||||||
|
public float3 P3;
|
||||||
|
|
||||||
|
public FaceTri() { }
|
||||||
|
|
||||||
|
public FaceTri(List<float3> vertices, int i1, int i2, int i3)
|
||||||
|
{
|
||||||
|
P1 = new float3(vertices[i1]);
|
||||||
|
P2 = new float3(vertices[i2]);
|
||||||
|
P3 = new float3(vertices[i3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ConvexDecomposition
|
||||||
|
{
|
||||||
|
private static void addTri(VertexPool vl, List<int> list, float3 p1, float3 p2, float3 p3)
|
||||||
|
{
|
||||||
|
int i1 = vl.getIndex(p1);
|
||||||
|
int i2 = vl.getIndex(p2);
|
||||||
|
int i3 = vl.getIndex(p3);
|
||||||
|
|
||||||
|
// do *not* process degenerate triangles!
|
||||||
|
if ( i1 != i2 && i1 != i3 && i2 != i3 )
|
||||||
|
{
|
||||||
|
list.Add(i1);
|
||||||
|
list.Add(i2);
|
||||||
|
list.Add(i3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void calcConvexDecomposition(List<float3> vertices, List<int> indices, ConvexDecompositionCallback callback, float masterVolume, int depth,
|
||||||
|
int maxDepth, float concavePercent, float mergePercent)
|
||||||
|
{
|
||||||
|
float4 plane = new float4();
|
||||||
|
bool split = false;
|
||||||
|
|
||||||
|
if (depth < maxDepth)
|
||||||
|
{
|
||||||
|
float volume = 0f;
|
||||||
|
float c = Concavity.computeConcavity(vertices, indices, ref plane, ref volume);
|
||||||
|
|
||||||
|
if (depth == 0)
|
||||||
|
{
|
||||||
|
masterVolume = volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
float percent = (c * 100.0f) / masterVolume;
|
||||||
|
|
||||||
|
if (percent > concavePercent) // if great than 5% of the total volume is concave, go ahead and keep splitting.
|
||||||
|
{
|
||||||
|
split = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depth >= maxDepth || !split)
|
||||||
|
{
|
||||||
|
HullResult result = new HullResult();
|
||||||
|
HullDesc desc = new HullDesc();
|
||||||
|
|
||||||
|
desc.SetHullFlag(HullFlag.QF_TRIANGLES);
|
||||||
|
|
||||||
|
desc.Vertices = vertices;
|
||||||
|
|
||||||
|
HullError ret = HullUtils.CreateConvexHull(desc, ref result);
|
||||||
|
|
||||||
|
if (ret == HullError.QE_OK)
|
||||||
|
{
|
||||||
|
ConvexResult r = new ConvexResult(result.OutputVertices, result.Indices);
|
||||||
|
callback(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<int> ifront = new List<int>();
|
||||||
|
List<int> iback = new List<int>();
|
||||||
|
|
||||||
|
VertexPool vfront = new VertexPool();
|
||||||
|
VertexPool vback = new VertexPool();
|
||||||
|
|
||||||
|
// ok..now we are going to 'split' all of the input triangles against this plane!
|
||||||
|
for (int i = 0; i < indices.Count / 3; i++)
|
||||||
|
{
|
||||||
|
int i1 = indices[i * 3 + 0];
|
||||||
|
int i2 = indices[i * 3 + 1];
|
||||||
|
int i3 = indices[i * 3 + 2];
|
||||||
|
|
||||||
|
FaceTri t = new FaceTri(vertices, i1, i2, i3);
|
||||||
|
|
||||||
|
float3[] front = new float3[4];
|
||||||
|
float3[] back = new float3[4];
|
||||||
|
|
||||||
|
int fcount = 0;
|
||||||
|
int bcount = 0;
|
||||||
|
|
||||||
|
PlaneTriResult result = PlaneTri.planeTriIntersection(plane, t, 0.00001f, ref front, out fcount, ref back, out bcount);
|
||||||
|
|
||||||
|
if (fcount > 4 || bcount > 4)
|
||||||
|
{
|
||||||
|
result = PlaneTri.planeTriIntersection(plane, t, 0.00001f, ref front, out fcount, ref back, out bcount);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (result)
|
||||||
|
{
|
||||||
|
case PlaneTriResult.PTR_FRONT:
|
||||||
|
Debug.Assert(fcount == 3);
|
||||||
|
addTri(vfront, ifront, front[0], front[1], front[2]);
|
||||||
|
break;
|
||||||
|
case PlaneTriResult.PTR_BACK:
|
||||||
|
Debug.Assert(bcount == 3);
|
||||||
|
addTri(vback, iback, back[0], back[1], back[2]);
|
||||||
|
break;
|
||||||
|
case PlaneTriResult.PTR_SPLIT:
|
||||||
|
Debug.Assert(fcount >= 3 && fcount <= 4);
|
||||||
|
Debug.Assert(bcount >= 3 && bcount <= 4);
|
||||||
|
|
||||||
|
addTri(vfront, ifront, front[0], front[1], front[2]);
|
||||||
|
addTri(vback, iback, back[0], back[1], back[2]);
|
||||||
|
|
||||||
|
if (fcount == 4)
|
||||||
|
{
|
||||||
|
addTri(vfront, ifront, front[0], front[2], front[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bcount == 4)
|
||||||
|
{
|
||||||
|
addTri(vback, iback, back[0], back[2], back[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ok... here we recursively call
|
||||||
|
if (ifront.Count > 0)
|
||||||
|
{
|
||||||
|
int vcount = vfront.GetSize();
|
||||||
|
List<float3> vertices2 = vfront.GetVertices();
|
||||||
|
for (int i = 0; i < vertices2.Count; i++)
|
||||||
|
vertices2[i] = new float3(vertices2[i]);
|
||||||
|
int tcount = ifront.Count / 3;
|
||||||
|
|
||||||
|
calcConvexDecomposition(vertices2, ifront, callback, masterVolume, depth + 1, maxDepth, concavePercent, mergePercent);
|
||||||
|
}
|
||||||
|
|
||||||
|
ifront.Clear();
|
||||||
|
vfront.Clear();
|
||||||
|
|
||||||
|
if (iback.Count > 0)
|
||||||
|
{
|
||||||
|
int vcount = vback.GetSize();
|
||||||
|
List<float3> vertices2 = vback.GetVertices();
|
||||||
|
int tcount = iback.Count / 3;
|
||||||
|
|
||||||
|
calcConvexDecomposition(vertices2, iback, callback, masterVolume, depth + 1, maxDepth, concavePercent, mergePercent);
|
||||||
|
}
|
||||||
|
|
||||||
|
iback.Clear();
|
||||||
|
vback.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
/* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Based on the convexdecomposition library from
|
||||||
|
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
|
||||||
|
{
|
||||||
|
public class ConvexResult
|
||||||
|
{
|
||||||
|
public List<float3> HullVertices;
|
||||||
|
public List<int> HullIndices;
|
||||||
|
|
||||||
|
public float mHullVolume; // the volume of the convex hull.
|
||||||
|
|
||||||
|
//public float[] OBBSides = new float[3]; // the width, height and breadth of the best fit OBB
|
||||||
|
//public float[] OBBCenter = new float[3]; // the center of the OBB
|
||||||
|
//public float[] OBBOrientation = new float[4]; // the quaternion rotation of the OBB.
|
||||||
|
//public float[] OBBTransform = new float[16]; // the 4x4 transform of the OBB.
|
||||||
|
//public float OBBVolume; // the volume of the OBB
|
||||||
|
|
||||||
|
//public float SphereRadius; // radius and center of best fit sphere
|
||||||
|
//public float[] SphereCenter = new float[3];
|
||||||
|
//public float SphereVolume; // volume of the best fit sphere
|
||||||
|
|
||||||
|
public ConvexResult()
|
||||||
|
{
|
||||||
|
HullVertices = new List<float3>();
|
||||||
|
HullIndices = new List<int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConvexResult(List<float3> hvertices, List<int> hindices)
|
||||||
|
{
|
||||||
|
HullVertices = hvertices;
|
||||||
|
HullIndices = hindices;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConvexResult(ConvexResult r)
|
||||||
|
{
|
||||||
|
HullVertices = new List<float3>(r.HullVertices);
|
||||||
|
HullIndices = new List<int>(r.HullIndices);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
HullVertices = null;
|
||||||
|
HullIndices = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,171 @@
|
||||||
|
/* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Based on the convexdecomposition library from
|
||||||
|
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
|
||||||
|
{
|
||||||
|
public class HullResult
|
||||||
|
{
|
||||||
|
public bool Polygons = true; // true if indices represents polygons, false indices are triangles
|
||||||
|
public List<float3> OutputVertices = new List<float3>();
|
||||||
|
public List<int> Indices;
|
||||||
|
|
||||||
|
// If triangles, then indices are array indexes into the vertex list.
|
||||||
|
// If polygons, indices are in the form (number of points in face) (p1, p2, p3, ..) etc..
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PHullResult
|
||||||
|
{
|
||||||
|
public List<float3> Vertices = new List<float3>();
|
||||||
|
public List<int> Indices = new List<int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum HullFlag : int
|
||||||
|
{
|
||||||
|
QF_DEFAULT = 0,
|
||||||
|
QF_TRIANGLES = (1 << 0), // report results as triangles, not polygons.
|
||||||
|
QF_SKIN_WIDTH = (1 << 2) // extrude hull based on this skin width
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum HullError : int
|
||||||
|
{
|
||||||
|
QE_OK, // success!
|
||||||
|
QE_FAIL // failed.
|
||||||
|
}
|
||||||
|
|
||||||
|
public class HullDesc
|
||||||
|
{
|
||||||
|
public HullFlag Flags; // flags to use when generating the convex hull.
|
||||||
|
public List<float3> Vertices;
|
||||||
|
public float NormalEpsilon; // the epsilon for removing duplicates. This is a normalized value, if normalized bit is on.
|
||||||
|
public float SkinWidth;
|
||||||
|
public uint MaxVertices; // maximum number of vertices to be considered for the hull!
|
||||||
|
public uint MaxFaces;
|
||||||
|
|
||||||
|
public HullDesc()
|
||||||
|
{
|
||||||
|
Flags = HullFlag.QF_DEFAULT;
|
||||||
|
Vertices = new List<float3>();
|
||||||
|
NormalEpsilon = 0.001f;
|
||||||
|
MaxVertices = 4096;
|
||||||
|
MaxFaces = 4096;
|
||||||
|
SkinWidth = 0.01f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HullDesc(HullFlag flags, List<float3> vertices)
|
||||||
|
{
|
||||||
|
Flags = flags;
|
||||||
|
Vertices = new List<float3>(vertices);
|
||||||
|
NormalEpsilon = 0.001f;
|
||||||
|
MaxVertices = 4096;
|
||||||
|
MaxFaces = 4096;
|
||||||
|
SkinWidth = 0.01f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasHullFlag(HullFlag flag)
|
||||||
|
{
|
||||||
|
return (Flags & flag) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetHullFlag(HullFlag flag)
|
||||||
|
{
|
||||||
|
Flags |= flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearHullFlag(HullFlag flag)
|
||||||
|
{
|
||||||
|
Flags &= ~flag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ConvexH
|
||||||
|
{
|
||||||
|
public struct HalfEdge
|
||||||
|
{
|
||||||
|
public short ea; // the other half of the edge (index into edges list)
|
||||||
|
public byte v; // the vertex at the start of this edge (index into vertices list)
|
||||||
|
public byte p; // the facet on which this edge lies (index into facets list)
|
||||||
|
|
||||||
|
public HalfEdge(short _ea, byte _v, byte _p)
|
||||||
|
{
|
||||||
|
ea = _ea;
|
||||||
|
v = _v;
|
||||||
|
p = _p;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HalfEdge(HalfEdge e)
|
||||||
|
{
|
||||||
|
ea = e.ea;
|
||||||
|
v = e.v;
|
||||||
|
p = e.p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<float3> vertices = new List<float3>();
|
||||||
|
public List<HalfEdge> edges = new List<HalfEdge>();
|
||||||
|
public List<Plane> facets = new List<Plane>();
|
||||||
|
|
||||||
|
public ConvexH(int vertices_size, int edges_size, int facets_size)
|
||||||
|
{
|
||||||
|
vertices = new List<float3>(vertices_size);
|
||||||
|
edges = new List<HalfEdge>(edges_size);
|
||||||
|
facets = new List<Plane>(facets_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class VertFlag
|
||||||
|
{
|
||||||
|
public byte planetest;
|
||||||
|
public byte junk;
|
||||||
|
public byte undermap;
|
||||||
|
public byte overmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EdgeFlag
|
||||||
|
{
|
||||||
|
public byte planetest;
|
||||||
|
public byte fixes;
|
||||||
|
public short undermap;
|
||||||
|
public short overmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PlaneFlag
|
||||||
|
{
|
||||||
|
public byte undermap;
|
||||||
|
public byte overmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Coplanar
|
||||||
|
{
|
||||||
|
public ushort ea;
|
||||||
|
public byte v0;
|
||||||
|
public byte v1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
/* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Based on the convexdecomposition library from
|
||||||
|
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
|
||||||
|
{
|
||||||
|
public class HullTriangle : int3
|
||||||
|
{
|
||||||
|
public int3 n = new int3();
|
||||||
|
public int id;
|
||||||
|
public int vmax;
|
||||||
|
public float rise;
|
||||||
|
private List<HullTriangle> tris;
|
||||||
|
|
||||||
|
public HullTriangle(int a, int b, int c, List<HullTriangle> tris)
|
||||||
|
: base(a, b, c)
|
||||||
|
{
|
||||||
|
this.tris = tris;
|
||||||
|
|
||||||
|
n = new int3(-1, -1, -1);
|
||||||
|
id = tris.Count;
|
||||||
|
tris.Add(this);
|
||||||
|
vmax = -1;
|
||||||
|
rise = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Debug.Assert(tris[id] == this);
|
||||||
|
tris[id] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int neib(int a, int b)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
int i1 = (i + 1) % 3;
|
||||||
|
int i2 = (i + 2) % 3;
|
||||||
|
if ((this)[i] == a && (this)[i1] == b)
|
||||||
|
return n[i2];
|
||||||
|
if ((this)[i] == b && (this)[i1] == a)
|
||||||
|
return n[i2];
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Assert(false);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setneib(int a, int b, int value)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
int i1 = (i + 1) % 3;
|
||||||
|
int i2 = (i + 2) % 3;
|
||||||
|
if ((this)[i] == a && (this)[i1] == b)
|
||||||
|
{
|
||||||
|
n[i2] = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((this)[i] == b && (this)[i1] == a)
|
||||||
|
{
|
||||||
|
n[i2] = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,28 @@
|
||||||
|
ConvexDecompositionDotNet
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
The MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2010 Intel Corporation.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Based on the convexdecomposition library from
|
||||||
|
<http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
|
@ -0,0 +1,99 @@
|
||||||
|
/* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Based on the convexdecomposition library from
|
||||||
|
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
|
||||||
|
{
|
||||||
|
public class Plane
|
||||||
|
{
|
||||||
|
public float3 normal = new float3();
|
||||||
|
public float dist; // distance below origin - the D from plane equasion Ax+By+Cz+D=0
|
||||||
|
|
||||||
|
public Plane(float3 n, float d)
|
||||||
|
{
|
||||||
|
normal = new float3(n);
|
||||||
|
dist = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Plane(Plane p)
|
||||||
|
{
|
||||||
|
normal = new float3(p.normal);
|
||||||
|
dist = p.dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Plane()
|
||||||
|
{
|
||||||
|
dist = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Transform(float3 position, Quaternion orientation)
|
||||||
|
{
|
||||||
|
// Transforms the plane to the space defined by the
|
||||||
|
// given position/orientation
|
||||||
|
float3 newNormal = Quaternion.Inverse(orientation) * normal;
|
||||||
|
float3 origin = Quaternion.Inverse(orientation) * (-normal * dist - position);
|
||||||
|
|
||||||
|
normal = newNormal;
|
||||||
|
dist = -float3.dot(newNormal, origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return normal.GetHashCode() ^ dist.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
Plane p = obj as Plane;
|
||||||
|
if (p == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return this == p;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(Plane a, Plane b)
|
||||||
|
{
|
||||||
|
return (a.normal == b.normal && a.dist == b.dist);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(Plane a, Plane b)
|
||||||
|
{
|
||||||
|
return !(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Plane PlaneFlip(Plane plane)
|
||||||
|
{
|
||||||
|
return new Plane(-plane.normal, -plane.dist);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool coplanar(Plane a, Plane b)
|
||||||
|
{
|
||||||
|
return (a == b || a == PlaneFlip(b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,211 @@
|
||||||
|
/* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Based on the convexdecomposition library from
|
||||||
|
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
|
||||||
|
{
|
||||||
|
public enum PlaneTriResult : int
|
||||||
|
{
|
||||||
|
PTR_FRONT,
|
||||||
|
PTR_BACK,
|
||||||
|
PTR_SPLIT
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PlaneTri
|
||||||
|
{
|
||||||
|
private static float DistToPt(float3 p, float4 plane)
|
||||||
|
{
|
||||||
|
return p.x * plane.x + p.y * plane.y + p.z * plane.z + plane.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PlaneTriResult getSidePlane(float3 p, float4 plane, float epsilon)
|
||||||
|
{
|
||||||
|
float d = DistToPt(p, plane);
|
||||||
|
|
||||||
|
if ((d + epsilon) > 0f)
|
||||||
|
return PlaneTriResult.PTR_FRONT; // it is 'in front' within the provided epsilon value.
|
||||||
|
|
||||||
|
return PlaneTriResult.PTR_BACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void add(float3 p, float3[] dest, ref int pcount)
|
||||||
|
{
|
||||||
|
dest[pcount++] = new float3(p);
|
||||||
|
Debug.Assert(pcount <= 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// assumes that the points are on opposite sides of the plane!
|
||||||
|
private static void intersect(float3 p1, float3 p2, float3 split, float4 plane)
|
||||||
|
{
|
||||||
|
float dp1 = DistToPt(p1, plane);
|
||||||
|
float[] dir = new float[3];
|
||||||
|
|
||||||
|
dir[0] = p2[0] - p1[0];
|
||||||
|
dir[1] = p2[1] - p1[1];
|
||||||
|
dir[2] = p2[2] - p1[2];
|
||||||
|
|
||||||
|
float dot1 = dir[0] * plane[0] + dir[1] * plane[1] + dir[2] * plane[2];
|
||||||
|
float dot2 = dp1 - plane[3];
|
||||||
|
|
||||||
|
float t = -(plane[3] + dot2) / dot1;
|
||||||
|
|
||||||
|
split.x = (dir[0] * t) + p1[0];
|
||||||
|
split.y = (dir[1] * t) + p1[1];
|
||||||
|
split.z = (dir[2] * t) + p1[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PlaneTriResult planeTriIntersection(float4 plane, FaceTri triangle, float epsilon, ref float3[] front, out int fcount, ref float3[] back, out int bcount)
|
||||||
|
{
|
||||||
|
fcount = 0;
|
||||||
|
bcount = 0;
|
||||||
|
|
||||||
|
// get the three vertices of the triangle.
|
||||||
|
float3 p1 = triangle.P1;
|
||||||
|
float3 p2 = triangle.P2;
|
||||||
|
float3 p3 = triangle.P3;
|
||||||
|
|
||||||
|
PlaneTriResult r1 = getSidePlane(p1, plane, epsilon); // compute the side of the plane each vertex is on
|
||||||
|
PlaneTriResult r2 = getSidePlane(p2, plane, epsilon);
|
||||||
|
PlaneTriResult r3 = getSidePlane(p3, plane, epsilon);
|
||||||
|
|
||||||
|
if (r1 == r2 && r1 == r3) // if all three vertices are on the same side of the plane.
|
||||||
|
{
|
||||||
|
if (r1 == PlaneTriResult.PTR_FRONT) // if all three are in front of the plane, then copy to the 'front' output triangle.
|
||||||
|
{
|
||||||
|
add(p1, front, ref fcount);
|
||||||
|
add(p2, front, ref fcount);
|
||||||
|
add(p3, front, ref fcount);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
add(p1, back, ref bcount); // if all three are in 'back' then copy to the 'back' output triangle.
|
||||||
|
add(p2, back, ref bcount);
|
||||||
|
add(p3, back, ref bcount);
|
||||||
|
}
|
||||||
|
return r1; // if all three points are on the same side of the plane return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// ok.. we need to split the triangle at the plane.
|
||||||
|
|
||||||
|
// First test ray segment P1 to P2
|
||||||
|
if (r1 == r2) // if these are both on the same side...
|
||||||
|
{
|
||||||
|
if (r1 == PlaneTriResult.PTR_FRONT)
|
||||||
|
{
|
||||||
|
add(p1, front, ref fcount);
|
||||||
|
add(p2, front, ref fcount);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
add(p1, back, ref bcount);
|
||||||
|
add(p2, back, ref bcount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float3 split = new float3();
|
||||||
|
intersect(p1, p2, split, plane);
|
||||||
|
|
||||||
|
if (r1 == PlaneTriResult.PTR_FRONT)
|
||||||
|
{
|
||||||
|
|
||||||
|
add(p1, front, ref fcount);
|
||||||
|
add(split, front, ref fcount);
|
||||||
|
|
||||||
|
add(split, back, ref bcount);
|
||||||
|
add(p2, back, ref bcount);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
add(p1, back, ref bcount);
|
||||||
|
add(split, back, ref bcount);
|
||||||
|
|
||||||
|
add(split, front, ref fcount);
|
||||||
|
add(p2, front, ref fcount);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next test ray segment P2 to P3
|
||||||
|
if (r2 == r3) // if these are both on the same side...
|
||||||
|
{
|
||||||
|
if (r3 == PlaneTriResult.PTR_FRONT)
|
||||||
|
{
|
||||||
|
add(p3, front, ref fcount);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
add(p3, back, ref bcount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float3 split = new float3(); // split the point
|
||||||
|
intersect(p2, p3, split, plane);
|
||||||
|
|
||||||
|
if (r3 == PlaneTriResult.PTR_FRONT)
|
||||||
|
{
|
||||||
|
add(split, front, ref fcount);
|
||||||
|
add(split, back, ref bcount);
|
||||||
|
|
||||||
|
add(p3, front, ref fcount);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
add(split, front, ref fcount);
|
||||||
|
add(split, back, ref bcount);
|
||||||
|
|
||||||
|
add(p3, back, ref bcount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next test ray segment P3 to P1
|
||||||
|
if (r3 != r1) // if these are both on the same side...
|
||||||
|
{
|
||||||
|
float3 split = new float3(); // split the point
|
||||||
|
intersect(p3, p1, split, plane);
|
||||||
|
|
||||||
|
if (r1 == PlaneTriResult.PTR_FRONT)
|
||||||
|
{
|
||||||
|
add(split, front, ref fcount);
|
||||||
|
add(split, back, ref bcount);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
add(split, front, ref fcount);
|
||||||
|
add(split, back, ref bcount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PlaneTriResult.PTR_SPLIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,209 @@
|
||||||
|
/* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Based on the convexdecomposition library from
|
||||||
|
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
|
||||||
|
{
|
||||||
|
public class Quaternion : float4
|
||||||
|
{
|
||||||
|
public Quaternion()
|
||||||
|
{
|
||||||
|
x = y = z = 0.0f;
|
||||||
|
w = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Quaternion(float3 v, float t)
|
||||||
|
{
|
||||||
|
v = float3.normalize(v);
|
||||||
|
w = (float)Math.Cos(t / 2.0f);
|
||||||
|
v = v * (float)Math.Sin(t / 2.0f);
|
||||||
|
x = v.x;
|
||||||
|
y = v.y;
|
||||||
|
z = v.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Quaternion(float _x, float _y, float _z, float _w)
|
||||||
|
{
|
||||||
|
x = _x;
|
||||||
|
y = _y;
|
||||||
|
z = _z;
|
||||||
|
w = _w;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float angle()
|
||||||
|
{
|
||||||
|
return (float)Math.Acos(w) * 2.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float3 axis()
|
||||||
|
{
|
||||||
|
float3 a = new float3(x, y, z);
|
||||||
|
if (Math.Abs(angle()) < 0.0000001f)
|
||||||
|
return new float3(1f, 0f, 0f);
|
||||||
|
return a * (1 / (float)Math.Sin(angle() / 2.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
public float3 xdir()
|
||||||
|
{
|
||||||
|
return new float3(1 - 2 * (y * y + z * z), 2 * (x * y + w * z), 2 * (x * z - w * y));
|
||||||
|
}
|
||||||
|
|
||||||
|
public float3 ydir()
|
||||||
|
{
|
||||||
|
return new float3(2 * (x * y - w * z), 1 - 2 * (x * x + z * z), 2 * (y * z + w * x));
|
||||||
|
}
|
||||||
|
|
||||||
|
public float3 zdir()
|
||||||
|
{
|
||||||
|
return new float3(2 * (x * z + w * y), 2 * (y * z - w * x), 1 - 2 * (x * x + y * y));
|
||||||
|
}
|
||||||
|
|
||||||
|
public float3x3 getmatrix()
|
||||||
|
{
|
||||||
|
return new float3x3(xdir(), ydir(), zdir());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator float3x3(Quaternion q)
|
||||||
|
{
|
||||||
|
return q.getmatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Quaternion operator *(Quaternion a, Quaternion b)
|
||||||
|
{
|
||||||
|
Quaternion c = new Quaternion();
|
||||||
|
c.w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z;
|
||||||
|
c.x = a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y;
|
||||||
|
c.y = a.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x;
|
||||||
|
c.z = a.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3 operator *(Quaternion q, float3 v)
|
||||||
|
{
|
||||||
|
// The following is equivalent to:
|
||||||
|
//return (q.getmatrix() * v);
|
||||||
|
float qx2 = q.x * q.x;
|
||||||
|
float qy2 = q.y * q.y;
|
||||||
|
float qz2 = q.z * q.z;
|
||||||
|
|
||||||
|
float qxqy = q.x * q.y;
|
||||||
|
float qxqz = q.x * q.z;
|
||||||
|
float qxqw = q.x * q.w;
|
||||||
|
float qyqz = q.y * q.z;
|
||||||
|
float qyqw = q.y * q.w;
|
||||||
|
float qzqw = q.z * q.w;
|
||||||
|
return new float3((1 - 2 * (qy2 + qz2)) * v.x + (2 * (qxqy - qzqw)) * v.y + (2 * (qxqz + qyqw)) * v.z, (2 * (qxqy + qzqw)) * v.x + (1 - 2 * (qx2 + qz2)) * v.y + (2 * (qyqz - qxqw)) * v.z, (2 * (qxqz - qyqw)) * v.x + (2 * (qyqz + qxqw)) * v.y + (1 - 2 * (qx2 + qy2)) * v.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Quaternion operator +(Quaternion a, Quaternion b)
|
||||||
|
{
|
||||||
|
return new Quaternion(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Quaternion operator *(Quaternion a, float b)
|
||||||
|
{
|
||||||
|
return new Quaternion(a.x *b, a.y *b, a.z *b, a.w *b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Quaternion normalize(Quaternion a)
|
||||||
|
{
|
||||||
|
float m = (float)Math.Sqrt(a.w * a.w + a.x * a.x + a.y * a.y + a.z * a.z);
|
||||||
|
if (m < 0.000000001f)
|
||||||
|
{
|
||||||
|
a.w = 1;
|
||||||
|
a.x = a.y = a.z = 0;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
return a * (1f / m);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float dot(Quaternion a, Quaternion b)
|
||||||
|
{
|
||||||
|
return (a.w * b.w + a.x * b.x + a.y * b.y + a.z * b.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Quaternion slerp(Quaternion a, Quaternion b, float interp)
|
||||||
|
{
|
||||||
|
if (dot(a, b) < 0.0)
|
||||||
|
{
|
||||||
|
a.w = -a.w;
|
||||||
|
a.x = -a.x;
|
||||||
|
a.y = -a.y;
|
||||||
|
a.z = -a.z;
|
||||||
|
}
|
||||||
|
float d = dot(a, b);
|
||||||
|
if (d >= 1.0)
|
||||||
|
{
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
float theta = (float)Math.Acos(d);
|
||||||
|
if (theta == 0.0f)
|
||||||
|
{
|
||||||
|
return (a);
|
||||||
|
}
|
||||||
|
return a * ((float)Math.Sin(theta - interp * theta) / (float)Math.Sin(theta)) + b * ((float)Math.Sin(interp * theta) / (float)Math.Sin(theta));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Quaternion Interpolate(Quaternion q0, Quaternion q1, float alpha)
|
||||||
|
{
|
||||||
|
return slerp(q0, q1, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Quaternion Inverse(Quaternion q)
|
||||||
|
{
|
||||||
|
return new Quaternion(-q.x, -q.y, -q.z, q.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Quaternion YawPitchRoll(float yaw, float pitch, float roll)
|
||||||
|
{
|
||||||
|
roll *= (3.14159264f / 180.0f);
|
||||||
|
yaw *= (3.14159264f / 180.0f);
|
||||||
|
pitch *= (3.14159264f / 180.0f);
|
||||||
|
return new Quaternion(new float3(0.0f, 0.0f, 1.0f), yaw) * new Quaternion(new float3(1.0f, 0.0f, 0.0f), pitch) * new Quaternion(new float3(0.0f, 1.0f, 0.0f), roll);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float Yaw(Quaternion q)
|
||||||
|
{
|
||||||
|
float3 v = q.ydir();
|
||||||
|
return (v.y == 0.0 && v.x == 0.0) ? 0.0f : (float)Math.Atan2(-v.x, v.y) * (180.0f / 3.14159264f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float Pitch(Quaternion q)
|
||||||
|
{
|
||||||
|
float3 v = q.ydir();
|
||||||
|
return (float)Math.Atan2(v.z, Math.Sqrt(v.x * v.x + v.y * v.y)) * (180.0f / 3.14159264f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float Roll(Quaternion q)
|
||||||
|
{
|
||||||
|
q = new Quaternion(new float3(0.0f, 0.0f, 1.0f), -Yaw(q) * (3.14159264f / 180.0f)) * q;
|
||||||
|
q = new Quaternion(new float3(1.0f, 0.0f, 0.0f), -Pitch(q) * (3.14159264f / 180.0f)) * q;
|
||||||
|
return (float)Math.Atan2(-q.xdir().z, q.xdir().x) * (180.0f / 3.14159264f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
ConvexDecompositionDotNet
|
||||||
|
=========================
|
||||||
|
|
||||||
|
A C# port of the ConvexDecomposition library by John W. Ratcliff and Stan Melax.
|
||||||
|
The original C++ version is available at <http://codesuppository.googlecode.com/>.
|
||||||
|
See the blog post at <http://codesuppository.blogspot.com/2006/08/approximate-convexdecomposition.html>
|
||||||
|
for a thorough explanation of generating convex hulls from concave meshes.
|
|
@ -0,0 +1,265 @@
|
||||||
|
/* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Based on the convexdecomposition library from
|
||||||
|
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
|
||||||
|
{
|
||||||
|
public class Rect3d
|
||||||
|
{
|
||||||
|
public float[] mMin = new float[3];
|
||||||
|
public float[] mMax = new float[3];
|
||||||
|
|
||||||
|
public Rect3d()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rect3d(float[] bmin, float[] bmax)
|
||||||
|
{
|
||||||
|
mMin[0] = bmin[0];
|
||||||
|
mMin[1] = bmin[1];
|
||||||
|
mMin[2] = bmin[2];
|
||||||
|
|
||||||
|
mMax[0] = bmax[0];
|
||||||
|
mMax[1] = bmax[1];
|
||||||
|
mMax[2] = bmax[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetMin(float[] bmin)
|
||||||
|
{
|
||||||
|
mMin[0] = bmin[0];
|
||||||
|
mMin[1] = bmin[1];
|
||||||
|
mMin[2] = bmin[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetMax(float[] bmax)
|
||||||
|
{
|
||||||
|
mMax[0] = bmax[0];
|
||||||
|
mMax[1] = bmax[1];
|
||||||
|
mMax[2] = bmax[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetMin(float x, float y, float z)
|
||||||
|
{
|
||||||
|
mMin[0] = x;
|
||||||
|
mMin[1] = y;
|
||||||
|
mMin[2] = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetMax(float x, float y, float z)
|
||||||
|
{
|
||||||
|
mMax[0] = x;
|
||||||
|
mMax[1] = y;
|
||||||
|
mMax[2] = z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SplitPlane
|
||||||
|
{
|
||||||
|
public static bool computeSplitPlane(List<float3> vertices, List<int> indices, ref float4 plane)
|
||||||
|
{
|
||||||
|
float[] bmin = { Single.MaxValue, Single.MaxValue, Single.MaxValue };
|
||||||
|
float[] bmax = { Single.MinValue, Single.MinValue, Single.MinValue };
|
||||||
|
|
||||||
|
for (int i = 0; i < vertices.Count; i++)
|
||||||
|
{
|
||||||
|
float3 p = vertices[i];
|
||||||
|
|
||||||
|
if (p[0] < bmin[0])
|
||||||
|
bmin[0] = p[0];
|
||||||
|
if (p[1] < bmin[1])
|
||||||
|
bmin[1] = p[1];
|
||||||
|
if (p[2] < bmin[2])
|
||||||
|
bmin[2] = p[2];
|
||||||
|
|
||||||
|
if (p[0] > bmax[0])
|
||||||
|
bmax[0] = p[0];
|
||||||
|
if (p[1] > bmax[1])
|
||||||
|
bmax[1] = p[1];
|
||||||
|
if (p[2] > bmax[2])
|
||||||
|
bmax[2] = p[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
float dx = bmax[0] - bmin[0];
|
||||||
|
float dy = bmax[1] - bmin[1];
|
||||||
|
float dz = bmax[2] - bmin[2];
|
||||||
|
|
||||||
|
float laxis = dx;
|
||||||
|
|
||||||
|
int axis = 0;
|
||||||
|
|
||||||
|
if (dy > dx)
|
||||||
|
{
|
||||||
|
axis = 1;
|
||||||
|
laxis = dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dz > dx && dz > dy)
|
||||||
|
{
|
||||||
|
axis = 2;
|
||||||
|
laxis = dz;
|
||||||
|
}
|
||||||
|
|
||||||
|
float[] p1 = new float[3];
|
||||||
|
float[] p2 = new float[3];
|
||||||
|
float[] p3 = new float[3];
|
||||||
|
|
||||||
|
p3[0] = p2[0] = p1[0] = bmin[0] + dx * 0.5f;
|
||||||
|
p3[1] = p2[1] = p1[1] = bmin[1] + dy * 0.5f;
|
||||||
|
p3[2] = p2[2] = p1[2] = bmin[2] + dz * 0.5f;
|
||||||
|
|
||||||
|
Rect3d b = new Rect3d(bmin, bmax);
|
||||||
|
|
||||||
|
Rect3d b1 = new Rect3d();
|
||||||
|
Rect3d b2 = new Rect3d();
|
||||||
|
|
||||||
|
splitRect(axis, b, b1, b2, p1);
|
||||||
|
|
||||||
|
switch (axis)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
p2[1] = bmin[1];
|
||||||
|
p2[2] = bmin[2];
|
||||||
|
|
||||||
|
if (dz > dy)
|
||||||
|
{
|
||||||
|
p3[1] = bmax[1];
|
||||||
|
p3[2] = bmin[2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p3[1] = bmin[1];
|
||||||
|
p3[2] = bmax[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
p2[0] = bmin[0];
|
||||||
|
p2[2] = bmin[2];
|
||||||
|
|
||||||
|
if (dx > dz)
|
||||||
|
{
|
||||||
|
p3[0] = bmax[0];
|
||||||
|
p3[2] = bmin[2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p3[0] = bmin[0];
|
||||||
|
p3[2] = bmax[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
p2[0] = bmin[0];
|
||||||
|
p2[1] = bmin[1];
|
||||||
|
|
||||||
|
if (dx > dy)
|
||||||
|
{
|
||||||
|
p3[0] = bmax[0];
|
||||||
|
p3[1] = bmin[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p3[0] = bmin[0];
|
||||||
|
p3[1] = bmax[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
computePlane(p1, p2, p3, plane);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void computePlane(float[] A, float[] B, float[] C, float4 plane)
|
||||||
|
{
|
||||||
|
float vx = (B[0] - C[0]);
|
||||||
|
float vy = (B[1] - C[1]);
|
||||||
|
float vz = (B[2] - C[2]);
|
||||||
|
|
||||||
|
float wx = (A[0] - B[0]);
|
||||||
|
float wy = (A[1] - B[1]);
|
||||||
|
float wz = (A[2] - B[2]);
|
||||||
|
|
||||||
|
float vw_x = vy * wz - vz * wy;
|
||||||
|
float vw_y = vz * wx - vx * wz;
|
||||||
|
float vw_z = vx * wy - vy * wx;
|
||||||
|
|
||||||
|
float mag = (float)Math.Sqrt((vw_x * vw_x) + (vw_y * vw_y) + (vw_z * vw_z));
|
||||||
|
|
||||||
|
if (mag < 0.000001f)
|
||||||
|
{
|
||||||
|
mag = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mag = 1.0f / mag;
|
||||||
|
}
|
||||||
|
|
||||||
|
float x = vw_x * mag;
|
||||||
|
float y = vw_y * mag;
|
||||||
|
float z = vw_z * mag;
|
||||||
|
|
||||||
|
float D = 0.0f - ((x * A[0]) + (y * A[1]) + (z * A[2]));
|
||||||
|
|
||||||
|
plane.x = x;
|
||||||
|
plane.y = y;
|
||||||
|
plane.z = z;
|
||||||
|
plane.w = D;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void splitRect(int axis, Rect3d source, Rect3d b1, Rect3d b2, float[] midpoint)
|
||||||
|
{
|
||||||
|
switch (axis)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
b1.SetMin(source.mMin);
|
||||||
|
b1.SetMax(midpoint[0], source.mMax[1], source.mMax[2]);
|
||||||
|
|
||||||
|
b2.SetMin(midpoint[0], source.mMin[1], source.mMin[2]);
|
||||||
|
b2.SetMax(source.mMax);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
b1.SetMin(source.mMin);
|
||||||
|
b1.SetMax(source.mMax[0], midpoint[1], source.mMax[2]);
|
||||||
|
|
||||||
|
b2.SetMin(source.mMin[0], midpoint[1], source.mMin[2]);
|
||||||
|
b2.SetMax(source.mMax);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
b1.SetMin(source.mMin);
|
||||||
|
b1.SetMax(source.mMax[0], source.mMax[1], midpoint[2]);
|
||||||
|
|
||||||
|
b2.SetMin(source.mMin[0], source.mMin[1], midpoint[2]);
|
||||||
|
b2.SetMax(source.mMax);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
/* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Based on the convexdecomposition library from
|
||||||
|
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
|
||||||
|
{
|
||||||
|
public class VertexPool
|
||||||
|
{
|
||||||
|
private List<float3> mVertices = new List<float3>();
|
||||||
|
private Dictionary<float3, int> mIndices = new Dictionary<float3, int>();
|
||||||
|
|
||||||
|
public int getIndex(float3 vtx)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
if (mIndices.TryGetValue(vtx, out idx))
|
||||||
|
return idx;
|
||||||
|
|
||||||
|
idx = mVertices.Count;
|
||||||
|
mVertices.Add(vtx);
|
||||||
|
mIndices.Add(vtx, idx);
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float3 Get(int idx)
|
||||||
|
{
|
||||||
|
return mVertices[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetSize()
|
||||||
|
{
|
||||||
|
return mVertices.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<float3> GetVertices()
|
||||||
|
{
|
||||||
|
return mVertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
mVertices.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
/* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Based on the convexdecomposition library from
|
||||||
|
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
|
||||||
|
{
|
||||||
|
public class float2
|
||||||
|
{
|
||||||
|
public float x;
|
||||||
|
public float y;
|
||||||
|
|
||||||
|
public float2()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public float2(float _x, float _y)
|
||||||
|
{
|
||||||
|
x = _x;
|
||||||
|
y = _y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float this[int i]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 0: return x;
|
||||||
|
case 1: return y;
|
||||||
|
}
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float2 operator -(float2 a, float2 b)
|
||||||
|
{
|
||||||
|
return new float2(a.x - b.x, a.y - b.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float2 operator +(float2 a, float2 b)
|
||||||
|
{
|
||||||
|
return new float2(a.x + b.x, a.y + b.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,444 @@
|
||||||
|
/* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Based on the convexdecomposition library from
|
||||||
|
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
|
||||||
|
{
|
||||||
|
public class float3 : IEquatable<float3>
|
||||||
|
{
|
||||||
|
public float x;
|
||||||
|
public float y;
|
||||||
|
public float z;
|
||||||
|
|
||||||
|
public float3()
|
||||||
|
{
|
||||||
|
x = 0;
|
||||||
|
y = 0;
|
||||||
|
z = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float3(float _x, float _y, float _z)
|
||||||
|
{
|
||||||
|
x = _x;
|
||||||
|
y = _y;
|
||||||
|
z = _z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float3(float3 f)
|
||||||
|
{
|
||||||
|
x = f.x;
|
||||||
|
y = f.y;
|
||||||
|
z = f.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float this[int i]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 0: return x;
|
||||||
|
case 1: return y;
|
||||||
|
case 2: return z;
|
||||||
|
}
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Distance(float3 a)
|
||||||
|
{
|
||||||
|
float3 d = new float3(a.x - x, a.y - y, a.z - z);
|
||||||
|
return d.Length();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Distance2(float3 a)
|
||||||
|
{
|
||||||
|
float dx = a.x - x;
|
||||||
|
float dy = a.y - y;
|
||||||
|
float dz = a.z - z;
|
||||||
|
return dx * dx + dy * dy + dz * dz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Length()
|
||||||
|
{
|
||||||
|
return (float)Math.Sqrt(x * x + y * y + z * z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Area(float3 p1, float3 p2)
|
||||||
|
{
|
||||||
|
float A = Partial(p1);
|
||||||
|
A += p1.Partial(p2);
|
||||||
|
A += p2.Partial(this);
|
||||||
|
return A * 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Partial(float3 p)
|
||||||
|
{
|
||||||
|
return (x * p.y) - (p.x * y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given a point and a line (defined by two points), compute the closest point
|
||||||
|
// in the line. (The line is treated as infinitely long.)
|
||||||
|
public void NearestPointInLine(float3 point, float3 line0, float3 line1)
|
||||||
|
{
|
||||||
|
float3 nearestPoint = new float3();
|
||||||
|
float3 lineDelta = line1 - line0;
|
||||||
|
|
||||||
|
// Handle degenerate lines
|
||||||
|
if (lineDelta == float3.Zero)
|
||||||
|
{
|
||||||
|
nearestPoint = line0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float delta = float3.dot(point - line0, lineDelta) / float3.dot(lineDelta, lineDelta);
|
||||||
|
nearestPoint = line0 + lineDelta * delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.x = nearestPoint.x;
|
||||||
|
this.y = nearestPoint.y;
|
||||||
|
this.z = nearestPoint.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given a point and a line segment (defined by two points), compute the closest point
|
||||||
|
// in the line. Cap the point at the endpoints of the line segment.
|
||||||
|
public void NearestPointInLineSegment(float3 point, float3 line0, float3 line1)
|
||||||
|
{
|
||||||
|
float3 nearestPoint = new float3();
|
||||||
|
float3 lineDelta = line1 - line0;
|
||||||
|
|
||||||
|
// Handle degenerate lines
|
||||||
|
if (lineDelta == Zero)
|
||||||
|
{
|
||||||
|
nearestPoint = line0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float delta = float3.dot(point - line0, lineDelta) / float3.dot(lineDelta, lineDelta);
|
||||||
|
|
||||||
|
// Clamp the point to conform to the segment's endpoints
|
||||||
|
if (delta < 0)
|
||||||
|
delta = 0;
|
||||||
|
else if (delta > 1)
|
||||||
|
delta = 1;
|
||||||
|
|
||||||
|
nearestPoint = line0 + lineDelta * delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.x = nearestPoint.x;
|
||||||
|
this.y = nearestPoint.y;
|
||||||
|
this.z = nearestPoint.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given a point and a triangle (defined by three points), compute the closest point
|
||||||
|
// in the triangle. Clamp the point so it's confined to the area of the triangle.
|
||||||
|
public void NearestPointInTriangle(float3 point, float3 triangle0, float3 triangle1, float3 triangle2)
|
||||||
|
{
|
||||||
|
float3 nearestPoint = new float3();
|
||||||
|
|
||||||
|
float3 lineDelta0 = triangle1 - triangle0;
|
||||||
|
float3 lineDelta1 = triangle2 - triangle0;
|
||||||
|
|
||||||
|
// Handle degenerate triangles
|
||||||
|
if ((lineDelta0 == Zero) || (lineDelta1 == Zero))
|
||||||
|
{
|
||||||
|
nearestPoint.NearestPointInLineSegment(point, triangle1, triangle2);
|
||||||
|
}
|
||||||
|
else if (lineDelta0 == lineDelta1)
|
||||||
|
{
|
||||||
|
nearestPoint.NearestPointInLineSegment(point, triangle0, triangle1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float3[] axis = new float3[3] { new float3(), new float3(), new float3() };
|
||||||
|
axis[0].NearestPointInLine(triangle0, triangle1, triangle2);
|
||||||
|
axis[1].NearestPointInLine(triangle1, triangle0, triangle2);
|
||||||
|
axis[2].NearestPointInLine(triangle2, triangle0, triangle1);
|
||||||
|
|
||||||
|
float3 axisDot = new float3();
|
||||||
|
axisDot.x = dot(triangle0 - axis[0], point - axis[0]);
|
||||||
|
axisDot.y = dot(triangle1 - axis[1], point - axis[1]);
|
||||||
|
axisDot.z = dot(triangle2 - axis[2], point - axis[2]);
|
||||||
|
|
||||||
|
bool bForce = true;
|
||||||
|
float bestMagnitude2 = 0;
|
||||||
|
float closeMagnitude2;
|
||||||
|
float3 closePoint = new float3();
|
||||||
|
|
||||||
|
if (axisDot.x < 0f)
|
||||||
|
{
|
||||||
|
closePoint.NearestPointInLineSegment(point, triangle1, triangle2);
|
||||||
|
closeMagnitude2 = point.Distance2(closePoint);
|
||||||
|
if (bForce || (bestMagnitude2 > closeMagnitude2))
|
||||||
|
{
|
||||||
|
bForce = false;
|
||||||
|
bestMagnitude2 = closeMagnitude2;
|
||||||
|
nearestPoint = closePoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (axisDot.y < 0f)
|
||||||
|
{
|
||||||
|
closePoint.NearestPointInLineSegment(point, triangle0, triangle2);
|
||||||
|
closeMagnitude2 = point.Distance2(closePoint);
|
||||||
|
if (bForce || (bestMagnitude2 > closeMagnitude2))
|
||||||
|
{
|
||||||
|
bForce = false;
|
||||||
|
bestMagnitude2 = closeMagnitude2;
|
||||||
|
nearestPoint = closePoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (axisDot.z < 0f)
|
||||||
|
{
|
||||||
|
closePoint.NearestPointInLineSegment(point, triangle0, triangle1);
|
||||||
|
closeMagnitude2 = point.Distance2(closePoint);
|
||||||
|
if (bForce || (bestMagnitude2 > closeMagnitude2))
|
||||||
|
{
|
||||||
|
bForce = false;
|
||||||
|
bestMagnitude2 = closeMagnitude2;
|
||||||
|
nearestPoint = closePoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If bForce is true at this point, it means the nearest point lies
|
||||||
|
// inside the triangle; use the nearest-point-on-a-plane equation
|
||||||
|
if (bForce)
|
||||||
|
{
|
||||||
|
float3 normal;
|
||||||
|
|
||||||
|
// Get the normal of the polygon (doesn't have to be a unit vector)
|
||||||
|
normal = float3.cross(lineDelta0, lineDelta1);
|
||||||
|
|
||||||
|
float3 pointDelta = point - triangle0;
|
||||||
|
float delta = float3.dot(normal, pointDelta) / float3.dot(normal, normal);
|
||||||
|
|
||||||
|
nearestPoint = point - normal * delta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.x = nearestPoint.x;
|
||||||
|
this.y = nearestPoint.y;
|
||||||
|
this.z = nearestPoint.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3 operator +(float3 a, float3 b)
|
||||||
|
{
|
||||||
|
return new float3(a.x + b.x, a.y + b.y, a.z + b.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3 operator -(float3 a, float3 b)
|
||||||
|
{
|
||||||
|
return new float3(a.x - b.x, a.y - b.y, a.z - b.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3 operator -(float3 a, float s)
|
||||||
|
{
|
||||||
|
return new float3(a.x - s, a.y - s, a.z - s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3 operator -(float3 v)
|
||||||
|
{
|
||||||
|
return new float3(-v.x, -v.y, -v.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3 operator *(float3 v, float s)
|
||||||
|
{
|
||||||
|
return new float3(v.x * s, v.y * s, v.z * s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3 operator *(float s, float3 v)
|
||||||
|
{
|
||||||
|
return new float3(v.x * s, v.y * s, v.z * s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3 operator *(float3 v, float3x3 m)
|
||||||
|
{
|
||||||
|
return new float3((m.x.x * v.x + m.y.x * v.y + m.z.x * v.z), (m.x.y * v.x + m.y.y * v.y + m.z.y * v.z), (m.x.z * v.x + m.y.z * v.y + m.z.z * v.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3 operator *(float3x3 m, float3 v)
|
||||||
|
{
|
||||||
|
return new float3(dot(m.x, v), dot(m.y, v), dot(m.z, v));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3 operator /(float3 v, float s)
|
||||||
|
{
|
||||||
|
float sinv = 1.0f / s;
|
||||||
|
return new float3(v.x * sinv, v.y * sinv, v.z * sinv);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(float3 other)
|
||||||
|
{
|
||||||
|
return this == other;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
float3 f = obj as float3;
|
||||||
|
if (f == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return this == f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(float3 a, float3 b)
|
||||||
|
{
|
||||||
|
// If both are null, or both are same instance, return true.
|
||||||
|
if (System.Object.ReferenceEquals(a, b))
|
||||||
|
return true;
|
||||||
|
// If one is null, but not both, return false.
|
||||||
|
if (((object)a == null) || ((object)b == null))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (a.x == b.x && a.y == b.y && a.z == b.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(float3 a, float3 b)
|
||||||
|
{
|
||||||
|
return (a.x != b.x || a.y != b.y || a.z != b.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float dot(float3 a, float3 b)
|
||||||
|
{
|
||||||
|
return a.x * b.x + a.y * b.y + a.z * b.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3 cmul(float3 v1, float3 v2)
|
||||||
|
{
|
||||||
|
return new float3(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3 cross(float3 a, float3 b)
|
||||||
|
{
|
||||||
|
return new float3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3 Interpolate(float3 v0, float3 v1, float alpha)
|
||||||
|
{
|
||||||
|
return v0 * (1 - alpha) + v1 * alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3 Round(float3 a, int digits)
|
||||||
|
{
|
||||||
|
return new float3((float)Math.Round(a.x, digits), (float)Math.Round(a.y, digits), (float)Math.Round(a.z, digits));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3 VectorMax(float3 a, float3 b)
|
||||||
|
{
|
||||||
|
return new float3(Math.Max(a.x, b.x), Math.Max(a.y, b.y), Math.Max(a.z, b.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3 VectorMin(float3 a, float3 b)
|
||||||
|
{
|
||||||
|
return new float3(Math.Min(a.x, b.x), Math.Min(a.y, b.y), Math.Min(a.z, b.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3 vabs(float3 v)
|
||||||
|
{
|
||||||
|
return new float3(Math.Abs(v.x), Math.Abs(v.y), Math.Abs(v.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float magnitude(float3 v)
|
||||||
|
{
|
||||||
|
return (float)Math.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3 normalize(float3 v)
|
||||||
|
{
|
||||||
|
float d = magnitude(v);
|
||||||
|
if (d == 0)
|
||||||
|
d = 0.1f;
|
||||||
|
d = 1 / d;
|
||||||
|
return new float3(v.x * d, v.y * d, v.z * d);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3 safenormalize(float3 v)
|
||||||
|
{
|
||||||
|
if (magnitude(v) <= 0.0f)
|
||||||
|
return new float3(1, 0, 0);
|
||||||
|
else
|
||||||
|
return normalize(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float Yaw(float3 v)
|
||||||
|
{
|
||||||
|
return (v.y == 0.0 && v.x == 0.0) ? 0.0f : (float)Math.Atan2(-v.x, v.y) * (180.0f / 3.14159264f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float Pitch(float3 v)
|
||||||
|
{
|
||||||
|
return (float)Math.Atan2(v.z, Math.Sqrt(v.x * v.x + v.y * v.y)) * (180.0f / 3.14159264f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float ComputePlane(float3 A, float3 B, float3 C)
|
||||||
|
{
|
||||||
|
float vx, vy, vz, wx, wy, wz, vw_x, vw_y, vw_z, mag;
|
||||||
|
|
||||||
|
vx = (B.x - C.x);
|
||||||
|
vy = (B.y - C.y);
|
||||||
|
vz = (B.z - C.z);
|
||||||
|
|
||||||
|
wx = (A.x - B.x);
|
||||||
|
wy = (A.y - B.y);
|
||||||
|
wz = (A.z - B.z);
|
||||||
|
|
||||||
|
vw_x = vy * wz - vz * wy;
|
||||||
|
vw_y = vz * wx - vx * wz;
|
||||||
|
vw_z = vx * wy - vy * wx;
|
||||||
|
|
||||||
|
mag = (float)Math.Sqrt((vw_x * vw_x) + (vw_y * vw_y) + (vw_z * vw_z));
|
||||||
|
|
||||||
|
if (mag < 0.000001f)
|
||||||
|
{
|
||||||
|
mag = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mag = 1.0f / mag;
|
||||||
|
}
|
||||||
|
|
||||||
|
x = vw_x * mag;
|
||||||
|
y = vw_y * mag;
|
||||||
|
z = vw_z * mag;
|
||||||
|
|
||||||
|
float D = 0.0f - ((x * A.x) + (y * A.y) + (z * A.z));
|
||||||
|
return D;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return String.Format("<{0}, {1}, {2}>", x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly float3 Zero = new float3();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,195 @@
|
||||||
|
/* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Based on the convexdecomposition library from
|
||||||
|
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
|
||||||
|
{
|
||||||
|
public class float3x3
|
||||||
|
{
|
||||||
|
public float3 x = new float3();
|
||||||
|
public float3 y = new float3();
|
||||||
|
public float3 z = new float3();
|
||||||
|
|
||||||
|
public float3x3()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public float3x3(float xx, float xy, float xz, float yx, float yy, float yz, float zx, float zy, float zz)
|
||||||
|
{
|
||||||
|
x = new float3(xx, xy, xz);
|
||||||
|
y = new float3(yx, yy, yz);
|
||||||
|
z = new float3(zx, zy, zz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float3x3(float3 _x, float3 _y, float3 _z)
|
||||||
|
{
|
||||||
|
x = new float3(_x);
|
||||||
|
y = new float3(_y);
|
||||||
|
z = new float3(_z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float3 this[int i]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 0: return x;
|
||||||
|
case 1: return y;
|
||||||
|
case 2: return z;
|
||||||
|
}
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float this[int i, int j]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
switch (j)
|
||||||
|
{
|
||||||
|
case 0: return x.x;
|
||||||
|
case 1: return x.y;
|
||||||
|
case 2: return x.z;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
switch (j)
|
||||||
|
{
|
||||||
|
case 0: return y.x;
|
||||||
|
case 1: return y.y;
|
||||||
|
case 2: return y.z;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
switch (j)
|
||||||
|
{
|
||||||
|
case 0: return z.x;
|
||||||
|
case 1: return z.y;
|
||||||
|
case 2: return z.z;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
switch (j)
|
||||||
|
{
|
||||||
|
case 0: x.x = value; return;
|
||||||
|
case 1: x.y = value; return;
|
||||||
|
case 2: x.z = value; return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
switch (j)
|
||||||
|
{
|
||||||
|
case 0: y.x = value; return;
|
||||||
|
case 1: y.y = value; return;
|
||||||
|
case 2: y.z = value; return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
switch (j)
|
||||||
|
{
|
||||||
|
case 0: z.x = value; return;
|
||||||
|
case 1: z.y = value; return;
|
||||||
|
case 2: z.z = value; return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3x3 Transpose(float3x3 m)
|
||||||
|
{
|
||||||
|
return new float3x3(new float3(m.x.x, m.y.x, m.z.x), new float3(m.x.y, m.y.y, m.z.y), new float3(m.x.z, m.y.z, m.z.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3x3 operator *(float3x3 a, float3x3 b)
|
||||||
|
{
|
||||||
|
return new float3x3(a.x * b, a.y * b, a.z * b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3x3 operator *(float3x3 a, float s)
|
||||||
|
{
|
||||||
|
return new float3x3(a.x * s, a.y * s, a.z * s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3x3 operator /(float3x3 a, float s)
|
||||||
|
{
|
||||||
|
float t = 1f / s;
|
||||||
|
return new float3x3(a.x * t, a.y * t, a.z * t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3x3 operator +(float3x3 a, float3x3 b)
|
||||||
|
{
|
||||||
|
return new float3x3(a.x + b.x, a.y + b.y, a.z + b.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3x3 operator -(float3x3 a, float3x3 b)
|
||||||
|
{
|
||||||
|
return new float3x3(a.x - b.x, a.y - b.y, a.z - b.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float Determinant(float3x3 m)
|
||||||
|
{
|
||||||
|
return m.x.x * m.y.y * m.z.z + m.y.x * m.z.y * m.x.z + m.z.x * m.x.y * m.y.z - m.x.x * m.z.y * m.y.z - m.y.x * m.x.y * m.z.z - m.z.x * m.y.y * m.x.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float3x3 Inverse(float3x3 a)
|
||||||
|
{
|
||||||
|
float3x3 b = new float3x3();
|
||||||
|
float d = Determinant(a);
|
||||||
|
Debug.Assert(d != 0);
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < 3; j++)
|
||||||
|
{
|
||||||
|
int i1 = (i + 1) % 3;
|
||||||
|
int i2 = (i + 2) % 3;
|
||||||
|
int j1 = (j + 1) % 3;
|
||||||
|
int j2 = (j + 2) % 3;
|
||||||
|
|
||||||
|
// reverse indexs i&j to take transpose
|
||||||
|
b[i, j] = (a[i1][j1] * a[i2][j2] - a[i1][j2] * a[i2][j1]) / d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,170 @@
|
||||||
|
/* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Based on the convexdecomposition library from
|
||||||
|
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
|
||||||
|
{
|
||||||
|
public class float4
|
||||||
|
{
|
||||||
|
public float x;
|
||||||
|
public float y;
|
||||||
|
public float z;
|
||||||
|
public float w;
|
||||||
|
|
||||||
|
public float4()
|
||||||
|
{
|
||||||
|
x = 0;
|
||||||
|
y = 0;
|
||||||
|
z = 0;
|
||||||
|
w = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float4(float _x, float _y, float _z, float _w)
|
||||||
|
{
|
||||||
|
x = _x;
|
||||||
|
y = _y;
|
||||||
|
z = _z;
|
||||||
|
w = _w;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float4(float3 v, float _w)
|
||||||
|
{
|
||||||
|
x = v.x;
|
||||||
|
y = v.y;
|
||||||
|
z = v.z;
|
||||||
|
w = _w;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float4(float4 f)
|
||||||
|
{
|
||||||
|
x = f.x;
|
||||||
|
y = f.y;
|
||||||
|
z = f.z;
|
||||||
|
w = f.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float this[int i]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 0: return x;
|
||||||
|
case 1: return y;
|
||||||
|
case 2: return z;
|
||||||
|
case 3: return w;
|
||||||
|
}
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float3 xyz()
|
||||||
|
{
|
||||||
|
return new float3(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setxyz(float3 xyz)
|
||||||
|
{
|
||||||
|
x = xyz.x;
|
||||||
|
y = xyz.y;
|
||||||
|
z = xyz.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
float4 f = obj as float4;
|
||||||
|
if (f == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return this == f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float4 Homogenize(float3 v3)
|
||||||
|
{
|
||||||
|
return Homogenize(v3, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
//C++ TO C# CONVERTER NOTE: C# does not allow default values for parameters. Overloaded methods are inserted above.
|
||||||
|
//ORIGINAL LINE: float4 Homogenize(const float3 &v3, const float &w =1.0f)
|
||||||
|
public static float4 Homogenize(float3 v3, float w)
|
||||||
|
{
|
||||||
|
return new float4(v3.x, v3.y, v3.z, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float4 cmul(float4 a, float4 b)
|
||||||
|
{
|
||||||
|
return new float4(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float4 operator +(float4 a, float4 b)
|
||||||
|
{
|
||||||
|
return new float4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
|
||||||
|
}
|
||||||
|
public static float4 operator -(float4 a, float4 b)
|
||||||
|
{
|
||||||
|
return new float4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float4 operator *(float4 v, float4x4 m)
|
||||||
|
{
|
||||||
|
return v.x * m.x + v.y * m.y + v.z * m.z + v.w * m.w; // yes this actually works
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(float4 a, float4 b)
|
||||||
|
{
|
||||||
|
// If both are null, or both are same instance, return true.
|
||||||
|
if (System.Object.ReferenceEquals(a, b))
|
||||||
|
return true;
|
||||||
|
// If one is null, but not both, return false.
|
||||||
|
if (((object)a == null) || ((object)b == null))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(float4 a, float4 b)
|
||||||
|
{
|
||||||
|
return !(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float4 operator *(float4 v, float s)
|
||||||
|
{
|
||||||
|
return new float4(v.x * s, v.y * s, v.z * s, v.w * s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float4 operator *(float s, float4 v)
|
||||||
|
{
|
||||||
|
return new float4(v.x * s, v.y * s, v.z * s, v.w * s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,284 @@
|
||||||
|
/* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Based on the convexdecomposition library from
|
||||||
|
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
|
||||||
|
{
|
||||||
|
public class float4x4
|
||||||
|
{
|
||||||
|
public float4 x = new float4();
|
||||||
|
public float4 y = new float4();
|
||||||
|
public float4 z = new float4();
|
||||||
|
public float4 w = new float4();
|
||||||
|
|
||||||
|
public float4x4()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public float4x4(float4 _x, float4 _y, float4 _z, float4 _w)
|
||||||
|
{
|
||||||
|
x = new float4(_x);
|
||||||
|
y = new float4(_y);
|
||||||
|
z = new float4(_z);
|
||||||
|
w = new float4(_w);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float4x4(
|
||||||
|
float m00, float m01, float m02, float m03,
|
||||||
|
float m10, float m11, float m12, float m13,
|
||||||
|
float m20, float m21, float m22, float m23,
|
||||||
|
float m30, float m31, float m32, float m33)
|
||||||
|
{
|
||||||
|
x = new float4(m00, m01, m02, m03);
|
||||||
|
y = new float4(m10, m11, m12, m13);
|
||||||
|
z = new float4(m20, m21, m22, m23);
|
||||||
|
w = new float4(m30, m31, m32, m33);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float4x4(float4x4 m)
|
||||||
|
{
|
||||||
|
x = new float4(m.x);
|
||||||
|
y = new float4(m.y);
|
||||||
|
z = new float4(m.z);
|
||||||
|
w = new float4(m.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float4 this[int i]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 0: return x;
|
||||||
|
case 1: return y;
|
||||||
|
case 2: return z;
|
||||||
|
case 3: return w;
|
||||||
|
}
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 0: x = value; return;
|
||||||
|
case 1: y = value; return;
|
||||||
|
case 2: z = value; return;
|
||||||
|
case 3: w = value; return;
|
||||||
|
}
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
float4x4 m = obj as float4x4;
|
||||||
|
if (m == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return this == m;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float4x4 operator *(float4x4 a, float4x4 b)
|
||||||
|
{
|
||||||
|
return new float4x4(a.x * b, a.y * b, a.z * b, a.w * b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(float4x4 a, float4x4 b)
|
||||||
|
{
|
||||||
|
return (a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(float4x4 a, float4x4 b)
|
||||||
|
{
|
||||||
|
return !(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float4x4 Inverse(float4x4 m)
|
||||||
|
{
|
||||||
|
float4x4 d = new float4x4();
|
||||||
|
//float dst = d.x.x;
|
||||||
|
float[] tmp = new float[12]; // temp array for pairs
|
||||||
|
float[] src = new float[16]; // array of transpose source matrix
|
||||||
|
float det; // determinant
|
||||||
|
// transpose matrix
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
src[i] = m[i].x;
|
||||||
|
src[i + 4] = m[i].y;
|
||||||
|
src[i + 8] = m[i].z;
|
||||||
|
src[i + 12] = m[i].w;
|
||||||
|
}
|
||||||
|
// calculate pairs for first 8 elements (cofactors)
|
||||||
|
tmp[0] = src[10] * src[15];
|
||||||
|
tmp[1] = src[11] * src[14];
|
||||||
|
tmp[2] = src[9] * src[15];
|
||||||
|
tmp[3] = src[11] * src[13];
|
||||||
|
tmp[4] = src[9] * src[14];
|
||||||
|
tmp[5] = src[10] * src[13];
|
||||||
|
tmp[6] = src[8] * src[15];
|
||||||
|
tmp[7] = src[11] * src[12];
|
||||||
|
tmp[8] = src[8] * src[14];
|
||||||
|
tmp[9] = src[10] * src[12];
|
||||||
|
tmp[10] = src[8] * src[13];
|
||||||
|
tmp[11] = src[9] * src[12];
|
||||||
|
// calculate first 8 elements (cofactors)
|
||||||
|
d.x.x = tmp[0]*src[5] + tmp[3]*src[6] + tmp[4]*src[7];
|
||||||
|
d.x.x -= tmp[1]*src[5] + tmp[2]*src[6] + tmp[5]*src[7];
|
||||||
|
d.x.y = tmp[1]*src[4] + tmp[6]*src[6] + tmp[9]*src[7];
|
||||||
|
d.x.y -= tmp[0]*src[4] + tmp[7]*src[6] + tmp[8]*src[7];
|
||||||
|
d.x.z = tmp[2]*src[4] + tmp[7]*src[5] + tmp[10]*src[7];
|
||||||
|
d.x.z -= tmp[3]*src[4] + tmp[6]*src[5] + tmp[11]*src[7];
|
||||||
|
d.x.w = tmp[5]*src[4] + tmp[8]*src[5] + tmp[11]*src[6];
|
||||||
|
d.x.w -= tmp[4]*src[4] + tmp[9]*src[5] + tmp[10]*src[6];
|
||||||
|
d.y.x = tmp[1]*src[1] + tmp[2]*src[2] + tmp[5]*src[3];
|
||||||
|
d.y.x -= tmp[0]*src[1] + tmp[3]*src[2] + tmp[4]*src[3];
|
||||||
|
d.y.y = tmp[0]*src[0] + tmp[7]*src[2] + tmp[8]*src[3];
|
||||||
|
d.y.y -= tmp[1]*src[0] + tmp[6]*src[2] + tmp[9]*src[3];
|
||||||
|
d.y.z = tmp[3]*src[0] + tmp[6]*src[1] + tmp[11]*src[3];
|
||||||
|
d.y.z -= tmp[2]*src[0] + tmp[7]*src[1] + tmp[10]*src[3];
|
||||||
|
d.y.w = tmp[4]*src[0] + tmp[9]*src[1] + tmp[10]*src[2];
|
||||||
|
d.y.w -= tmp[5]*src[0] + tmp[8]*src[1] + tmp[11]*src[2];
|
||||||
|
// calculate pairs for second 8 elements (cofactors)
|
||||||
|
tmp[0] = src[2]*src[7];
|
||||||
|
tmp[1] = src[3]*src[6];
|
||||||
|
tmp[2] = src[1]*src[7];
|
||||||
|
tmp[3] = src[3]*src[5];
|
||||||
|
tmp[4] = src[1]*src[6];
|
||||||
|
tmp[5] = src[2]*src[5];
|
||||||
|
tmp[6] = src[0]*src[7];
|
||||||
|
tmp[7] = src[3]*src[4];
|
||||||
|
tmp[8] = src[0]*src[6];
|
||||||
|
tmp[9] = src[2]*src[4];
|
||||||
|
tmp[10] = src[0]*src[5];
|
||||||
|
tmp[11] = src[1]*src[4];
|
||||||
|
// calculate second 8 elements (cofactors)
|
||||||
|
d.z.x = tmp[0]*src[13] + tmp[3]*src[14] + tmp[4]*src[15];
|
||||||
|
d.z.x -= tmp[1]*src[13] + tmp[2]*src[14] + tmp[5]*src[15];
|
||||||
|
d.z.y = tmp[1]*src[12] + tmp[6]*src[14] + tmp[9]*src[15];
|
||||||
|
d.z.y -= tmp[0]*src[12] + tmp[7]*src[14] + tmp[8]*src[15];
|
||||||
|
d.z.z = tmp[2]*src[12] + tmp[7]*src[13] + tmp[10]*src[15];
|
||||||
|
d.z.z -= tmp[3]*src[12] + tmp[6]*src[13] + tmp[11]*src[15];
|
||||||
|
d.z.w = tmp[5]*src[12] + tmp[8]*src[13] + tmp[11]*src[14];
|
||||||
|
d.z.w-= tmp[4]*src[12] + tmp[9]*src[13] + tmp[10]*src[14];
|
||||||
|
d.w.x = tmp[2]*src[10] + tmp[5]*src[11] + tmp[1]*src[9];
|
||||||
|
d.w.x-= tmp[4]*src[11] + tmp[0]*src[9] + tmp[3]*src[10];
|
||||||
|
d.w.y = tmp[8]*src[11] + tmp[0]*src[8] + tmp[7]*src[10];
|
||||||
|
d.w.y-= tmp[6]*src[10] + tmp[9]*src[11] + tmp[1]*src[8];
|
||||||
|
d.w.z = tmp[6]*src[9] + tmp[11]*src[11] + tmp[3]*src[8];
|
||||||
|
d.w.z-= tmp[10]*src[11] + tmp[2]*src[8] + tmp[7]*src[9];
|
||||||
|
d.w.w = tmp[10]*src[10] + tmp[4]*src[8] + tmp[9]*src[9];
|
||||||
|
d.w.w-= tmp[8]*src[9] + tmp[11]*src[10] + tmp[5]*src[8];
|
||||||
|
// calculate determinant
|
||||||
|
det = src[0] * d.x.x + src[1] * d.x.y + src[2] * d.x.z + src[3] * d.x.w;
|
||||||
|
// calculate matrix inverse
|
||||||
|
det = 1/det;
|
||||||
|
for (int j = 0; j < 4; j++)
|
||||||
|
d[j] *= det;
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float4x4 MatrixRigidInverse(float4x4 m)
|
||||||
|
{
|
||||||
|
float4x4 trans_inverse = MatrixTranslation(-m.w.xyz());
|
||||||
|
float4x4 rot = new float4x4(m);
|
||||||
|
rot.w = new float4(0f, 0f, 0f, 1f);
|
||||||
|
return trans_inverse * MatrixTranspose(rot);
|
||||||
|
}
|
||||||
|
public static float4x4 MatrixTranspose(float4x4 m)
|
||||||
|
{
|
||||||
|
return new float4x4(m.x.x, m.y.x, m.z.x, m.w.x, m.x.y, m.y.y, m.z.y, m.w.y, m.x.z, m.y.z, m.z.z, m.w.z, m.x.w, m.y.w, m.z.w, m.w.w);
|
||||||
|
}
|
||||||
|
public static float4x4 MatrixPerspectiveFov(float fovy, float aspect, float zn, float zf)
|
||||||
|
{
|
||||||
|
float h = 1.0f / (float)Math.Tan(fovy / 2.0f); // view space height
|
||||||
|
float w = h / aspect; // view space width
|
||||||
|
return new float4x4(w, 0, 0, 0, 0, h, 0, 0, 0, 0, zf / (zn - zf), -1, 0, 0, zn * zf / (zn - zf), 0);
|
||||||
|
}
|
||||||
|
public static float4x4 MatrixTranslation(float3 t)
|
||||||
|
{
|
||||||
|
return new float4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, t.x, t.y, t.z, 1);
|
||||||
|
}
|
||||||
|
public static float4x4 MatrixRotationZ(float angle_radians)
|
||||||
|
{
|
||||||
|
float s = (float)Math.Sin(angle_radians);
|
||||||
|
float c = (float)Math.Cos(angle_radians);
|
||||||
|
return new float4x4(c, s, 0, 0, -s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
public static float4x4 MatrixLookAt(float3 eye, float3 at, float3 up)
|
||||||
|
{
|
||||||
|
float4x4 m = new float4x4();
|
||||||
|
m.w.w = 1.0f;
|
||||||
|
m.w.setxyz(eye);
|
||||||
|
m.z.setxyz(float3.normalize(eye - at));
|
||||||
|
m.x.setxyz(float3.normalize(float3.cross(up, m.z.xyz())));
|
||||||
|
m.y.setxyz(float3.cross(m.z.xyz(), m.x.xyz()));
|
||||||
|
return MatrixRigidInverse(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float4x4 MatrixFromQuatVec(Quaternion q, float3 v)
|
||||||
|
{
|
||||||
|
// builds a 4x4 transformation matrix based on orientation q and translation v
|
||||||
|
float qx2 = q.x * q.x;
|
||||||
|
float qy2 = q.y * q.y;
|
||||||
|
float qz2 = q.z * q.z;
|
||||||
|
|
||||||
|
float qxqy = q.x * q.y;
|
||||||
|
float qxqz = q.x * q.z;
|
||||||
|
float qxqw = q.x * q.w;
|
||||||
|
float qyqz = q.y * q.z;
|
||||||
|
float qyqw = q.y * q.w;
|
||||||
|
float qzqw = q.z * q.w;
|
||||||
|
|
||||||
|
return new float4x4(
|
||||||
|
1 - 2 * (qy2 + qz2),
|
||||||
|
2 * (qxqy + qzqw),
|
||||||
|
2 * (qxqz - qyqw),
|
||||||
|
0,
|
||||||
|
2 * (qxqy - qzqw),
|
||||||
|
1 - 2 * (qx2 + qz2),
|
||||||
|
2 * (qyqz + qxqw),
|
||||||
|
0,
|
||||||
|
2 * (qxqz + qyqw),
|
||||||
|
2 * (qyqz - qxqw),
|
||||||
|
1 - 2 * (qx2 + qy2),
|
||||||
|
0,
|
||||||
|
v.x,
|
||||||
|
v.y,
|
||||||
|
v.z,
|
||||||
|
1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,128 @@
|
||||||
|
/* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Based on the convexdecomposition library from
|
||||||
|
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
|
||||||
|
{
|
||||||
|
public class int3
|
||||||
|
{
|
||||||
|
public int x;
|
||||||
|
public int y;
|
||||||
|
public int z;
|
||||||
|
|
||||||
|
public int3()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public int3(int _x, int _y, int _z)
|
||||||
|
{
|
||||||
|
x = _x;
|
||||||
|
y = _y;
|
||||||
|
z = _z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int this[int i]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 0: return x;
|
||||||
|
case 1: return y;
|
||||||
|
case 2: return z;
|
||||||
|
}
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 0: x = value; return;
|
||||||
|
case 1: y = value; return;
|
||||||
|
case 2: z = value; return;
|
||||||
|
}
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
int3 i = obj as int3;
|
||||||
|
if (i == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return this == i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(int3 a, int3 b)
|
||||||
|
{
|
||||||
|
// If both are null, or both are same instance, return true.
|
||||||
|
if (System.Object.ReferenceEquals(a, b))
|
||||||
|
return true;
|
||||||
|
// If one is null, but not both, return false.
|
||||||
|
if (((object)a == null) || ((object)b == null))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
if (a[i] != b[i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(int3 a, int3 b)
|
||||||
|
{
|
||||||
|
return !(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int3 roll3(int3 a)
|
||||||
|
{
|
||||||
|
int tmp = a[0];
|
||||||
|
a[0] = a[1];
|
||||||
|
a[1] = a[2];
|
||||||
|
a[2] = tmp;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool isa(int3 a, int3 b)
|
||||||
|
{
|
||||||
|
return (a == b || roll3(a) == b || a == roll3(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool b2b(int3 a, int3 b)
|
||||||
|
{
|
||||||
|
return isa(a, new int3(b[2], b[1], b[0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Based on the convexdecomposition library from
|
||||||
|
* <http://codesuppository.googlecode.com> by John W. Ratcliff and Stan Melax.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.ConvexDecompositionDotNet
|
||||||
|
{
|
||||||
|
public class int4
|
||||||
|
{
|
||||||
|
public int x;
|
||||||
|
public int y;
|
||||||
|
public int z;
|
||||||
|
public int w;
|
||||||
|
|
||||||
|
public int4()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public int4(int _x, int _y, int _z, int _w)
|
||||||
|
{
|
||||||
|
x = _x;
|
||||||
|
y = _y;
|
||||||
|
z = _z;
|
||||||
|
w = _w;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int this[int i]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 0: return x;
|
||||||
|
case 1: return y;
|
||||||
|
case 2: return z;
|
||||||
|
case 3: return w;
|
||||||
|
}
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
<Project frameworkVersion="v3_5" name="OpenSim.Region.Physics.ConvexDecompositionDotNet" path="addon-modules/ConvexDecompositionDotNet" 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.Data"/>
|
||||||
|
<Reference name="System.Xml"/>
|
||||||
|
|
||||||
|
<Files>
|
||||||
|
<Match pattern="*.cs" recurse="true">
|
||||||
|
<Exclude name="Tests" pattern="Tests"/>
|
||||||
|
</Match>
|
||||||
|
</Files>
|
||||||
|
</Project>
|
Binary file not shown.
Loading…
Reference in New Issue