From 134f86e8d5c414409631b25b8c6f0ee45fbd8631 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Thu, 3 Nov 2016 21:44:39 +1000 Subject: Initial update to OpenSim 0.8.2.1 source code. --- .../Physics/BasicPhysicsPlugin/AssemblyInfo.cs | 58 - .../BasicPhysicsPlugin/BasicPhysicsActor.cs | 311 -- .../BasicPhysicsPlugin/BasicPhysicsPlugin.cs | 64 - .../Physics/BasicPhysicsPlugin/BasicPhysicsPrim.cs | 315 -- .../BasicPhysicsPlugin/BasicPhysicsScene.cs | 194 - .../Region/Physics/BulletSNPlugin/BSCharacter.cs | 814 ---- .../Region/Physics/BulletSNPlugin/BSConstraint.cs | 135 - .../Physics/BulletSNPlugin/BSConstraint6Dof.cs | 153 - .../BulletSNPlugin/BSConstraintCollection.cs | 180 - .../Physics/BulletSNPlugin/BSConstraintHinge.cs | 57 - .../Region/Physics/BulletSNPlugin/BSDynamics.cs | 1377 ------- OpenSim/Region/Physics/BulletSNPlugin/BSLinkset.cs | 329 -- .../Physics/BulletSNPlugin/BSLinksetCompound.cs | 397 -- .../Physics/BulletSNPlugin/BSLinksetConstraints.cs | 316 -- .../Region/Physics/BulletSNPlugin/BSMaterials.cs | 200 - OpenSim/Region/Physics/BulletSNPlugin/BSMotors.cs | 347 -- OpenSim/Region/Physics/BulletSNPlugin/BSParam.cs | 559 --- .../Region/Physics/BulletSNPlugin/BSPhysObject.cs | 346 -- OpenSim/Region/Physics/BulletSNPlugin/BSPlugin.cs | 81 - OpenSim/Region/Physics/BulletSNPlugin/BSPrim.cs | 1494 ------- OpenSim/Region/Physics/BulletSNPlugin/BSScene.cs | 957 ----- .../Physics/BulletSNPlugin/BSShapeCollection.cs | 1015 ----- OpenSim/Region/Physics/BulletSNPlugin/BSShapes.cs | 208 - .../Physics/BulletSNPlugin/BSTerrainHeightmap.cs | 175 - .../Physics/BulletSNPlugin/BSTerrainManager.cs | 461 --- .../Region/Physics/BulletSNPlugin/BSTerrainMesh.cs | 267 -- .../Region/Physics/BulletSNPlugin/BulletSimAPI.cs | 1603 -------- .../Region/Physics/BulletSNPlugin/BulletSimData.cs | 280 -- OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs | 1839 --------- OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs | 1622 -------- .../Region/Physics/BulletSPlugin/BSApiTemplate.cs | 662 --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 827 ---- .../Region/Physics/BulletSPlugin/BSConstraint.cs | 138 - .../Physics/BulletSPlugin/BSConstraint6Dof.cs | 151 - .../BulletSPlugin/BSConstraintCollection.cs | 180 - .../Physics/BulletSPlugin/BSConstraintHinge.cs | 55 - OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 1383 ------- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 329 -- .../Physics/BulletSPlugin/BSLinksetCompound.cs | 392 -- .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 312 -- .../Region/Physics/BulletSPlugin/BSMaterials.cs | 200 - OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs | 347 -- OpenSim/Region/Physics/BulletSPlugin/BSParam.cs | 582 --- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 386 -- OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs | 76 - OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 1513 ------- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 946 ----- .../Physics/BulletSPlugin/BSShapeCollection.cs | 1009 ----- OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs | 232 -- .../Physics/BulletSPlugin/BSTerrainHeightmap.cs | 171 - .../Physics/BulletSPlugin/BSTerrainManager.cs | 458 --- .../Region/Physics/BulletSPlugin/BSTerrainMesh.cs | 265 -- .../Region/Physics/BulletSPlugin/BulletSimData.cs | 263 -- .../Region/Physics/BulletSPlugin/BulletSimTODO.txt | 272 -- .../BulletSPlugin/Properties/AssemblyInfo.cs | 33 - .../Physics/ConvexDecompositionDotNet/CTri.cs | 341 -- .../Physics/ConvexDecompositionDotNet/Concavity.cs | 233 -- .../ConvexDecompositionDotNet/ConvexBuilder.cs | 411 -- .../ConvexDecomposition.cs | 200 - .../ConvexDecompositionDotNet/ConvexResult.cs | 74 - .../ConvexDecompositionDotNet/HullClasses.cs | 171 - .../ConvexDecompositionDotNet/HullTriangle.cs | 99 - .../Physics/ConvexDecompositionDotNet/HullUtils.cs | 1868 --------- .../Physics/ConvexDecompositionDotNet/LICENSE.txt | 28 - .../Physics/ConvexDecompositionDotNet/Plane.cs | 99 - .../Physics/ConvexDecompositionDotNet/PlaneTri.cs | 211 - .../Properties/AssemblyInfo.cs | 36 - .../ConvexDecompositionDotNet/Quaternion.cs | 209 - .../Physics/ConvexDecompositionDotNet/README.txt | 7 - .../ConvexDecompositionDotNet/SplitPlane.cs | 265 -- .../ConvexDecompositionDotNet/VertexLookup.cs | 70 - .../Physics/ConvexDecompositionDotNet/float2.cs | 70 - .../Physics/ConvexDecompositionDotNet/float3.cs | 444 -- .../Physics/ConvexDecompositionDotNet/float3x3.cs | 195 - .../Physics/ConvexDecompositionDotNet/float4.cs | 170 - .../Physics/ConvexDecompositionDotNet/float4x4.cs | 284 -- .../Physics/ConvexDecompositionDotNet/int3.cs | 128 - .../Physics/ConvexDecompositionDotNet/int4.cs | 66 - OpenSim/Region/Physics/Manager/AssemblyInfo.cs | 58 - OpenSim/Region/Physics/Manager/CollisionLocker.cs | 73 - OpenSim/Region/Physics/Manager/IMesher.cs | 70 - .../Region/Physics/Manager/IPhysicsParameters.cs | 73 - OpenSim/Region/Physics/Manager/NullPhysicsScene.cs | 121 - OpenSim/Region/Physics/Manager/PhysicsActor.cs | 567 --- OpenSim/Region/Physics/Manager/PhysicsJoint.cs | 55 - .../Region/Physics/Manager/PhysicsPluginManager.cs | 240 -- OpenSim/Region/Physics/Manager/PhysicsScene.cs | 283 -- OpenSim/Region/Physics/Manager/PhysicsSensor.cs | 78 - OpenSim/Region/Physics/Manager/PhysicsVector.cs | 186 - OpenSim/Region/Physics/Manager/VehicleConstants.cs | 121 - OpenSim/Region/Physics/Manager/ZeroMesher.cs | 83 - OpenSim/Region/Physics/Meshing/HelperTypes.cs | 436 -- OpenSim/Region/Physics/Meshing/Mesh.cs | 333 -- OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 761 ---- OpenSim/Region/Physics/Meshing/PrimMesher.cs | 2324 ----------- .../Physics/Meshing/Properties/AssemblyInfo.cs | 33 - OpenSim/Region/Physics/Meshing/SculptMap.cs | 183 - OpenSim/Region/Physics/Meshing/SculptMesh.cs | 646 --- OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs | 58 - OpenSim/Region/Physics/OdePlugin/ODECharacter.cs | 1411 ------- .../Physics/OdePlugin/ODEDynamics.c_comments | 630 --- OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs | 974 ----- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 3380 --------------- .../Physics/OdePlugin/ODERayCastRequestManager.cs | 434 -- .../Region/Physics/OdePlugin/OdePhysicsJoint.cs | 48 - OpenSim/Region/Physics/OdePlugin/OdePlugin.cs | 90 - OpenSim/Region/Physics/OdePlugin/OdeScene.cs | 4323 -------------------- .../Region/Physics/OdePlugin/Tests/ODETestClass.cs | 128 - OpenSim/Region/Physics/OdePlugin/drawstuff.cs | 98 - OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs | 58 - OpenSim/Region/Physics/POSPlugin/POSCharacter.cs | 340 -- OpenSim/Region/Physics/POSPlugin/POSPlugin.cs | 64 - OpenSim/Region/Physics/POSPlugin/POSPrim.cs | 335 -- OpenSim/Region/Physics/POSPlugin/POSScene.cs | 270 -- 114 files changed, 52380 deletions(-) delete mode 100644 OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs delete mode 100644 OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs delete mode 100644 OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs delete mode 100644 OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPrim.cs delete mode 100644 OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BSCharacter.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BSConstraint.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BSConstraint6Dof.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BSConstraintCollection.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BSConstraintHinge.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BSDynamics.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BSLinkset.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BSLinksetCompound.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BSLinksetConstraints.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BSMaterials.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BSMotors.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BSParam.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BSPhysObject.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BSPlugin.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BSPrim.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BSScene.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BSShapeCollection.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BSShapes.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BSTerrainHeightmap.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BSTerrainManager.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BSTerrainMesh.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BulletSimAPI.cs delete mode 100644 OpenSim/Region/Physics/BulletSNPlugin/BulletSimData.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs delete mode 100644 OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs delete mode 100644 OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs delete mode 100644 OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSParam.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs delete mode 100644 OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs delete mode 100644 OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs delete mode 100644 OpenSim/Region/Physics/BulletSPlugin/BSScene.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt delete mode 100644 OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/CTri.cs delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/Concavity.cs delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/ConvexBuilder.cs delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/ConvexDecomposition.cs delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/ConvexResult.cs delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/HullClasses.cs delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/HullTriangle.cs delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/HullUtils.cs delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/LICENSE.txt delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/Plane.cs delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/PlaneTri.cs delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/Quaternion.cs delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/README.txt delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/SplitPlane.cs delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/VertexLookup.cs delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/float2.cs delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/float3.cs delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/float3x3.cs delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/float4.cs delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/float4x4.cs delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/int3.cs delete mode 100644 OpenSim/Region/Physics/ConvexDecompositionDotNet/int4.cs delete mode 100644 OpenSim/Region/Physics/Manager/AssemblyInfo.cs delete mode 100644 OpenSim/Region/Physics/Manager/CollisionLocker.cs delete mode 100644 OpenSim/Region/Physics/Manager/IMesher.cs delete mode 100755 OpenSim/Region/Physics/Manager/IPhysicsParameters.cs delete mode 100644 OpenSim/Region/Physics/Manager/NullPhysicsScene.cs delete mode 100644 OpenSim/Region/Physics/Manager/PhysicsActor.cs delete mode 100644 OpenSim/Region/Physics/Manager/PhysicsJoint.cs delete mode 100644 OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs delete mode 100644 OpenSim/Region/Physics/Manager/PhysicsScene.cs delete mode 100644 OpenSim/Region/Physics/Manager/PhysicsSensor.cs delete mode 100644 OpenSim/Region/Physics/Manager/PhysicsVector.cs delete mode 100644 OpenSim/Region/Physics/Manager/VehicleConstants.cs delete mode 100644 OpenSim/Region/Physics/Manager/ZeroMesher.cs delete mode 100644 OpenSim/Region/Physics/Meshing/HelperTypes.cs delete mode 100644 OpenSim/Region/Physics/Meshing/Mesh.cs delete mode 100644 OpenSim/Region/Physics/Meshing/Meshmerizer.cs delete mode 100644 OpenSim/Region/Physics/Meshing/PrimMesher.cs delete mode 100644 OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs delete mode 100644 OpenSim/Region/Physics/Meshing/SculptMap.cs delete mode 100644 OpenSim/Region/Physics/Meshing/SculptMesh.cs delete mode 100644 OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs delete mode 100644 OpenSim/Region/Physics/OdePlugin/ODECharacter.cs delete mode 100644 OpenSim/Region/Physics/OdePlugin/ODEDynamics.c_comments delete mode 100644 OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs delete mode 100644 OpenSim/Region/Physics/OdePlugin/ODEPrim.cs delete mode 100644 OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs delete mode 100644 OpenSim/Region/Physics/OdePlugin/OdePhysicsJoint.cs delete mode 100644 OpenSim/Region/Physics/OdePlugin/OdePlugin.cs delete mode 100644 OpenSim/Region/Physics/OdePlugin/OdeScene.cs delete mode 100644 OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs delete mode 100644 OpenSim/Region/Physics/OdePlugin/drawstuff.cs delete mode 100644 OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs delete mode 100644 OpenSim/Region/Physics/POSPlugin/POSCharacter.cs delete mode 100644 OpenSim/Region/Physics/POSPlugin/POSPlugin.cs delete mode 100644 OpenSim/Region/Physics/POSPlugin/POSPrim.cs delete mode 100644 OpenSim/Region/Physics/POSPlugin/POSScene.cs (limited to 'OpenSim/Region/Physics') diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs deleted file mode 100644 index fb9cb66..0000000 --- a/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Reflection; -using System.Runtime.InteropServices; - -// Information about this assembly is defined by the following -// attributes. -// -// change them to the information which is associated with the assembly -// you compile. - -[assembly : AssemblyTitle("BasicPhysicsPlugin")] -[assembly : AssemblyDescription("")] -[assembly : AssemblyConfiguration("")] -[assembly : AssemblyCompany("http://opensimulator.org")] -[assembly : AssemblyProduct("BasicPhysicsPlugin")] -[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers")] -[assembly : AssemblyTrademark("")] -[assembly : AssemblyCulture("")] - -// This sets the default COM visibility of types in the assembly to invisible. -// If you need to expose a type to COM, use [ComVisible(true)] on that type. - -[assembly : ComVisible(false)] - -// The assembly version has following format : -// -// Major.Minor.Build.Revision -// -// You can specify all values by your own or you can build default build and revision -// numbers with the '*' character (the default): - -[assembly : AssemblyVersion("0.7.5.*")] diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs deleted file mode 100644 index e43136a..0000000 --- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using Nini.Config; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.BasicPhysicsPlugin -{ - public class BasicActor : PhysicsActor - { - private Vector3 _size; - - public BasicActor(Vector3 size) - { - Size = size; - } - - public override int PhysicsActorType - { - get { return (int) ActorTypes.Agent; } - set { return; } - } - - public override Vector3 RotationalVelocity { get; set; } - - public override bool SetAlwaysRun - { - get { return false; } - set { return; } - } - - public override uint LocalID - { - set { return; } - } - - public override bool Grabbed - { - set { return; } - } - - public override bool Selected - { - set { return; } - } - - public override float Buoyancy - { - get { return 0f; } - set { return; } - } - - public override bool FloatOnWater - { - set { return; } - } - - public override bool IsPhysical - { - get { return false; } - set { return; } - } - - public override bool ThrottleUpdates - { - get { return false; } - set { return; } - } - - public override bool Flying { get; set; } - - public override bool IsColliding { get; set; } - - public override bool CollidingGround - { - get { return false; } - set { return; } - } - - public override bool CollidingObj - { - get { return false; } - set { return; } - } - - public override bool Stopped - { - get { return false; } - } - - public override Vector3 Position { get; set; } - - public override Vector3 Size - { - get { return _size; } - set { - _size = value; - _size.Z = _size.Z / 2.0f; - } - } - - public override PrimitiveBaseShape Shape - { - set { return; } - } - - public override float Mass - { - get { return 0f; } - } - - public override Vector3 Force - { - get { return Vector3.Zero; } - set { return; } - } - - 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) - { - - } - - public override void SetVolumeDetect(int param) - { - - } - - public override Vector3 CenterOfMass - { - get { return Vector3.Zero; } - } - - public override Vector3 GeometricCenter - { - get { return Vector3.Zero; } - } - - public override Vector3 Velocity { get; set; } - - public override Vector3 Torque - { - get { return Vector3.Zero; } - set { return; } - } - - public override float CollisionScore - { - get { return 0f; } - set { } - } - - public override Quaternion Orientation - { - get { return Quaternion.Identity; } - set { } - } - - public override Vector3 Acceleration { get; set; } - - public override bool Kinematic - { - get { return true; } - set { } - } - - public override void link(PhysicsActor obj) - { - } - - public override void delink() - { - } - - public override void LockAngularMotion(Vector3 axis) - { - } - - public override void AddForce(Vector3 force, bool pushforce) - { - } - - public override void AddAngularForce(Vector3 force, bool pushforce) - { - } - - public override void SetMomentum(Vector3 momentum) - { - } - - public override void CrossingFailure() - { - } - - public override Vector3 PIDTarget - { - set { return; } - } - - public override bool PIDActive - { - set { return; } - } - - public override float PIDTau - { - set { return; } - } - - public override float PIDHoverHeight - { - set { return; } - } - - public override bool PIDHoverActive - { - set { return; } - } - - public override PIDHoverType PIDHoverType - { - set { return; } - } - - public override float PIDHoverTau - { - set { return; } - } - - 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 SubscribeEvents(int ms) - { - } - - public override void UnSubscribeEvents() - { - } - - public override bool SubscribedEvents() - { - return false; - } - } -} diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs deleted file mode 100644 index 7ab2a03..0000000 --- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.BasicPhysicsPlugin -{ - /// - /// Effectively a physics plugin that simulates no physics at all. - /// - public class BasicPhysicsPlugin : IPhysicsPlugin - { - public BasicPhysicsPlugin() - { - } - - public bool Init() - { - return true; - } - - public PhysicsScene GetScene(string sceneIdentifier) - { - return new BasicScene(sceneIdentifier); - } - - public string GetName() - { - return ("basicphysics"); - } - - public void Dispose() - { - } - } -} diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPrim.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPrim.cs deleted file mode 100644 index 47d7df3..0000000 --- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPrim.cs +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using Nini.Config; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.BasicPhysicsPlugin -{ - public class BasicPhysicsPrim : PhysicsActor - { - private Vector3 _size; -// private PrimitiveBaseShape _shape; - - public BasicPhysicsPrim( - string name, uint localId, Vector3 position, Vector3 size, Quaternion orientation, PrimitiveBaseShape shape) - { - Name = name; - LocalID = localId; - Position = position; - Size = size; - Orientation = orientation; - Shape = shape; - } - - public override int PhysicsActorType - { - get { return (int) ActorTypes.Agent; } - set { return; } - } - - public override Vector3 RotationalVelocity { get; set; } - - public override bool SetAlwaysRun - { - get { return false; } - set { return; } - } - - public override uint LocalID - { - set { return; } - } - - public override bool Grabbed - { - set { return; } - } - - public override bool Selected - { - set { return; } - } - - public override float Buoyancy - { - get { return 0f; } - set { return; } - } - - public override bool FloatOnWater - { - set { return; } - } - - public override bool IsPhysical - { - get { return false; } - set { return; } - } - - public override bool ThrottleUpdates - { - get { return false; } - set { return; } - } - - public override bool Flying { get; set; } - - public override bool IsColliding { get; set; } - - public override bool CollidingGround - { - get { return false; } - set { return; } - } - - public override bool CollidingObj - { - get { return false; } - set { return; } - } - - public override bool Stopped - { - get { return false; } - } - - public override Vector3 Position { get; set; } - - public override Vector3 Size - { - get { return _size; } - set { - _size = value; - _size.Z = _size.Z / 2.0f; - } - } - - public override PrimitiveBaseShape Shape - { -// set { _shape = value; } - set {} - } - - public override float Mass - { - get { return 0f; } - } - - public override Vector3 Force - { - get { return Vector3.Zero; } - set { return; } - } - - 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) - { - - } - - public override void SetVolumeDetect(int param) - { - - } - - public override Vector3 CenterOfMass - { - get { return Vector3.Zero; } - } - - public override Vector3 GeometricCenter - { - get { return Vector3.Zero; } - } - - public override Vector3 Velocity { get; set; } - - public override Vector3 Torque - { - get { return Vector3.Zero; } - set { return; } - } - - public override float CollisionScore - { - get { return 0f; } - set { } - } - - public override Quaternion Orientation { get; set; } - - public override Vector3 Acceleration { get; set; } - - public override bool Kinematic - { - get { return true; } - set { } - } - - public override void link(PhysicsActor obj) - { - } - - public override void delink() - { - } - - public override void LockAngularMotion(Vector3 axis) - { - } - - public override void AddForce(Vector3 force, bool pushforce) - { - } - - public override void AddAngularForce(Vector3 force, bool pushforce) - { - } - - public override void SetMomentum(Vector3 momentum) - { - } - - public override void CrossingFailure() - { - } - - public override Vector3 PIDTarget - { - set { return; } - } - - public override bool PIDActive - { - set { return; } - } - - public override float PIDTau - { - set { return; } - } - - public override float PIDHoverHeight - { - set { return; } - } - - public override bool PIDHoverActive - { - set { return; } - } - - public override PIDHoverType PIDHoverType - { - set { return; } - } - - public override float PIDHoverTau - { - set { return; } - } - - 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 SubscribeEvents(int ms) - { - } - - public override void UnSubscribeEvents() - { - } - - public override bool SubscribedEvents() - { - return false; - } - } -} diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs deleted file mode 100644 index f5826ed..0000000 --- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using Nini.Config; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.BasicPhysicsPlugin -{ - /// - /// This is an incomplete extremely basic physics implementation - /// - /// - /// Not useful for anything at the moment apart from some regression testing in other components where some form - /// of physics plugin is needed. - /// - public class BasicScene : PhysicsScene - { - private List _actors = new List(); - private List _prims = new List(); - private float[] _heightMap; - - //protected internal string sceneIdentifier; - - public BasicScene(string _sceneIdentifier) - { - //sceneIdentifier = _sceneIdentifier; - } - - public override void Initialise(IMesher meshmerizer, IConfigSource config) - { - } - - public override void Dispose() {} - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, - Vector3 size, Quaternion rotation, bool isPhysical, uint localid) - { - BasicPhysicsPrim prim = new BasicPhysicsPrim(primName, localid, position, size, rotation, pbs); - prim.IsPhysical = isPhysical; - - _prims.Add(prim); - - return prim; - } - - public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) - { - BasicActor act = new BasicActor(size); - act.Position = position; - act.Flying = isFlying; - _actors.Add(act); - return act; - } - - public override void RemovePrim(PhysicsActor actor) - { - BasicPhysicsPrim prim = (BasicPhysicsPrim)actor; - if (_prims.Contains(prim)) - _prims.Remove(prim); - } - - public override void RemoveAvatar(PhysicsActor actor) - { - BasicActor act = (BasicActor)actor; - if (_actors.Contains(act)) - _actors.Remove(act); - } - - public override void AddPhysicsActorTaint(PhysicsActor prim) - { - } - - public override float Simulate(float timeStep) - { - float fps = 0; - for (int i = 0; i < _actors.Count; ++i) - { - BasicActor actor = _actors[i]; - Vector3 actorPosition = actor.Position; - Vector3 actorVelocity = actor.Velocity; - - actorPosition.X += actor.Velocity.X*timeStep; - actorPosition.Y += actor.Velocity.Y*timeStep; - - if (actor.Position.Y < 0) - { - actorPosition.Y = 0.1F; - } - else if (actor.Position.Y >= Constants.RegionSize) - { - actorPosition.Y = ((int)Constants.RegionSize - 0.1f); - } - - if (actor.Position.X < 0) - { - actorPosition.X = 0.1F; - } - else if (actor.Position.X >= Constants.RegionSize) - { - actorPosition.X = ((int)Constants.RegionSize - 0.1f); - } - - float terrainHeight = 0; - if (_heightMap != null) - terrainHeight = _heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X]; - - float height = terrainHeight + actor.Size.Z; - - if (actor.Flying) - { - if (actor.Position.Z + (actor.Velocity.Z * timeStep) < terrainHeight + 2) - { - actorPosition.Z = height; - actorVelocity.Z = 0; - actor.IsColliding = true; - } - else - { - actorPosition.Z += actor.Velocity.Z * timeStep; - actor.IsColliding = false; - } - } - else - { - actorPosition.Z = height; - actorVelocity.Z = 0; - actor.IsColliding = true; - } - - actor.Position = actorPosition; - actor.Velocity = actorVelocity; - } - - return fps; - } - - public override void GetResults() - { - } - - public override bool IsThreaded - { - get { return (false); // for now we won't be multithreaded - } - } - - public override void SetTerrain(float[] heightMap) - { - _heightMap = heightMap; - } - - public override void DeleteTerrain() - { - } - - public override void SetWaterLevel(float baseheight) - { - } - - public override Dictionary GetTopColliders() - { - Dictionary returncolliders = new Dictionary(); - return returncolliders; - } - } -} diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSNPlugin/BSCharacter.cs deleted file mode 100644 index d91c47f..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BSCharacter.cs +++ /dev/null @@ -1,814 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Reflection; -using log4net; -using OMV = OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.BulletSNPlugin -{ -public sealed class BSCharacter : BSPhysObject -{ - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private static readonly string LogHeader = "[BULLETS CHAR]"; - - // private bool _stopped; - private OMV.Vector3 _size; - private bool _grabbed; - private bool _selected; - private OMV.Vector3 _position; - private float _mass; - private float _avatarDensity; - private float _avatarVolume; - private OMV.Vector3 _force; - private OMV.Vector3 _velocity; - private OMV.Vector3 _torque; - private float _collisionScore; - private OMV.Vector3 _acceleration; - private OMV.Quaternion _orientation; - private int _physicsActorType; - private bool _isPhysical; - private bool _flying; - private bool _setAlwaysRun; - private bool _throttleUpdates; - private bool _isColliding; - private bool _collidingObj; - private bool _floatOnWater; - private OMV.Vector3 _rotationalVelocity; - private bool _kinematic; - private float _buoyancy; - - // The friction and velocity of the avatar is modified depending on whether walking or not. - private OMV.Vector3 _appliedVelocity; // the last velocity applied to the avatar - private float _currentFriction; // the friction currently being used (changed by setVelocity). - - private BSVMotor _velocityMotor; - - private OMV.Vector3 _PIDTarget; - private bool _usePID; - private float _PIDTau; - private bool _useHoverPID; - private float _PIDHoverHeight; - private PIDHoverType _PIDHoverType; - private float _PIDHoverTao; - - public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) - : base(parent_scene, localID, avName, "BSCharacter") - { - _physicsActorType = (int)ActorTypes.Agent; - _position = pos; - - // Old versions of ScenePresence passed only the height. If width and/or depth are zero, - // replace with the default values. - _size = size; - if (_size.X == 0f) _size.X = BSParam.AvatarCapsuleDepth; - if (_size.Y == 0f) _size.Y = BSParam.AvatarCapsuleWidth; - - // A motor to control the acceleration and deceleration of the avatar movement. - // _velocityMotor = new BSVMotor("BSCharacter.Velocity", 3f, 5f, BSMotor.InfiniteVector, 1f); - // _velocityMotor = new BSPIDVMotor("BSCharacter.Velocity", 3f, 5f, BSMotor.InfiniteVector, 1f); - // Infinite decay and timescale values so motor only changes current to target values. - _velocityMotor = new BSVMotor("BSCharacter.Velocity", - 0.2f, // time scale - BSMotor.Infinite, // decay time scale - BSMotor.InfiniteVector, // friction timescale - 1f // efficiency - ); - _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages. - - _flying = isFlying; - _orientation = OMV.Quaternion.Identity; - _velocity = OMV.Vector3.Zero; - _appliedVelocity = OMV.Vector3.Zero; - _buoyancy = ComputeBuoyancyFromFlying(isFlying); - _currentFriction = BSParam.AvatarStandingFriction; - _avatarDensity = BSParam.AvatarDensity; - - // The dimensions of the avatar capsule are kept in the scale. - // Physics creates a unit capsule which is scaled by the physics engine. - ComputeAvatarScale(_size); - // set _avatarVolume and _mass based on capsule size, _density and Scale - ComputeAvatarVolumeAndMass(); - DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", - LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass); - - // do actual creation in taint time - PhysicsScene.TaintedObject("BSCharacter.create", delegate() - { - DetailLog("{0},BSCharacter.create,taint", LocalID); - // New body and shape into PhysBody and PhysShape - PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this); - - SetPhysicalProperties(); - }); - return; - } - - // called when this character is being destroyed and the resources should be released - public override void Destroy() - { - base.Destroy(); - - DetailLog("{0},BSCharacter.Destroy", LocalID); - PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() - { - PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); - PhysBody.Clear(); - PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); - PhysShape.Clear(); - }); - } - - private void SetPhysicalProperties() - { - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr); - - ZeroMotion(true); - ForcePosition = _position; - // Set the velocity and compute the proper friction - ForceVelocity = _velocity; - // Setting the current and target in the motor will cause it to start computing any deceleration. - _velocityMotor.Reset(); - _velocityMotor.SetCurrent(_velocity); - _velocityMotor.SetTarget(_velocity); - _velocityMotor.Enabled = false; - - // This will enable or disable the flying buoyancy of the avatar. - // Needs to be reset especially when an avatar is recreated after crossing a region boundry. - Flying = _flying; - - BulletSimAPI.SetRestitution2(PhysBody.ptr, BSParam.AvatarRestitution); - BulletSimAPI.SetMargin2(PhysShape.ptr, PhysicsScene.Params.collisionMargin); - BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); - BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, BSParam.ContactProcessingThreshold); - if (BSParam.CcdMotionThreshold > 0f) - { - BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, BSParam.CcdMotionThreshold); - BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, BSParam.CcdSweptSphereRadius); - } - - UpdatePhysicalMassProperties(RawMass, false); - - // Make so capsule does not fall over - BulletSimAPI.SetAngularFactorV2(PhysBody.ptr, OMV.Vector3.Zero); - - BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); - - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr, _position, _orientation); - - // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); - BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_DEACTIVATION); - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); - - // Do this after the object has been added to the world - PhysBody.collisionType = CollisionType.Avatar; - PhysBody.ApplyCollisionMask(); - } - - public override void RequestPhysicsterseUpdate() - { - base.RequestPhysicsterseUpdate(); - } - // No one calls this method so I don't know what it could possibly mean - public override bool Stopped { get { return false; } } - - public override OMV.Vector3 Size { - get - { - // Avatar capsule size is kept in the scale parameter. - return _size; - } - - set { - // When an avatar's size is set, only the height is changed. - _size = value; - // Old versions of ScenePresence passed only the height. If width and/or depth are zero, - // replace with the default values. - if (_size.X == 0f) _size.X = BSParam.AvatarCapsuleDepth; - if (_size.Y == 0f) _size.Y = BSParam.AvatarCapsuleWidth; - - ComputeAvatarScale(_size); - ComputeAvatarVolumeAndMass(); - DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}", - LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass); - - PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() - { - if (PhysBody.HasPhysicalBody && PhysShape.HasPhysicalShape) - { - BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); - UpdatePhysicalMassProperties(RawMass, true); - // Make sure this change appears as a property update event - BulletSimAPI.PushUpdate2(PhysBody.ptr); - } - }); - - } - } - - public override PrimitiveBaseShape Shape - { - set { BaseShape = value; } - } - // I want the physics engine to make an avatar capsule - public override BSPhysicsShapeType PreferredPhysicalShape - { - get {return BSPhysicsShapeType.SHAPE_CAPSULE; } - } - - 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; } - - // Set motion values to zero. - // Do it to the properties so the values get set in the physics engine. - // Push the setting of the values to the viewer. - // Called at taint time! - public override void ZeroMotion(bool inTaintTime) - { - _velocity = OMV.Vector3.Zero; - _acceleration = OMV.Vector3.Zero; - _rotationalVelocity = OMV.Vector3.Zero; - - // Zero some other properties directly into the physics engine - PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() - { - if (PhysBody.HasPhysicalBody) - BulletSimAPI.ClearAllForces2(PhysBody.ptr); - }); - } - public override void ZeroAngularMotion(bool inTaintTime) - { - _rotationalVelocity = OMV.Vector3.Zero; - - PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() - { - if (PhysBody.HasPhysicalBody) - { - BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); - BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); - // The next also get rid of applied linear force but the linear velocity is untouched. - BulletSimAPI.ClearForces2(PhysBody.ptr); - } - }); - } - - - public override void LockAngularMotion(OMV.Vector3 axis) { return; } - - public override OMV.Vector3 RawPosition - { - get { return _position; } - set { _position = value; } - } - public override OMV.Vector3 Position { - get { - // Don't refetch the position because this function is called a zillion times - // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID); - return _position; - } - set { - _position = value; - PositionSanityCheck(); - - PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() - { - DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); - if (PhysBody.HasPhysicalBody) - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - }); - } - } - public override OMV.Vector3 ForcePosition { - get { - _position = BulletSimAPI.GetPosition2(PhysBody.ptr); - return _position; - } - set { - _position = value; - PositionSanityCheck(); - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - } - } - - - // Check that the current position is sane and, if not, modify the position to make it so. - // Check for being below terrain or on water. - // Returns 'true' of the position was made sane by some action. - private bool PositionSanityCheck() - { - bool ret = false; - - // TODO: check for out of bounds - if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(_position)) - { - // The character is out of the known/simulated area. - // Upper levels of code will handle the transition to other areas so, for - // the time, we just ignore the position. - return ret; - } - - // If below the ground, move the avatar up - float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); - if (Position.Z < terrainHeight) - { - DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); - _position.Z = terrainHeight + 2.0f; - ret = true; - } - if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) - { - float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position); - if (Position.Z < waterHeight) - { - _position.Z = waterHeight; - ret = true; - } - } - - return ret; - } - - // A version of the sanity check that also makes sure a new position value is - // pushed back to the physics engine. This routine would be used by anyone - // who is not already pushing the value. - private bool PositionSanityCheck(bool inTaintTime) - { - bool ret = false; - if (PositionSanityCheck()) - { - // The new position value must be pushed into the physics engine but we can't - // just assign to "Position" because of potential call loops. - PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() - { - DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); - if (PhysBody.HasPhysicalBody) - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - }); - ret = true; - } - return ret; - } - - public override float Mass { get { return _mass; } } - - // used when we only want this prim's mass and not the linkset thing - public override float RawMass { - get {return _mass; } - } - public override void UpdatePhysicalMassProperties(float physMass, bool inWorld) - { - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass); - BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia); - } - - public override OMV.Vector3 Force { - get { return _force; } - set { - _force = value; - // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); - PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() - { - DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); - if (PhysBody.HasPhysicalBody) - BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); - }); - } - } - - public bool TouchingGround() - { - bool ret = BulletSimAPI.RayCastGround(PhysicsScene.World.ptr,_position,_size.Z * 0.55f, PhysBody.ptr); - return ret; - } - // Avatars don't do vehicles - public override int VehicleType { get { return (int)Vehicle.TYPE_NONE; } set { return; } } - public override void VehicleFloatParam(int param, float value) { } - public override void VehicleVectorParam(int param, OMV.Vector3 value) {} - public override void VehicleRotationParam(int param, OMV.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 OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } } - public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } } - - // Sets the target in the motor. This starts the changing of the avatar's velocity. - public override OMV.Vector3 TargetVelocity - { - get - { - return _velocityMotor.TargetValue; - } - set - { - DetailLog("{0},BSCharacter.setTargetVelocity,call,vel={1}", LocalID, value); - - if (!_flying) - if ((value.Z >= 0.0001f) || (value.Z <= -0.0001f) || _velocity.Z < -0.0001f) - if (!TouchingGround()) - value.Z = _velocity.Z; - if (_setAlwaysRun) - value *= 1.3f; - - OMV.Vector3 targetVel = value; - - PhysicsScene.TaintedObject("BSCharacter.setTargetVelocity", delegate() - { - - _velocityMotor.Reset(); - _velocityMotor.SetTarget(targetVel); - _velocityMotor.SetCurrent(_velocity); - _velocityMotor.Enabled = true; - - // Make sure a property update happens next step so the motor gets incorporated. - BulletSimAPI.PushUpdate2(PhysBody.ptr); - }); - } - } - // Directly setting velocity means this is what the user really wants now. - public override OMV.Vector3 Velocity { - get { return _velocity; } - set { - _velocity = value; - // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); - PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() - { - _velocityMotor.Reset(); - _velocityMotor.SetCurrent(_velocity); - _velocityMotor.SetTarget(_velocity); - // Even though the motor is initialized, it's not used and the velocity goes straight into the avatar. - _velocityMotor.Enabled = false; - - DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); - ForceVelocity = _velocity; - }); - } - } - public override OMV.Vector3 ForceVelocity { - get { return _velocity; } - set { - PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity"); - - _velocity = value; - // Depending on whether the avatar is moving or not, change the friction - // to keep the avatar from slipping around - if (_velocity.Length() == 0) - { - if (_currentFriction != BSParam.AvatarStandingFriction) - { - _currentFriction = BSParam.AvatarStandingFriction; - if (PhysBody.HasPhysicalBody) - BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); - } - } - else - { - if (_currentFriction != BSParam.AvatarFriction) - { - _currentFriction = BSParam.AvatarFriction; - if (PhysBody.HasPhysicalBody) - BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); - } - } - // Remember the set velocity so we can suppress the reduction by friction, ... - _appliedVelocity = value; - - BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); - BulletSimAPI.Activate2(PhysBody.ptr, true); - } - } - public override OMV.Vector3 Torque { - get { return _torque; } - set { _torque = value; - } - } - public override float CollisionScore { - get { return _collisionScore; } - set { _collisionScore = value; - } - } - public override OMV.Vector3 Acceleration { - get { return _acceleration; } - set { _acceleration = value; } - } - public override OMV.Quaternion RawOrientation - { - get { return _orientation; } - set { _orientation = value; } - } - public override OMV.Quaternion Orientation { - get { return _orientation; } - set { - _orientation = value; - // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); - PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() - { - if (PhysBody.HasPhysicalBody) - { - // _position = BulletSimAPI.GetPosition2(BSBody.ptr); - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - } - }); - } - } - // Go directly to Bullet to get/set the value. - public override OMV.Quaternion ForceOrientation - { - get - { - _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr); - return _orientation; - } - set - { - _orientation = value; - BulletSimAPI.SetTranslation2(PhysBody.ptr, _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 IsSolid { - get { return true; } - } - public override bool IsStatic { - get { return false; } - } - public override bool Flying { - get { return _flying; } - set { - _flying = value; - - // simulate flying by changing the effect of gravity - Buoyancy = ComputeBuoyancyFromFlying(_flying); - } - } - // Flying is implimented by changing the avatar's buoyancy. - // Would this be done better with a vehicle type? - private float ComputeBuoyancyFromFlying(bool ifFlying) { - return ifFlying ? 1f : 0f; - } - 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 == PhysicsScene.SimulationStep); } - set { _isColliding = value; } - } - public override bool CollidingGround { - get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } - set { CollidingGround = value; } - } - public override bool CollidingObj { - get { return _collidingObj; } - set { _collidingObj = value; } - } - public override bool FloatOnWater { - set { - _floatOnWater = value; - PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() - { - if (PhysBody.HasPhysicalBody) - { - if (_floatOnWater) - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); - else - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); - } - }); - } - } - public override OMV.Vector3 RotationalVelocity { - get { return _rotationalVelocity; } - set { _rotationalVelocity = value; } - } - public override OMV.Vector3 ForceRotationalVelocity { - get { return _rotationalVelocity; } - set { _rotationalVelocity = value; } - } - public override bool Kinematic { - get { return _kinematic; } - set { _kinematic = value; } - } - // neg=fall quickly, 0=1g, 1=0g, pos=float up - public override float Buoyancy { - get { return _buoyancy; } - set { _buoyancy = value; - PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate() - { - DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - ForceBuoyancy = _buoyancy; - }); - } - } - public override float ForceBuoyancy { - get { return _buoyancy; } - set { - PhysicsScene.AssertInTaintTime("BSCharacter.ForceBuoyancy"); - - _buoyancy = value; - DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - // Buoyancy is faked by changing the gravity applied to the object - float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); - if (PhysBody.HasPhysicalBody) - BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); - } - } - - // Used for MoveTo - public override OMV.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 OMV.Quaternion APIDTarget { set { return; } } - public override bool APIDActive { set { return; } } - public override float APIDStrength { set { return; } } - public override float APIDDamping { set { return; } } - - public override void AddForce(OMV.Vector3 force, bool pushforce) { - if (force.IsFinite()) - { - _force.X += force.X; - _force.Y += force.Y; - _force.Z += force.Z; - // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); - PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate() - { - DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); - if (PhysBody.HasPhysicalBody) - BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); - }); - } - else - { - m_log.ErrorFormat("{0}: Got a NaN force applied to a Character", LogHeader); - } - //m_lastUpdateSent = false; - } - - public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { - } - public override void SetMomentum(OMV.Vector3 momentum) { - } - - private void ComputeAvatarScale(OMV.Vector3 size) - { - OMV.Vector3 newScale = size; - // newScale.X = PhysicsScene.Params.avatarCapsuleWidth; - // newScale.Y = PhysicsScene.Params.avatarCapsuleDepth; - - // From the total height, remove the capsule half spheres that are at each end - // The 1.15f came from ODE. Not sure what this factors in. - // newScale.Z = (size.Z * 1.15f) - (newScale.X + newScale.Y); - - // The total scale height is the central cylindar plus the caps on the two ends. - newScale.Z = size.Z + (Math.Min(size.X, size.Y) * 2f); - - // Convert diameters to radii and height to half height -- the way Bullet expects it. - Scale = newScale / 2f; - } - - // set _avatarVolume and _mass based on capsule size, _density and Scale - private void ComputeAvatarVolumeAndMass() - { - _avatarVolume = (float)( - Math.PI - * Scale.X - * Scale.Y // the area of capsule cylinder - * Scale.Z // times height of capsule cylinder - + 1.33333333f - * Math.PI - * Scale.X - * Math.Min(Scale.X, Scale.Y) - * Scale.Y // plus the volume of the capsule end caps - ); - _mass = _avatarDensity * _avatarVolume; - } - - // The physics engine says that properties have updated. Update same and inform - // the world that things have changed. - public override void UpdateProperties(EntityProperties entprop) - { - _position = entprop.Position; - _orientation = entprop.Rotation; - _velocity = entprop.Velocity; - _acceleration = entprop.Acceleration; - _rotationalVelocity = entprop.RotationalVelocity; - - // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. - PositionSanityCheck(true); - - if (_velocityMotor.Enabled) - { - // TODO: Decide if the step parameters should be changed depending on the avatar's - // state (flying, colliding, ...). - - OMV.Vector3 stepVelocity = _velocityMotor.Step(PhysicsScene.LastTimeStep); - - // If falling, we keep the world's downward vector no matter what the other axis specify. - if (!Flying && !IsColliding) - { - stepVelocity.Z = entprop.Velocity.Z; - DetailLog("{0},BSCharacter.UpdateProperties,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity); - } - - // If the user has said stop and we've stopped applying velocity correction, - // the motor can be turned off. Set the velocity to zero so the zero motion is sent to the viewer. - if (_velocityMotor.TargetValue.ApproxEquals(OMV.Vector3.Zero, 0.01f) && _velocityMotor.ErrorIsZero) - { - ZeroMotion(true); - stepVelocity = OMV.Vector3.Zero; - _velocityMotor.Enabled = false; - DetailLog("{0},BSCharacter.UpdateProperties,taint,disableVelocityMotor,m={1}", LocalID, _velocityMotor); - } - - _velocity = stepVelocity; - entprop.Velocity = _velocity; - BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); - } - - // remember the current and last set values - LastEntityProperties = CurrentEntityProperties; - CurrentEntityProperties = entprop; - - // Tell the linkset about value changes - Linkset.UpdateProperties(this, true); - - // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. - // base.RequestPhysicsterseUpdate(); - - DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", - LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); - } -} -} diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSNPlugin/BSConstraint.cs deleted file mode 100644 index f1bed39..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BSConstraint.cs +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSNPlugin -{ - -public abstract class BSConstraint : IDisposable -{ - private static string LogHeader = "[BULLETSIM CONSTRAINT]"; - - protected BulletWorld m_world; - protected BulletBody m_body1; - protected BulletBody m_body2; - protected BulletConstraint m_constraint; - protected bool m_enabled = false; - - public BulletBody Body1 { get { return m_body1; } } - public BulletBody Body2 { get { return m_body2; } } - public BulletConstraint Constraint { get { return m_constraint; } } - public abstract ConstraintType Type { get; } - public bool IsEnabled { get { return m_enabled; } } - - public BSConstraint() - { - } - - public virtual void Dispose() - { - if (m_enabled) - { - m_enabled = false; - if (m_constraint.HasPhysicalConstraint) - { - bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr); - m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}", - BSScene.DetailLogZero, - m_body1.ID, m_body1.ptr.ToString(), - m_body2.ID, m_body2.ptr.ToString(), - success); - m_constraint.Clear(); - } - } - } - - public virtual bool SetLinearLimits(Vector3 low, Vector3 high) - { - bool ret = false; - if (m_enabled) - ret = BulletSimAPI.SetLinearLimits2(m_constraint.ptr, low, high); - return ret; - } - - public virtual bool SetAngularLimits(Vector3 low, Vector3 high) - { - bool ret = false; - if (m_enabled) - ret = BulletSimAPI.SetAngularLimits2(m_constraint.ptr, low, high); - return ret; - } - - public virtual bool SetSolverIterations(float cnt) - { - bool ret = false; - if (m_enabled) - { - BulletSimAPI.SetConstraintNumSolverIterations2(m_constraint.ptr, cnt); - ret = true; - } - return ret; - } - - public virtual bool CalculateTransforms() - { - bool ret = false; - if (m_enabled) - { - // Recompute the internal transforms - BulletSimAPI.CalculateTransforms2(m_constraint.ptr); - ret = true; - } - return ret; - } - - // Reset this constraint making sure it has all its internal structures - // recomputed and is enabled and ready to go. - public virtual bool RecomputeConstraintVariables(float mass) - { - bool ret = false; - if (m_enabled) - { - ret = CalculateTransforms(); - if (ret) - { - // Setting an object's mass to zero (making it static like when it's selected) - // automatically disables the constraints. - // If the link is enabled, be sure to set the constraint itself to enabled. - BulletSimAPI.SetConstraintEnable2(m_constraint.ptr, BSParam.NumericBool(true)); - } - else - { - m_world.physicsScene.Logger.ErrorFormat("{0} CalculateTransforms failed. A={1}, B={2}", LogHeader, Body1.ID, Body2.ID); - } - } - return ret; - } -} -} diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSConstraint6Dof.cs b/OpenSim/Region/Physics/BulletSNPlugin/BSConstraint6Dof.cs deleted file mode 100644 index d1e3f55..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BSConstraint6Dof.cs +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSNPlugin -{ - -public sealed class BSConstraint6Dof : BSConstraint -{ - private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]"; - - public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } } - - // Create a btGeneric6DofConstraint - public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2, - Vector3 frame1, Quaternion frame1rot, - Vector3 frame2, Quaternion frame2rot, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) - { - m_world = world; - m_body1 = obj1; - m_body2 = obj2; - m_constraint = new BulletConstraint( - BulletSimAPI.Create6DofConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr, - frame1, frame1rot, - frame2, frame2rot, - useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); - m_enabled = true; - world.physicsScene.DetailLog("{0},BS6DofConstraint,createFrame,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", - BSScene.DetailLogZero, world.worldID, - obj1.ID, obj1.ptr.ToString(), obj2.ID, obj2.ptr.ToString()); - } - - public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2, - Vector3 joinPoint, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) - { - m_world = world; - m_body1 = obj1; - m_body2 = obj2; - if (!obj1.HasPhysicalBody || !obj2.HasPhysicalBody) - { - world.physicsScene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", - BSScene.DetailLogZero, world.worldID, - obj1.ID, obj1.ptr.ToString(), obj2.ID, obj2.ptr.ToString()); - world.physicsScene.Logger.ErrorFormat("{0} Attempt to build 6DOF constraint with missing bodies: wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", - LogHeader, world.worldID, obj1.ID, obj1.ptr.ToString(), obj2.ID, obj2.ptr.ToString()); - m_enabled = false; - } - else - { - m_constraint = new BulletConstraint( - BulletSimAPI.Create6DofConstraintToPoint2(m_world.ptr, m_body1.ptr, m_body2.ptr, - joinPoint, - useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); - world.physicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}", - BSScene.DetailLogZero, world.worldID, m_constraint.ptr.ToString(), - obj1.ID, obj1.ptr.ToString(), obj2.ID, obj2.ptr.ToString()); - if (!m_constraint.HasPhysicalConstraint) - { - world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}", - LogHeader, obj1.ID, obj2.ID); - m_enabled = false; - } - else - { - m_enabled = true; - } - } - } - - public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) - { - bool ret = false; - if (m_enabled) - { - BulletSimAPI.SetFrames2(m_constraint.ptr, frameA, frameArot, frameB, frameBrot); - ret = true; - } - return ret; - } - - public bool SetCFMAndERP(float cfm, float erp) - { - bool ret = false; - if (m_enabled) - { - BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); - BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); - BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); - ret = true; - } - return ret; - } - - public bool UseFrameOffset(bool useOffset) - { - bool ret = false; - float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; - if (m_enabled) - ret = BulletSimAPI.UseFrameOffset2(m_constraint.ptr, onOff); - return ret; - } - - public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce) - { - bool ret = false; - float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; - if (m_enabled) - { - ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.ptr, onOff, targetVelocity, maxMotorForce); - m_world.physicsScene.DetailLog("{0},BS6DOFConstraint,TransLimitMotor,enable={1},vel={2},maxForce={3}", - BSScene.DetailLogZero, enable, targetVelocity, maxMotorForce); - } - return ret; - } - - public bool SetBreakingImpulseThreshold(float threshold) - { - bool ret = false; - if (m_enabled) - ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.ptr, threshold); - return ret; - } -} -} diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSNPlugin/BSConstraintCollection.cs deleted file mode 100644 index 87d1e44..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BSConstraintCollection.cs +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using log4net; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSNPlugin -{ - -public sealed class BSConstraintCollection : IDisposable -{ - // private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - // private static readonly string LogHeader = "[CONSTRAINT COLLECTION]"; - - delegate bool ConstraintAction(BSConstraint constrain); - - private List m_constraints; - private BulletWorld m_world; - - public BSConstraintCollection(BulletWorld world) - { - m_world = world; - m_constraints = new List(); - } - - public void Dispose() - { - this.Clear(); - } - - public void Clear() - { - lock (m_constraints) - { - foreach (BSConstraint cons in m_constraints) - { - cons.Dispose(); - } - m_constraints.Clear(); - } - } - - public bool AddConstraint(BSConstraint cons) - { - lock (m_constraints) - { - // There is only one constraint between any bodies. Remove any old just to make sure. - RemoveAndDestroyConstraint(cons.Body1, cons.Body2); - - m_constraints.Add(cons); - } - - return true; - } - - // Get the constraint between two bodies. There can be only one. - // Return 'true' if a constraint was found. - public bool TryGetConstraint(BulletBody body1, BulletBody body2, out BSConstraint returnConstraint) - { - bool found = false; - BSConstraint foundConstraint = null; - - uint lookingID1 = body1.ID; - uint lookingID2 = body2.ID; - lock (m_constraints) - { - foreach (BSConstraint constrain in m_constraints) - { - if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2) - || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1)) - { - foundConstraint = constrain; - found = true; - break; - } - } - } - returnConstraint = foundConstraint; - return found; - } - - // Remove any constraint between the passed bodies. - // Presumed there is only one such constraint possible. - // Return 'true' if a constraint was found and destroyed. - public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2) - { - bool ret = false; - lock (m_constraints) - { - BSConstraint constrain; - if (this.TryGetConstraint(body1, body2, out constrain)) - { - // remove the constraint from our collection - RemoveAndDestroyConstraint(constrain); - ret = true; - } - } - - return ret; - } - - // The constraint MUST exist in the collection - public bool RemoveAndDestroyConstraint(BSConstraint constrain) - { - lock (m_constraints) - { - // remove the constraint from our collection - m_constraints.Remove(constrain); - } - // tell the engine that all its structures need to be freed - constrain.Dispose(); - // we destroyed something - return true; - } - - // Remove all constraints that reference the passed body. - // Return 'true' if any constraints were destroyed. - public bool RemoveAndDestroyConstraint(BulletBody body1) - { - List toRemove = new List(); - uint lookingID = body1.ID; - lock (m_constraints) - { - foreach (BSConstraint constrain in m_constraints) - { - if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID) - { - toRemove.Add(constrain); - } - } - foreach (BSConstraint constrain in toRemove) - { - m_constraints.Remove(constrain); - constrain.Dispose(); - } - } - return (toRemove.Count > 0); - } - - public bool RecalculateAllConstraints() - { - bool ret = false; - lock (m_constraints) - { - foreach (BSConstraint constrain in m_constraints) - { - constrain.CalculateTransforms(); - ret = true; - } - } - return ret; - } -} -} diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSConstraintHinge.cs b/OpenSim/Region/Physics/BulletSNPlugin/BSConstraintHinge.cs deleted file mode 100644 index fbd1bc0..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BSConstraintHinge.cs +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSNPlugin -{ - -public sealed class BSConstraintHinge : BSConstraint -{ - public override ConstraintType Type { get { return ConstraintType.HINGE_CONSTRAINT_TYPE; } } - - public BSConstraintHinge(BulletWorld world, BulletBody obj1, BulletBody obj2, - Vector3 pivotInA, Vector3 pivotInB, - Vector3 axisInA, Vector3 axisInB, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) - { - m_world = world; - m_body1 = obj1; - m_body2 = obj2; - m_constraint = new BulletConstraint( - BulletSimAPI.CreateHingeConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr, - pivotInA, pivotInB, - axisInA, axisInB, - useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); - m_enabled = true; - } - -} - -} diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSNPlugin/BSDynamics.cs deleted file mode 100644 index 415ad4f..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BSDynamics.cs +++ /dev/null @@ -1,1377 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The quotations from http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial - * are Copyright (c) 2009 Linden Research, Inc and are used under their license - * of Creative Commons Attribution-Share Alike 3.0 - * (http://creativecommons.org/licenses/by-sa/3.0/). - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Runtime.InteropServices; -using OpenMetaverse; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.BulletSNPlugin -{ - public sealed class BSDynamics - { - private static string LogHeader = "[BULLETSIM VEHICLE]"; - - private BSScene PhysicsScene { get; set; } - // the prim this dynamic controller belongs to - private BSPrim Prim { get; set; } - - // mass of the vehicle fetched each time we're calles - private float m_vehicleMass; - - // Vehicle properties - public Vehicle Type { get; set; } - - // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier - private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings: - // HOVER_TERRAIN_ONLY - // HOVER_GLOBAL_HEIGHT - // NO_DEFLECTION_UP - // HOVER_WATER_ONLY - // HOVER_UP_ONLY - // LIMIT_MOTOR_UP - // LIMIT_ROLL_ONLY - private Vector3 m_BlockingEndPoint = Vector3.Zero; - private Quaternion m_RollreferenceFrame = Quaternion.Identity; - private Quaternion m_referenceFrame = Quaternion.Identity; - - // Linear properties - private BSVMotor m_linearMotor = new BSVMotor("LinearMotor"); - private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time - private Vector3 m_linearMotorOffset = Vector3.Zero; // the point of force can be offset from the center - private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL - private Vector3 m_linearFrictionTimescale = Vector3.Zero; - private float m_linearMotorDecayTimescale = 0; - private float m_linearMotorTimescale = 0; - private Vector3 m_lastLinearVelocityVector = Vector3.Zero; - private Vector3 m_lastPositionVector = Vector3.Zero; - // private bool m_LinearMotorSetLastFrame = false; - // private Vector3 m_linearMotorOffset = Vector3.Zero; - - //Angular properties - private BSVMotor m_angularMotor = new BSVMotor("AngularMotor"); - private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor - // private int m_angularMotorApply = 0; // application frame counter - private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity - private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate - private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate - private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate - private Vector3 m_lastAngularVelocity = Vector3.Zero; - private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body - - //Deflection properties - private BSVMotor m_angularDeflectionMotor = new BSVMotor("AngularDeflection"); - private float m_angularDeflectionEfficiency = 0; - private float m_angularDeflectionTimescale = 0; - private float m_linearDeflectionEfficiency = 0; - private float m_linearDeflectionTimescale = 0; - - //Banking properties - private float m_bankingEfficiency = 0; - private float m_bankingMix = 0; - private float m_bankingTimescale = 0; - - //Hover and Buoyancy properties - private BSVMotor m_hoverMotor = new BSVMotor("Hover"); - private float m_VhoverHeight = 0f; - private float m_VhoverEfficiency = 0f; - private float m_VhoverTimescale = 0f; - private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height - private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. - // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity) - // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity. - // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity. - - //Attractor properties - private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction"); - private float m_verticalAttractionEfficiency = 1.0f; // damped - private float m_verticalAttractionCutoff = 500f; // per the documentation - // Timescale > cutoff means no vert attractor. - private float m_verticalAttractionTimescale = 510f; - - // Just some recomputed constants: - static readonly float PIOverFour = ((float)Math.PI) / 4f; - static readonly float PIOverTwo = ((float)Math.PI) / 2f; - - public BSDynamics(BSScene myScene, BSPrim myPrim) - { - PhysicsScene = myScene; - Prim = myPrim; - Type = Vehicle.TYPE_NONE; - } - - // Return 'true' if this vehicle is doing vehicle things - public bool IsActive - { - get { return Type != Vehicle.TYPE_NONE && Prim.IsPhysical; } - } - - internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) - { - VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); - switch (pParam) - { - case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: - m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f); - break; - case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: - m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); - break; - case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: - m_angularMotorDecayTimescale = ClampInRange(0.01f, pValue, 120); - m_angularMotor.TargetValueDecayTimeScale = m_angularMotorDecayTimescale; - break; - case Vehicle.ANGULAR_MOTOR_TIMESCALE: - m_angularMotorTimescale = Math.Max(pValue, 0.01f); - m_angularMotor.TimeScale = m_angularMotorTimescale; - break; - case Vehicle.BANKING_EFFICIENCY: - m_bankingEfficiency = ClampInRange(-1f, pValue, 1f); - break; - case Vehicle.BANKING_MIX: - m_bankingMix = Math.Max(pValue, 0.01f); - break; - case Vehicle.BANKING_TIMESCALE: - m_bankingTimescale = Math.Max(pValue, 0.01f); - break; - case Vehicle.BUOYANCY: - m_VehicleBuoyancy = ClampInRange(-1f, pValue, 1f); - break; - case Vehicle.HOVER_EFFICIENCY: - m_VhoverEfficiency = ClampInRange(0f, pValue, 1f); - break; - case Vehicle.HOVER_HEIGHT: - m_VhoverHeight = pValue; - break; - case Vehicle.HOVER_TIMESCALE: - m_VhoverTimescale = Math.Max(pValue, 0.01f); - break; - case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: - m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f); - break; - case Vehicle.LINEAR_DEFLECTION_TIMESCALE: - m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); - break; - case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: - m_linearMotorDecayTimescale = ClampInRange(0.01f, pValue, 120); - m_linearMotor.TargetValueDecayTimeScale = m_linearMotorDecayTimescale; - break; - case Vehicle.LINEAR_MOTOR_TIMESCALE: - m_linearMotorTimescale = Math.Max(pValue, 0.01f); - m_linearMotor.TimeScale = m_linearMotorTimescale; - break; - case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: - m_verticalAttractionEfficiency = ClampInRange(0.1f, pValue, 1f); - m_verticalAttractionMotor.Efficiency = m_verticalAttractionEfficiency; - break; - case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: - m_verticalAttractionTimescale = Math.Max(pValue, 0.01f); - m_verticalAttractionMotor.TimeScale = m_verticalAttractionTimescale; - break; - - // These are vector properties but the engine lets you use a single float value to - // set all of the components to the same value - case Vehicle.ANGULAR_FRICTION_TIMESCALE: - m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); - m_angularMotor.FrictionTimescale = m_angularFrictionTimescale; - break; - case Vehicle.ANGULAR_MOTOR_DIRECTION: - m_angularMotorDirection = new Vector3(pValue, pValue, pValue); - m_angularMotor.SetTarget(m_angularMotorDirection); - break; - case Vehicle.LINEAR_FRICTION_TIMESCALE: - m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); - m_linearMotor.FrictionTimescale = m_linearFrictionTimescale; - break; - case Vehicle.LINEAR_MOTOR_DIRECTION: - m_linearMotorDirection = new Vector3(pValue, pValue, pValue); - m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); - m_linearMotor.SetTarget(m_linearMotorDirection); - break; - case Vehicle.LINEAR_MOTOR_OFFSET: - m_linearMotorOffset = new Vector3(pValue, pValue, pValue); - break; - - } - }//end ProcessFloatVehicleParam - - internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) - { - VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); - switch (pParam) - { - case Vehicle.ANGULAR_FRICTION_TIMESCALE: - m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); - m_angularMotor.FrictionTimescale = m_angularFrictionTimescale; - break; - case Vehicle.ANGULAR_MOTOR_DIRECTION: - // Limit requested angular speed to 2 rps= 4 pi rads/sec - pValue.X = ClampInRange(-12.56f, pValue.X, 12.56f); - pValue.Y = ClampInRange(-12.56f, pValue.Y, 12.56f); - pValue.Z = ClampInRange(-12.56f, pValue.Z, 12.56f); - m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); - m_angularMotor.SetTarget(m_angularMotorDirection); - break; - case Vehicle.LINEAR_FRICTION_TIMESCALE: - m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); - m_linearMotor.FrictionTimescale = m_linearFrictionTimescale; - break; - case Vehicle.LINEAR_MOTOR_DIRECTION: - m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); - m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); - m_linearMotor.SetTarget(m_linearMotorDirection); - break; - case Vehicle.LINEAR_MOTOR_OFFSET: - m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); - break; - case Vehicle.BLOCK_EXIT: - m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z); - break; - } - }//end ProcessVectorVehicleParam - - internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) - { - VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); - switch (pParam) - { - case Vehicle.REFERENCE_FRAME: - m_referenceFrame = pValue; - break; - case Vehicle.ROLL_FRAME: - m_RollreferenceFrame = pValue; - break; - } - }//end ProcessRotationVehicleParam - - internal void ProcessVehicleFlags(int pParam, bool remove) - { - VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", Prim.LocalID, pParam, remove); - VehicleFlag parm = (VehicleFlag)pParam; - if (pParam == -1) - m_flags = (VehicleFlag)0; - else - { - if (remove) - m_flags &= ~parm; - else - m_flags |= parm; - } - } - - internal void ProcessTypeChange(Vehicle pType) - { - VDetailLog("{0},ProcessTypeChange,type={1}", Prim.LocalID, pType); - // Set Defaults For Type - Type = pType; - switch (pType) - { - case Vehicle.TYPE_NONE: - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 0; - m_linearMotorDecayTimescale = 0; - m_linearFrictionTimescale = new Vector3(0, 0, 0); - - m_angularMotorDirection = Vector3.Zero; - m_angularMotorDecayTimescale = 0; - m_angularMotorTimescale = 0; - m_angularFrictionTimescale = new Vector3(0, 0, 0); - - m_VhoverHeight = 0; - m_VhoverEfficiency = 0; - m_VhoverTimescale = 0; - m_VehicleBuoyancy = 0; - - m_linearDeflectionEfficiency = 1; - m_linearDeflectionTimescale = 1; - - m_angularDeflectionEfficiency = 0; - m_angularDeflectionTimescale = 1000; - - m_verticalAttractionEfficiency = 0; - m_verticalAttractionTimescale = 0; - - m_bankingEfficiency = 0; - m_bankingTimescale = 1000; - m_bankingMix = 1; - - m_referenceFrame = Quaternion.Identity; - m_flags = (VehicleFlag)0; - - break; - - case Vehicle.TYPE_SLED: - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 1000; - m_linearMotorDecayTimescale = 120; - m_linearFrictionTimescale = new Vector3(30, 1, 1000); - - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 1000; - m_angularMotorDecayTimescale = 120; - m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); - - m_VhoverHeight = 0; - m_VhoverEfficiency = 10; // TODO: this looks wrong!! - m_VhoverTimescale = 10; - m_VehicleBuoyancy = 0; - - m_linearDeflectionEfficiency = 1; - m_linearDeflectionTimescale = 1; - - m_angularDeflectionEfficiency = 1; - m_angularDeflectionTimescale = 1000; - - m_verticalAttractionEfficiency = 0; - m_verticalAttractionTimescale = 0; - - m_bankingEfficiency = 0; - m_bankingTimescale = 10; - m_bankingMix = 1; - - m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY - | VehicleFlag.HOVER_TERRAIN_ONLY - | VehicleFlag.HOVER_GLOBAL_HEIGHT - | VehicleFlag.HOVER_UP_ONLY); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP - | VehicleFlag.LIMIT_ROLL_ONLY - | VehicleFlag.LIMIT_MOTOR_UP); - - break; - case Vehicle.TYPE_CAR: - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 1; - m_linearMotorDecayTimescale = 60; - m_linearFrictionTimescale = new Vector3(100, 2, 1000); - - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 1; - m_angularMotorDecayTimescale = 0.8f; - m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); - - m_VhoverHeight = 0; - m_VhoverEfficiency = 0; - m_VhoverTimescale = 1000; - m_VehicleBuoyancy = 0; - - m_linearDeflectionEfficiency = 1; - m_linearDeflectionTimescale = 2; - - m_angularDeflectionEfficiency = 0; - m_angularDeflectionTimescale = 10; - - m_verticalAttractionEfficiency = 1f; - m_verticalAttractionTimescale = 10f; - - m_bankingEfficiency = -0.2f; - m_bankingMix = 1; - m_bankingTimescale = 1; - - m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY - | VehicleFlag.HOVER_TERRAIN_ONLY - | VehicleFlag.HOVER_GLOBAL_HEIGHT); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP - | VehicleFlag.LIMIT_ROLL_ONLY - | VehicleFlag.LIMIT_MOTOR_UP - | VehicleFlag.HOVER_UP_ONLY); - break; - case Vehicle.TYPE_BOAT: - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 5; - m_linearMotorDecayTimescale = 60; - m_linearFrictionTimescale = new Vector3(10, 3, 2); - - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 4; - m_angularMotorDecayTimescale = 4; - m_angularFrictionTimescale = new Vector3(10,10,10); - - m_VhoverHeight = 0; - m_VhoverEfficiency = 0.5f; - m_VhoverTimescale = 2; - m_VehicleBuoyancy = 1; - - m_linearDeflectionEfficiency = 0.5f; - m_linearDeflectionTimescale = 3; - - m_angularDeflectionEfficiency = 0.5f; - m_angularDeflectionTimescale = 5; - - m_verticalAttractionEfficiency = 0.5f; - m_verticalAttractionTimescale = 5f; - - m_bankingEfficiency = -0.3f; - m_bankingMix = 0.8f; - m_bankingTimescale = 1; - - m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY - | VehicleFlag.HOVER_GLOBAL_HEIGHT - | VehicleFlag.LIMIT_ROLL_ONLY - | VehicleFlag.HOVER_UP_ONLY); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP - | VehicleFlag.LIMIT_MOTOR_UP - | VehicleFlag.HOVER_WATER_ONLY); - break; - case Vehicle.TYPE_AIRPLANE: - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 2; - m_linearMotorDecayTimescale = 60; - m_linearFrictionTimescale = new Vector3(200, 10, 5); - - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 4; - m_angularMotorDecayTimescale = 4; - m_angularFrictionTimescale = new Vector3(20, 20, 20); - - m_VhoverHeight = 0; - m_VhoverEfficiency = 0.5f; - m_VhoverTimescale = 1000; - m_VehicleBuoyancy = 0; - - m_linearDeflectionEfficiency = 0.5f; - m_linearDeflectionTimescale = 3; - - m_angularDeflectionEfficiency = 1; - m_angularDeflectionTimescale = 2; - - m_verticalAttractionEfficiency = 0.9f; - m_verticalAttractionTimescale = 2f; - - m_bankingEfficiency = 1; - m_bankingMix = 0.7f; - m_bankingTimescale = 2; - - m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY - | VehicleFlag.HOVER_TERRAIN_ONLY - | VehicleFlag.HOVER_GLOBAL_HEIGHT - | VehicleFlag.HOVER_UP_ONLY - | VehicleFlag.NO_DEFLECTION_UP - | VehicleFlag.LIMIT_MOTOR_UP); - m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); - break; - case Vehicle.TYPE_BALLOON: - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 5; - m_linearFrictionTimescale = new Vector3(5, 5, 5); - m_linearMotorDecayTimescale = 60; - - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 6; - m_angularFrictionTimescale = new Vector3(10, 10, 10); - m_angularMotorDecayTimescale = 10; - - m_VhoverHeight = 5; - m_VhoverEfficiency = 0.8f; - m_VhoverTimescale = 10; - m_VehicleBuoyancy = 1; - - m_linearDeflectionEfficiency = 0; - m_linearDeflectionTimescale = 5; - - m_angularDeflectionEfficiency = 0; - m_angularDeflectionTimescale = 5; - - m_verticalAttractionEfficiency = 1f; - m_verticalAttractionTimescale = 100f; - - m_bankingEfficiency = 0; - m_bankingMix = 0.7f; - m_bankingTimescale = 5; - - m_referenceFrame = Quaternion.Identity; - - m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY - | VehicleFlag.HOVER_TERRAIN_ONLY - | VehicleFlag.HOVER_UP_ONLY - | VehicleFlag.NO_DEFLECTION_UP - | VehicleFlag.LIMIT_MOTOR_UP); - m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY - | VehicleFlag.HOVER_GLOBAL_HEIGHT); - break; - } - - // Update any physical parameters based on this type. - Refresh(); - - m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, - m_linearMotorDecayTimescale, m_linearFrictionTimescale, - 1f); - m_linearMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) - - m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, - m_angularMotorDecayTimescale, m_angularFrictionTimescale, - 1f); - m_angularMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) - - m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale, - BSMotor.Infinite, BSMotor.InfiniteVector, - m_verticalAttractionEfficiency); - // Z goes away and we keep X and Y - m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f); - m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) - } - - // Some of the properties of this prim may have changed. - // Do any updating needed for a vehicle - public void Refresh() - { - if (IsActive) - { - // Remember the mass so we don't have to fetch it every step - m_vehicleMass = Prim.Linkset.LinksetMass; - - // Friction affects are handled by this vehicle code - float friction = 0f; - BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, friction); - - // Moderate angular movement introduced by Bullet. - // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle. - // Maybe compute linear and angular factor and damping from params. - float angularDamping = BSParam.VehicleAngularDamping; - BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, angularDamping); - - // Vehicles report collision events so we know when it's on the ground - BulletSimAPI.AddToCollisionFlags2(Prim.PhysBody.ptr, CollisionFlags.BS_VEHICLE_COLLISIONS); - - Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(Prim.PhysShape.ptr, m_vehicleMass); - BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia); - BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr); - - Vector3 grav = PhysicsScene.DefaultGravity * (1f - Prim.Buoyancy); - BulletSimAPI.SetGravity2(Prim.PhysBody.ptr, grav); - - VDetailLog("{0},BSDynamics.Refresh,mass={1},frict={2},inert={3},aDamp={4}", - Prim.LocalID, m_vehicleMass, friction, localInertia, angularDamping); - } - else - { - BulletSimAPI.RemoveFromCollisionFlags2(Prim.PhysBody.ptr, CollisionFlags.BS_VEHICLE_COLLISIONS); - } - } - - public bool RemoveBodyDependencies(BSPhysObject prim) - { - // If active, we need to add our properties back when the body is rebuilt. - return IsActive; - } - - public void RestoreBodyDependencies(BSPhysObject prim) - { - if (Prim.LocalID != prim.LocalID) - { - // The call should be on us by our prim. Error if not. - PhysicsScene.Logger.ErrorFormat("{0} RestoreBodyDependencies: called by not my prim. passedLocalID={1}, vehiclePrimLocalID={2}", - LogHeader, prim.LocalID, Prim.LocalID); - return; - } - Refresh(); - } - - #region Known vehicle value functions - // Vehicle physical parameters that we buffer from constant getting and setting. - // The "m_known*" values are unknown until they are fetched and the m_knownHas flag is set. - // Changing is remembered and the parameter is stored back into the physics engine only if updated. - // This does two things: 1) saves continuious calls into unmanaged code, and - // 2) signals when a physics property update must happen back to the simulator - // to update values modified for the vehicle. - private int m_knownChanged; - private int m_knownHas; - private float m_knownTerrainHeight; - private float m_knownWaterLevel; - private Vector3 m_knownPosition; - private Vector3 m_knownVelocity; - private Vector3 m_knownForce; - private Quaternion m_knownOrientation; - private Vector3 m_knownRotationalVelocity; - private Vector3 m_knownRotationalForce; - private Vector3 m_knownForwardVelocity; // vehicle relative forward speed - - private const int m_knownChangedPosition = 1 << 0; - private const int m_knownChangedVelocity = 1 << 1; - private const int m_knownChangedForce = 1 << 2; - private const int m_knownChangedOrientation = 1 << 3; - private const int m_knownChangedRotationalVelocity = 1 << 4; - private const int m_knownChangedRotationalForce = 1 << 5; - private const int m_knownChangedTerrainHeight = 1 << 6; - private const int m_knownChangedWaterLevel = 1 << 7; - private const int m_knownChangedForwardVelocity = 1 << 8; - - private void ForgetKnownVehicleProperties() - { - m_knownHas = 0; - m_knownChanged = 0; - } - // Push all the changed values back into the physics engine - private void PushKnownChanged() - { - if (m_knownChanged != 0) - { - if ((m_knownChanged & m_knownChangedPosition) != 0) - Prim.ForcePosition = m_knownPosition; - - if ((m_knownChanged & m_knownChangedOrientation) != 0) - Prim.ForceOrientation = m_knownOrientation; - - if ((m_knownChanged & m_knownChangedVelocity) != 0) - { - Prim.ForceVelocity = m_knownVelocity; - BulletSimAPI.SetInterpolationLinearVelocity2(Prim.PhysBody.ptr, VehicleVelocity); - } - - if ((m_knownChanged & m_knownChangedForce) != 0) - Prim.AddForce((Vector3)m_knownForce, false, true); - - if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0) - { - Prim.ForceRotationalVelocity = m_knownRotationalVelocity; - // Fake out Bullet by making it think the velocity is the same as last time. - BulletSimAPI.SetInterpolationAngularVelocity2(Prim.PhysBody.ptr, m_knownRotationalVelocity); - } - - if ((m_knownChanged & m_knownChangedRotationalForce) != 0) - Prim.AddAngularForce((Vector3)m_knownRotationalForce, false, true); - - // If we set one of the values (ie, the physics engine didn't do it) we must force - // an UpdateProperties event to send the changes up to the simulator. - BulletSimAPI.PushUpdate2(Prim.PhysBody.ptr); - } - m_knownChanged = 0; - } - - // Since the computation of terrain height can be a little involved, this routine - // is used to fetch the height only once for each vehicle simulation step. - private float GetTerrainHeight(Vector3 pos) - { - if ((m_knownHas & m_knownChangedTerrainHeight) == 0) - { - m_knownTerrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); - m_knownHas |= m_knownChangedTerrainHeight; - } - return m_knownTerrainHeight; - } - - // Since the computation of water level can be a little involved, this routine - // is used ot fetch the level only once for each vehicle simulation step. - private float GetWaterLevel(Vector3 pos) - { - if ((m_knownHas & m_knownChangedWaterLevel) == 0) - { - m_knownWaterLevel = Prim.PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(pos); - m_knownHas |= m_knownChangedWaterLevel; - } - return (float)m_knownWaterLevel; - } - - private Vector3 VehiclePosition - { - get - { - if ((m_knownHas & m_knownChangedPosition) == 0) - { - m_knownPosition = Prim.ForcePosition; - m_knownHas |= m_knownChangedPosition; - } - return m_knownPosition; - } - set - { - m_knownPosition = value; - m_knownChanged |= m_knownChangedPosition; - m_knownHas |= m_knownChangedPosition; - } - } - - private Quaternion VehicleOrientation - { - get - { - if ((m_knownHas & m_knownChangedOrientation) == 0) - { - m_knownOrientation = Prim.ForceOrientation; - m_knownHas |= m_knownChangedOrientation; - } - return m_knownOrientation; - } - set - { - m_knownOrientation = value; - m_knownChanged |= m_knownChangedOrientation; - m_knownHas |= m_knownChangedOrientation; - } - } - - private Vector3 VehicleVelocity - { - get - { - if ((m_knownHas & m_knownChangedVelocity) == 0) - { - m_knownVelocity = Prim.ForceVelocity; - m_knownHas |= m_knownChangedVelocity; - } - return (Vector3)m_knownVelocity; - } - set - { - m_knownVelocity = value; - m_knownChanged |= m_knownChangedVelocity; - m_knownHas |= m_knownChangedVelocity; - } - } - - private void VehicleAddForce(Vector3 aForce) - { - if ((m_knownHas & m_knownChangedForce) == 0) - { - m_knownForce = Vector3.Zero; - } - m_knownForce += aForce; - m_knownChanged |= m_knownChangedForce; - m_knownHas |= m_knownChangedForce; - } - - private Vector3 VehicleRotationalVelocity - { - get - { - if ((m_knownHas & m_knownChangedRotationalVelocity) == 0) - { - m_knownRotationalVelocity = Prim.ForceRotationalVelocity; - m_knownHas |= m_knownChangedRotationalVelocity; - } - return (Vector3)m_knownRotationalVelocity; - } - set - { - m_knownRotationalVelocity = value; - m_knownChanged |= m_knownChangedRotationalVelocity; - m_knownHas |= m_knownChangedRotationalVelocity; - } - } - private void VehicleAddAngularForce(Vector3 aForce) - { - if ((m_knownHas & m_knownChangedRotationalForce) == 0) - { - m_knownRotationalForce = Vector3.Zero; - } - m_knownRotationalForce += aForce; - m_knownChanged |= m_knownChangedRotationalForce; - m_knownHas |= m_knownChangedRotationalForce; - } - // Vehicle relative forward velocity - private Vector3 VehicleForwardVelocity - { - get - { - if ((m_knownHas & m_knownChangedForwardVelocity) == 0) - { - m_knownForwardVelocity = VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation)); - m_knownHas |= m_knownChangedForwardVelocity; - } - return m_knownForwardVelocity; - } - } - private float VehicleForwardSpeed - { - get - { - return VehicleForwardVelocity.X; - } - } - - #endregion // Known vehicle value functions - - // One step of the vehicle properties for the next 'pTimestep' seconds. - internal void Step(float pTimestep) - { - if (!IsActive) return; - - ForgetKnownVehicleProperties(); - - MoveLinear(pTimestep); - MoveAngular(pTimestep); - - LimitRotation(pTimestep); - - // remember the position so next step we can limit absolute movement effects - m_lastPositionVector = VehiclePosition; - - // If we forced the changing of some vehicle parameters, update the values and - // for the physics engine to note the changes so an UpdateProperties event will happen. - PushKnownChanged(); - - VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", - Prim.LocalID, VehiclePosition, Prim.Force, VehicleVelocity, VehicleRotationalVelocity); - } - - // Apply the effect of the linear motor and other linear motions (like hover and float). - private void MoveLinear(float pTimestep) - { - Vector3 linearMotorContribution = m_linearMotor.Step(pTimestep); - - // The movement computed in the linear motor is relative to the vehicle - // coordinates. Rotate the movement to world coordinates. - linearMotorContribution *= VehicleOrientation; - - // ================================================================== - // Buoyancy: force to overcome gravity. - // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; - // So, if zero, don't change anything (let gravity happen). If one, negate the effect of gravity. - Vector3 buoyancyContribution = Prim.PhysicsScene.DefaultGravity * m_VehicleBuoyancy; - - Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep); - - Vector3 hoverContribution = ComputeLinearHover(pTimestep); - - ComputeLinearBlockingEndPoint(pTimestep); - - Vector3 limitMotorUpContribution = ComputeLinearMotorUp(pTimestep); - - // ================================================================== - Vector3 newVelocity = linearMotorContribution - + terrainHeightContribution - + hoverContribution - + limitMotorUpContribution; - - Vector3 newForce = buoyancyContribution; - - // If not changing some axis, reduce out velocity - if ((m_flags & (VehicleFlag.NO_X)) != 0) - newVelocity.X = 0; - if ((m_flags & (VehicleFlag.NO_Y)) != 0) - newVelocity.Y = 0; - if ((m_flags & (VehicleFlag.NO_Z)) != 0) - newVelocity.Z = 0; - - // ================================================================== - // Clamp high or low velocities - float newVelocityLengthSq = newVelocity.LengthSquared(); - if (newVelocityLengthSq > 1000f) - { - newVelocity /= newVelocity.Length(); - newVelocity *= 1000f; - } - else if (newVelocityLengthSq < 0.001f) - newVelocity = Vector3.Zero; - - // ================================================================== - // Stuff new linear velocity into the vehicle. - // Since the velocity is just being set, it is not scaled by pTimeStep. Bullet will do that for us. - VehicleVelocity = newVelocity; - - // Other linear forces are applied as forces. - Vector3 totalDownForce = newForce * m_vehicleMass; - if (!totalDownForce.ApproxEquals(Vector3.Zero, 0.01f)) - { - VehicleAddForce(totalDownForce); - } - - VDetailLog("{0}, MoveLinear,done,newVel={1},totDown={2},IsColliding={3}", - Prim.LocalID, newVelocity, totalDownForce, Prim.IsColliding); - VDetailLog("{0}, MoveLinear,done,linContrib={1},terrContrib={2},hoverContrib={3},limitContrib={4},buoyContrib={5}", - Prim.LocalID, - linearMotorContribution, terrainHeightContribution, hoverContribution, - limitMotorUpContribution, buoyancyContribution - ); - - } // end MoveLinear() - - public Vector3 ComputeLinearTerrainHeightCorrection(float pTimestep) - { - Vector3 ret = Vector3.Zero; - // If below the terrain, move us above the ground a little. - // TODO: Consider taking the rotated size of the object or possibly casting a ray. - if (VehiclePosition.Z < GetTerrainHeight(VehiclePosition)) - { - // TODO: correct position by applying force rather than forcing position. - Vector3 newPosition = VehiclePosition; - newPosition.Z = GetTerrainHeight(VehiclePosition) + 1f; - VehiclePosition = newPosition; - VDetailLog("{0}, MoveLinear,terrainHeight,terrainHeight={1},pos={2}", - Prim.LocalID, GetTerrainHeight(VehiclePosition), VehiclePosition); - } - return ret; - } - - public Vector3 ComputeLinearHover(float pTimestep) - { - Vector3 ret = Vector3.Zero; - - // m_VhoverEfficiency: 0=bouncy, 1=totally damped - // m_VhoverTimescale: time to achieve height - if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) - { - // We should hover, get the target height - if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0) - { - m_VhoverTargetHeight = GetWaterLevel(VehiclePosition) + m_VhoverHeight; - } - if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) - { - m_VhoverTargetHeight = GetTerrainHeight(VehiclePosition) + m_VhoverHeight; - } - if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) - { - m_VhoverTargetHeight = m_VhoverHeight; - } - - if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) - { - // If body is already heigher, use its height as target height - if (VehiclePosition.Z > m_VhoverTargetHeight) - m_VhoverTargetHeight = VehiclePosition.Z; - } - - if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) - { - if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f) - { - Vector3 pos = VehiclePosition; - pos.Z = m_VhoverTargetHeight; - VehiclePosition = pos; - } - } - else - { - // Error is positive if below the target and negative if above. - float verticalError = m_VhoverTargetHeight - VehiclePosition.Z; - float verticalCorrectionVelocity = verticalError / m_VhoverTimescale; - - // TODO: implement m_VhoverEfficiency correctly - if (Math.Abs(verticalError) > m_VhoverEfficiency) - { - ret = new Vector3(0f, 0f, verticalCorrectionVelocity); - } - } - - VDetailLog("{0}, MoveLinear,hover,pos={1},ret={2},hoverTS={3},height={4},target={5}", - Prim.LocalID, VehiclePosition, ret, m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight); - } - - return ret; - } - - public bool ComputeLinearBlockingEndPoint(float pTimestep) - { - bool changed = false; - - Vector3 pos = VehiclePosition; - Vector3 posChange = pos - m_lastPositionVector; - if (m_BlockingEndPoint != Vector3.Zero) - { - if (pos.X >= (m_BlockingEndPoint.X - (float)1)) - { - pos.X -= posChange.X + 1; - changed = true; - } - if (pos.Y >= (m_BlockingEndPoint.Y - (float)1)) - { - pos.Y -= posChange.Y + 1; - changed = true; - } - if (pos.Z >= (m_BlockingEndPoint.Z - (float)1)) - { - pos.Z -= posChange.Z + 1; - changed = true; - } - if (pos.X <= 0) - { - pos.X += posChange.X + 1; - changed = true; - } - if (pos.Y <= 0) - { - pos.Y += posChange.Y + 1; - changed = true; - } - if (changed) - { - VehiclePosition = pos; - VDetailLog("{0}, MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", - Prim.LocalID, m_BlockingEndPoint, posChange, pos); - } - } - return changed; - } - - // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : - // Prevent ground vehicles from motoring into the sky. This flag has a subtle effect when - // used with conjunction with banking: the strength of the banking will decay when the - // vehicle no longer experiences collisions. The decay timescale is the same as - // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering - // when they are in mid jump. - // TODO: this code is wrong. Also, what should it do for boats (height from water)? - // This is just using the ground and a general collision check. Should really be using - // a downward raycast to find what is below. - public Vector3 ComputeLinearMotorUp(float pTimestep) - { - Vector3 ret = Vector3.Zero; - float distanceAboveGround = 0f; - - if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) - { - float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition); - distanceAboveGround = VehiclePosition.Z - targetHeight; - // Not colliding if the vehicle is off the ground - if (!Prim.IsColliding) - { - // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); - ret = new Vector3(0, 0, -distanceAboveGround); - } - // TODO: this calculation is wrong. From the description at - // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce - // has a decay factor. This says this force should - // be computed with a motor. - // TODO: add interaction with banking. - } - VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}", - Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret); - return ret; - } - - // ======================================================================= - // ======================================================================= - // Apply the effect of the angular motor. - // The 'contribution' is how much angular correction velocity each function wants. - // All the contributions are added together and the resulting velocity is - // set directly on the vehicle. - private void MoveAngular(float pTimestep) - { - // The user wants this many radians per second angular change? - Vector3 angularMotorContribution = m_angularMotor.Step(pTimestep); - - // ================================================================== - // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : - // This flag prevents linear deflection parallel to world z-axis. This is useful - // for preventing ground vehicles with large linear deflection, like bumper cars, - // from climbing their linear deflection into the sky. - // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement - if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) - { - angularMotorContribution.X = 0f; - angularMotorContribution.Y = 0f; - VDetailLog("{0}, MoveAngular,noDeflectionUp,angularMotorContrib={1}", Prim.LocalID, angularMotorContribution); - } - - Vector3 verticalAttractionContribution = ComputeAngularVerticalAttraction(); - - Vector3 deflectionContribution = ComputeAngularDeflection(); - - Vector3 bankingContribution = ComputeAngularBanking(); - - // ================================================================== - m_lastVertAttractor = verticalAttractionContribution; - - m_lastAngularVelocity = angularMotorContribution - + verticalAttractionContribution - + deflectionContribution - + bankingContribution; - - // ================================================================== - // Apply the correction velocity. - // TODO: Should this be applied as an angular force (torque)? - if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) - { - VehicleRotationalVelocity = m_lastAngularVelocity; - - VDetailLog("{0}, MoveAngular,done,nonZero,angMotorContrib={1},vertAttrContrib={2},bankContrib={3},deflectContrib={4},totalContrib={5}", - Prim.LocalID, - angularMotorContribution, verticalAttractionContribution, - bankingContribution, deflectionContribution, - m_lastAngularVelocity - ); - } - else - { - // The vehicle is not adding anything angular wise. - VehicleRotationalVelocity = Vector3.Zero; - VDetailLog("{0}, MoveAngular,done,zero", Prim.LocalID); - } - - // ================================================================== - //Offset section - if (m_linearMotorOffset != Vector3.Zero) - { - //Offset of linear velocity doesn't change the linear velocity, - // but causes a torque to be applied, for example... - // - // IIIII >>> IIIII - // IIIII >>> IIIII - // IIIII >>> IIIII - // ^ - // | Applying a force at the arrow will cause the object to move forward, but also rotate - // - // - // The torque created is the linear velocity crossed with the offset - - // TODO: this computation should be in the linear section - // because that is where we know the impulse being applied. - Vector3 torqueFromOffset = Vector3.Zero; - // torqueFromOffset = Vector3.Cross(m_linearMotorOffset, appliedImpulse); - if (float.IsNaN(torqueFromOffset.X)) - torqueFromOffset.X = 0; - if (float.IsNaN(torqueFromOffset.Y)) - torqueFromOffset.Y = 0; - if (float.IsNaN(torqueFromOffset.Z)) - torqueFromOffset.Z = 0; - - VehicleAddAngularForce(torqueFromOffset * m_vehicleMass); - VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset); - } - - } - // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: - // Some vehicles, like boats, should always keep their up-side up. This can be done by - // enabling the "vertical attractor" behavior that springs the vehicle's local z-axis to - // the world z-axis (a.k.a. "up"). To take advantage of this feature you would set the - // VEHICLE_VERTICAL_ATTRACTION_TIMESCALE to control the period of the spring frequency, - // and then set the VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY to control the damping. An - // efficiency of 0.0 will cause the spring to wobble around its equilibrium, while an - // efficiency of 1.0 will cause the spring to reach its equilibrium with exponential decay. - public Vector3 ComputeAngularVerticalAttraction() - { - Vector3 ret = Vector3.Zero; - - // If vertical attaction timescale is reasonable - if (m_verticalAttractionTimescale < m_verticalAttractionCutoff) - { - // Take a vector pointing up and convert it from world to vehicle relative coords. - Vector3 verticalError = Vector3.UnitZ * VehicleOrientation; - - // If vertical attraction correction is needed, the vector that was pointing up (UnitZ) - // is now: - // leaning to one side: rotated around the X axis with the Y value going - // from zero (nearly straight up) to one (completely to the side)) or - // leaning front-to-back: rotated around the Y axis with the value of X being between - // zero and one. - // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees. - - // Y error means needed rotation around X axis and visa versa. - // Since the error goes from zero to one, the asin is the corresponding angle. - ret.X = (float)Math.Asin(verticalError.Y); - // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.) - ret.Y = -(float)Math.Asin(verticalError.X); - - // If verticalError.Z is negative, the vehicle is upside down. Add additional push. - if (verticalError.Z < 0f) - { - ret.X += PIOverFour; - ret.Y += PIOverFour; - } - - // 'ret' is now the necessary velocity to correct tilt in one second. - // Correction happens over a number of seconds. - Vector3 unscaledContrib = ret; - ret /= m_verticalAttractionTimescale; - - VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},eff={3},ts={4},vertAttr={5}", - Prim.LocalID, verticalError, unscaledContrib, m_verticalAttractionEfficiency, m_verticalAttractionTimescale, ret); - } - return ret; - } - - // Return the angular correction to correct the direction the vehicle is pointing to be - // the direction is should want to be pointing. - // The vehicle is moving in some direction and correct its orientation to it is pointing - // in that direction. - // TODO: implement reference frame. - public Vector3 ComputeAngularDeflection() - { - Vector3 ret = Vector3.Zero; - return ret; // DEBUG DEBUG DEBUG - // Disable angular deflection for the moment. - // Since angularMotorUp and angularDeflection are computed independently, they will calculate - // approximately the same X or Y correction. When added together (when contributions are combined) - // this creates an over-correction and then wabbling as the target is overshot. - // TODO: rethink how the different correction computations inter-relate. - - if (m_angularDeflectionEfficiency != 0) - { - // The direction the vehicle is moving - Vector3 movingDirection = VehicleVelocity; - movingDirection.Normalize(); - - // The direction the vehicle is pointing - Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation; - pointingDirection.Normalize(); - - // The difference between what is and what should be. - Vector3 deflectionError = movingDirection - pointingDirection; - - // Don't try to correct very large errors (not our job) - if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = 0f; - if (Math.Abs(deflectionError.Y) > PIOverFour) deflectionError.Y = 0f; - if (Math.Abs(deflectionError.Z) > PIOverFour) deflectionError.Z = 0f; - - // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError); - - // Scale the correction by recovery timescale and efficiency - ret = (-deflectionError) * m_angularDeflectionEfficiency; - ret /= m_angularDeflectionTimescale; - - VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}", - Prim.LocalID, movingDirection, pointingDirection, deflectionError, ret); - VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3}", - Prim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale); - } - return ret; - } - - // Return an angular change to rotate the vehicle around the Z axis when the vehicle - // is tipped around the X axis. - // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: - // The vertical attractor feature must be enabled in order for the banking behavior to - // function. The way banking works is this: a rotation around the vehicle's roll-axis will - // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude - // of the yaw effect will be proportional to the - // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's - // velocity along its preferred axis of motion. - // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any - // positive rotation (by the right-hand rule) about the roll-axis will effect a - // (negative) torque around the yaw-axis, making it turn to the right--that is the - // vehicle will lean into the turn, which is how real airplanes and motorcycle's work. - // Negating the banking coefficient will make it so that the vehicle leans to the - // outside of the turn (not very "physical" but might allow interesting vehicles so why not?). - // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making - // banking vehicles do what you want rather than what the laws of physics allow. - // For example, consider a real motorcycle...it must be moving forward in order for - // it to turn while banking, however video-game motorcycles are often configured - // to turn in place when at a dead stop--because they are often easier to control - // that way using the limited interface of the keyboard or game controller. The - // VEHICLE_BANKING_MIX enables combinations of both realistic and non-realistic - // banking by functioning as a slider between a banking that is correspondingly - // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the - // banking effect depends only on the vehicle's rotation about its roll-axis compared - // to "dynamic" where the banking is also proportional to its velocity along its - // roll-axis. Finding the best value of the "mixture" will probably require trial and error. - // The time it takes for the banking behavior to defeat a preexisting angular velocity about the - // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to - // bank quickly then give it a banking timescale of about a second or less, otherwise you can - // make a sluggish vehicle by giving it a timescale of several seconds. - public Vector3 ComputeAngularBanking() - { - Vector3 ret = Vector3.Zero; - - if (m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff) - { - // This works by rotating a unit vector to the orientation of the vehicle. The - // roll (tilt) will be Y component of a tilting Z vector (zero for no tilt - // up to one for full over). - Vector3 rollComponents = Vector3.UnitZ * VehicleOrientation; - - // Figure out the yaw value for this much roll. - float turnComponent = rollComponents.Y * rollComponents.Y * m_bankingEfficiency; - // Keep the sign - if (rollComponents.Y < 0f) - turnComponent = -turnComponent; - - // TODO: there must be a better computation of the banking force. - float bankingTurnForce = turnComponent; - - // actual error = static turn error + dynamic turn error - float mixedBankingError = bankingTurnForce * (1f - m_bankingMix) + bankingTurnForce * m_bankingMix * VehicleForwardSpeed; - // TODO: the banking effect should not go to infinity but what to limit it to? - mixedBankingError = ClampInRange(-20f, mixedBankingError, 20f); - - // Build the force vector to change rotation from what it is to what it should be - ret.Z = -mixedBankingError; - - // Don't do it all at once. - ret /= m_bankingTimescale; - - VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},turnComp={3},bankErr={4},mixedBankErr={5},ret={6}", - Prim.LocalID, rollComponents, VehicleForwardSpeed, turnComponent, bankingTurnForce, mixedBankingError, ret); - } - return ret; - } - - // This is from previous instantiations of XXXDynamics.cs. - // Applies roll reference frame. - // TODO: is this the right way to separate the code to do this operation? - // Should this be in MoveAngular()? - internal void LimitRotation(float timestep) - { - Quaternion rotq = VehicleOrientation; - Quaternion m_rot = rotq; - if (m_RollreferenceFrame != Quaternion.Identity) - { - if (rotq.X >= m_RollreferenceFrame.X) - { - m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2); - } - if (rotq.Y >= m_RollreferenceFrame.Y) - { - m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2); - } - if (rotq.X <= -m_RollreferenceFrame.X) - { - m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2); - } - if (rotq.Y <= -m_RollreferenceFrame.Y) - { - m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2); - } - } - if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0) - { - m_rot.X = 0; - m_rot.Y = 0; - } - if (rotq != m_rot) - { - VehicleOrientation = m_rot; - VDetailLog("{0}, LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot); - } - - } - - private float ClampInRange(float low, float val, float high) - { - return Math.Max(low, Math.Min(val, high)); - // return Utils.Clamp(val, low, high); - } - - // Invoke the detailed logger and output something if it's enabled. - private void VDetailLog(string msg, params Object[] args) - { - if (Prim.PhysicsScene.VehicleLoggingEnabled) - Prim.PhysicsScene.DetailLog(msg, args); - } - } -} diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSNPlugin/BSLinkset.cs deleted file mode 100644 index 845a113..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BSLinkset.cs +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OMV = OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSNPlugin -{ - -// A BSPrim can get individual information about its linkedness attached -// to it through an instance of a subclass of LinksetInfo. -// Each type of linkset will define the information needed for its type. -public abstract class BSLinksetInfo -{ - public virtual void Clear() { } -} - -public abstract class BSLinkset -{ - // private static string LogHeader = "[BULLETSIM LINKSET]"; - - public enum LinksetImplementation - { - Constraint = 0, // linkset tied together with constraints - Compound = 1, // linkset tied together as a compound object - Manual = 2 // linkset tied together manually (code moves all the pieces) - } - // Create the correct type of linkset for this child - public static BSLinkset Factory(BSScene physScene, BSPhysObject parent) - { - BSLinkset ret = null; - - switch ((int)BSParam.LinksetImplementation) - { - case (int)LinksetImplementation.Constraint: - ret = new BSLinksetConstraints(physScene, parent); - break; - case (int)LinksetImplementation.Compound: - ret = new BSLinksetCompound(physScene, parent); - break; - case (int)LinksetImplementation.Manual: - // ret = new BSLinksetManual(physScene, parent); - break; - default: - ret = new BSLinksetCompound(physScene, parent); - break; - } - return ret; - } - - public BSPhysObject LinksetRoot { get; protected set; } - - public BSScene PhysicsScene { get; private set; } - - static int m_nextLinksetID = 1; - public int LinksetID { get; private set; } - - // The children under the root in this linkset. - protected HashSet m_children; - - // We lock the diddling of linkset classes to prevent any badness. - // This locks the modification of the instances of this class. Changes - // to the physical representation is done via the tainting mechenism. - protected object m_linksetActivityLock = new Object(); - - // Some linksets have a preferred physical shape. - // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected. - public virtual BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) - { - return BSPhysicsShapeType.SHAPE_UNKNOWN; - } - - // We keep the prim's mass in the linkset structure since it could be dependent on other prims - public float LinksetMass { get; protected set; } - - public virtual bool LinksetIsColliding { get { return false; } } - - public OMV.Vector3 CenterOfMass - { - get { return ComputeLinksetCenterOfMass(); } - } - - public OMV.Vector3 GeometricCenter - { - get { return ComputeLinksetGeometricCenter(); } - } - - protected BSLinkset(BSScene scene, BSPhysObject parent) - { - // A simple linkset of one (no children) - LinksetID = m_nextLinksetID++; - // We create LOTS of linksets. - if (m_nextLinksetID <= 0) - m_nextLinksetID = 1; - PhysicsScene = scene; - LinksetRoot = parent; - m_children = new HashSet(); - LinksetMass = parent.RawMass; - Rebuilding = false; - } - - // Link to a linkset where the child knows the parent. - // Parent changing should not happen so do some sanity checking. - // We return the parent's linkset so the child can track its membership. - // Called at runtime. - public BSLinkset AddMeToLinkset(BSPhysObject child) - { - lock (m_linksetActivityLock) - { - // Don't add the root to its own linkset - if (!IsRoot(child)) - AddChildToLinkset(child); - LinksetMass = ComputeLinksetMass(); - } - return this; - } - - // Remove a child from a linkset. - // Returns a new linkset for the child which is a linkset of one (just the - // orphened child). - // Called at runtime. - public BSLinkset RemoveMeFromLinkset(BSPhysObject child) - { - lock (m_linksetActivityLock) - { - if (IsRoot(child)) - { - // Cannot remove the root from a linkset. - return this; - } - RemoveChildFromLinkset(child); - LinksetMass = ComputeLinksetMass(); - } - - // The child is down to a linkset of just itself - return BSLinkset.Factory(PhysicsScene, child); - } - - // Return 'true' if the passed object is the root object of this linkset - public bool IsRoot(BSPhysObject requestor) - { - return (requestor.LocalID == LinksetRoot.LocalID); - } - - public int NumberOfChildren { get { return m_children.Count; } } - - // Return 'true' if this linkset has any children (more than the root member) - public bool HasAnyChildren { get { return (m_children.Count > 0); } } - - // Return 'true' if this child is in this linkset - public bool HasChild(BSPhysObject child) - { - bool ret = false; - lock (m_linksetActivityLock) - { - ret = m_children.Contains(child); - /* Safer version but the above should work - foreach (BSPhysObject bp in m_children) - { - if (child.LocalID == bp.LocalID) - { - ret = true; - break; - } - } - */ - } - return ret; - } - - // Perform an action on each member of the linkset including root prim. - // Depends on the action on whether this should be done at taint time. - public delegate bool ForEachMemberAction(BSPhysObject obj); - public virtual bool ForEachMember(ForEachMemberAction action) - { - bool ret = false; - lock (m_linksetActivityLock) - { - action(LinksetRoot); - foreach (BSPhysObject po in m_children) - { - if (action(po)) - break; - } - } - return ret; - } - - // I am the root of a linkset and a new child is being added - // Called while LinkActivity is locked. - protected abstract void AddChildToLinkset(BSPhysObject child); - - // I am the root of a linkset and one of my children is being removed. - // Safe to call even if the child is not really in my linkset. - protected abstract void RemoveChildFromLinkset(BSPhysObject child); - - // When physical properties are changed the linkset needs to recalculate - // its internal properties. - // May be called at runtime or taint-time. - public virtual void Refresh(BSPhysObject requestor) - { - LinksetMass = ComputeLinksetMass(); - } - - // Flag denoting the linkset is in the process of being rebuilt. - // Used to know not the schedule a rebuild in the middle of a rebuild. - protected bool Rebuilding { get; set; } - - // The object is going dynamic (physical). Do any setup necessary - // for a dynamic linkset. - // Only the state of the passed object can be modified. The rest of the linkset - // has not yet been fully constructed. - // Return 'true' if any properties updated on the passed object. - // Called at taint-time! - public abstract bool MakeDynamic(BSPhysObject child); - - // The object is going static (non-physical). Do any setup necessary - // for a static linkset. - // Return 'true' if any properties updated on the passed object. - // Called at taint-time! - public abstract bool MakeStatic(BSPhysObject child); - - // Called when a parameter update comes from the physics engine for any object - // of the linkset is received. - // Passed flag is update came from physics engine (true) or the user (false). - // Called at taint-time!! - public abstract void UpdateProperties(BSPhysObject physObject, bool physicalUpdate); - - // Routine used when rebuilding the body of the root of the linkset - // Destroy all the constraints have have been made to root. - // This is called when the root body is changing. - // Returns 'true' of something was actually removed and would need restoring - // Called at taint-time!! - public abstract bool RemoveBodyDependencies(BSPrim child); - - // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', - // this routine will restore the removed constraints. - // Called at taint-time!! - public abstract void RestoreBodyDependencies(BSPrim child); - - // ================================================================ - protected virtual float ComputeLinksetMass() - { - float mass = LinksetRoot.RawMass; - if (HasAnyChildren) - { - lock (m_linksetActivityLock) - { - foreach (BSPhysObject bp in m_children) - { - mass += bp.RawMass; - } - } - } - return mass; - } - - protected virtual OMV.Vector3 ComputeLinksetCenterOfMass() - { - OMV.Vector3 com; - lock (m_linksetActivityLock) - { - com = LinksetRoot.Position * LinksetRoot.RawMass; - float totalMass = LinksetRoot.RawMass; - - foreach (BSPhysObject bp in m_children) - { - com += bp.Position * bp.RawMass; - totalMass += bp.RawMass; - } - if (totalMass != 0f) - com /= totalMass; - } - - return com; - } - - protected virtual OMV.Vector3 ComputeLinksetGeometricCenter() - { - OMV.Vector3 com; - lock (m_linksetActivityLock) - { - com = LinksetRoot.Position; - - foreach (BSPhysObject bp in m_children) - { - com += bp.Position * bp.RawMass; - } - com /= (m_children.Count + 1); - } - - return com; - } - - // Invoke the detailed logger and output something if it's enabled. - protected void DetailLog(string msg, params Object[] args) - { - if (PhysicsScene.PhysicsLogging.Enabled) - PhysicsScene.DetailLog(msg, args); - } - -} -} diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSNPlugin/BSLinksetCompound.cs deleted file mode 100644 index 9a977e6..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BSLinksetCompound.cs +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OpenSim.Framework; - -using OMV = OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSNPlugin -{ - -// When a child is linked, the relationship position of the child to the parent -// is remembered so the child's world position can be recomputed when it is -// removed from the linkset. -sealed class BSLinksetCompoundInfo : BSLinksetInfo -{ - public OMV.Vector3 OffsetPos; - public OMV.Quaternion OffsetRot; - public BSLinksetCompoundInfo(OMV.Vector3 p, OMV.Quaternion r) - { - OffsetPos = p; - OffsetRot = r; - } - public override void Clear() - { - OffsetPos = OMV.Vector3.Zero; - OffsetRot = OMV.Quaternion.Identity; - } - public override string ToString() - { - StringBuilder buff = new StringBuilder(); - buff.Append(""); - return buff.ToString(); - } -}; - -public sealed class BSLinksetCompound : BSLinkset -{ - private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]"; - - public BSLinksetCompound(BSScene scene, BSPhysObject parent) : base(scene, parent) - { - } - - // For compound implimented linksets, if there are children, use compound shape for the root. - public override BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) - { - // Returning 'unknown' means we don't have a preference. - BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN; - if (IsRoot(requestor) && HasAnyChildren) - { - ret = BSPhysicsShapeType.SHAPE_COMPOUND; - } - // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret); - return ret; - } - - // When physical properties are changed the linkset needs to recalculate - // its internal properties. - public override void Refresh(BSPhysObject requestor) - { - base.Refresh(requestor); - - // Something changed so do the rebuilding thing - // ScheduleRebuild(); - } - - // Schedule a refresh to happen after all the other taint processing. - private void ScheduleRebuild(BSPhysObject requestor) - { - DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1}", - requestor.LocalID, Rebuilding); - // When rebuilding, it is possible to set properties that would normally require a rebuild. - // If already rebuilding, don't request another rebuild. - if (!Rebuilding) - { - PhysicsScene.PostTaintObject("BSLinksetCompound.ScheduleRebuild", LinksetRoot.LocalID, delegate() - { - if (HasAnyChildren) - RecomputeLinksetCompound(); - }); - } - } - - // The object is going dynamic (physical). Do any setup necessary - // for a dynamic linkset. - // Only the state of the passed object can be modified. The rest of the linkset - // has not yet been fully constructed. - // Return 'true' if any properties updated on the passed object. - // Called at taint-time! - public override bool MakeDynamic(BSPhysObject child) - { - bool ret = false; - DetailLog("{0},BSLinksetCompound.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child)); - if (IsRoot(child)) - { - // The root is going dynamic. Make sure mass is properly set. - ScheduleRebuild(LinksetRoot); - } - else - { - // The origional prims are removed from the world as the shape of the root compound - // shape takes over. - BulletSimAPI.AddToCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); - BulletSimAPI.ForceActivationState2(child.PhysBody.ptr, ActivationState.DISABLE_SIMULATION); - // We don't want collisions from the old linkset children. - BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - - child.PhysBody.collisionType = CollisionType.LinksetChild; - - ret = true; - } - return ret; - } - - // The object is going static (non-physical). Do any setup necessary for a static linkset. - // Return 'true' if any properties updated on the passed object. - // This doesn't normally happen -- OpenSim removes the objects from the physical - // world if it is a static linkset. - // Called at taint-time! - public override bool MakeStatic(BSPhysObject child) - { - bool ret = false; - DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child)); - if (IsRoot(child)) - { - ScheduleRebuild(LinksetRoot); - } - else - { - // The non-physical children can come back to life. - BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); - - child.PhysBody.collisionType = CollisionType.LinksetChild; - - // Don't force activation so setting of DISABLE_SIMULATION can stay if used. - BulletSimAPI.Activate2(child.PhysBody.ptr, false); - ret = true; - } - return ret; - } - - public override void UpdateProperties(BSPhysObject updated, bool physicalUpdate) - { - // The user moving a child around requires the rebuilding of the linkset compound shape - // One problem is this happens when a border is crossed -- the simulator implementation - // is to store the position into the group which causes the move of the object - // but it also means all the child positions get updated. - // What would cause an unnecessary rebuild so we make sure the linkset is in a - // region before bothering to do a rebuild. - if (!IsRoot(updated) - && !physicalUpdate - && PhysicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition)) - { - updated.LinksetInfo = null; - ScheduleRebuild(updated); - } - } - - // Routine called when rebuilding the body of some member of the linkset. - // Since we don't keep in world relationships, do nothing unless it's a child changing. - // Returns 'true' of something was actually removed and would need restoring - // Called at taint-time!! - public override bool RemoveBodyDependencies(BSPrim child) - { - bool ret = false; - - DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString(), IsRoot(child)); - - if (!IsRoot(child)) - { - // Because it is a convenient time, recompute child world position and rotation based on - // its position in the linkset. - RecomputeChildWorldPosition(child, true); - } - - // Cannot schedule a refresh/rebuild here because this routine is called when - // the linkset is being rebuilt. - // InternalRefresh(LinksetRoot); - - return ret; - } - - // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', - // this routine will restore the removed constraints. - // Called at taint-time!! - public override void RestoreBodyDependencies(BSPrim child) - { - } - - // When the linkset is built, the child shape is added to the compound shape relative to the - // root shape. The linkset then moves around but this does not move the actual child - // prim. The child prim's location must be recomputed based on the location of the root shape. - private void RecomputeChildWorldPosition(BSPhysObject child, bool inTaintTime) - { - BSLinksetCompoundInfo lci = child.LinksetInfo as BSLinksetCompoundInfo; - if (lci != null) - { - if (inTaintTime) - { - OMV.Vector3 oldPos = child.RawPosition; - child.ForcePosition = LinksetRoot.RawPosition + lci.OffsetPos; - child.ForceOrientation = LinksetRoot.RawOrientation * lci.OffsetRot; - DetailLog("{0},BSLinksetCompound.RecomputeChildWorldPosition,oldPos={1},lci={2},newPos={3}", - child.LocalID, oldPos, lci, child.RawPosition); - } - else - { - // TaintedObject is not used here so the raw position is set now and not at taint-time. - child.Position = LinksetRoot.RawPosition + lci.OffsetPos; - child.Orientation = LinksetRoot.RawOrientation * lci.OffsetRot; - } - } - else - { - // This happens when children have been added to the linkset but the linkset - // has not been constructed yet. So like, at taint time, adding children to a linkset - // and then changing properties of the children (makePhysical, for instance) - // but the post-print action of actually rebuilding the linkset has not yet happened. - // PhysicsScene.Logger.WarnFormat("{0} Restoring linkset child position failed because of no relative position computed. ID={1}", - // LogHeader, child.LocalID); - DetailLog("{0},BSLinksetCompound.recomputeChildWorldPosition,noRelativePositonInfo", child.LocalID); - } - } - - // ================================================================ - - // Add a new child to the linkset. - // Called while LinkActivity is locked. - protected override void AddChildToLinkset(BSPhysObject child) - { - if (!HasChild(child)) - { - m_children.Add(child); - - DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); - - // Rebuild the compound shape with the new child shape included - ScheduleRebuild(child); - } - return; - } - - // Remove the specified child from the linkset. - // Safe to call even if the child is not really in the linkset. - protected override void RemoveChildFromLinkset(BSPhysObject child) - { - if (m_children.Remove(child)) - { - DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", - child.LocalID, - LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString(), - child.LocalID, child.PhysBody.ptr.ToString()); - - // Cause the child's body to be rebuilt and thus restored to normal operation - RecomputeChildWorldPosition(child, false); - child.ForceBodyShapeRebuild(false); - - if (!HasAnyChildren) - { - // The linkset is now empty. The root needs rebuilding. - LinksetRoot.ForceBodyShapeRebuild(false); - } - else - { - // Rebuild the compound shape with the child removed - ScheduleRebuild(child); - } - } - return; - } - - // Called before the simulation step to make sure the compound based linkset - // is all initialized. - // Constraint linksets are rebuilt every time. - // Note that this works for rebuilding just the root after a linkset is taken apart. - // Called at taint time!! - private void RecomputeLinksetCompound() - { - try - { - // Suppress rebuilding while rebuilding - Rebuilding = true; - - // Cause the root shape to be rebuilt as a compound object with just the root in it - LinksetRoot.ForceBodyShapeRebuild(true); - - DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", - LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); - - // Add a shape for each of the other children in the linkset - ForEachMember(delegate(BSPhysObject cPrim) - { - if (!IsRoot(cPrim)) - { - // Compute the displacement of the child from the root of the linkset. - // This info is saved in the child prim so the relationship does not - // change over time and the new child position can be computed - // when the linkset is being disassembled (the linkset may have moved). - BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo; - if (lci == null) - { - // Each child position and rotation is given relative to the root. - OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); - OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation; - OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; - - // Save relative position for recomputing child's world position after moving linkset. - lci = new BSLinksetCompoundInfo(displacementPos, displacementRot); - cPrim.LinksetInfo = lci; - DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci); - } - - DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", - LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot); - - if (cPrim.PhysShape.isNativeShape) - { - // A native shape is turning into a hull collision shape because native - // shapes are not shared so we have to hullify it so it will be tracked - // and freed at the correct time. This also solves the scaling problem - // (native shapes scaled but hull/meshes are assumed to not be). - // TODO: decide of the native shape can just be used in the compound shape. - // Use call to CreateGeomNonSpecial(). - BulletShape saveShape = cPrim.PhysShape; - cPrim.PhysShape.Clear(); // Don't let the create free the child's shape - // PhysicsScene.Shapes.CreateGeomNonSpecial(true, cPrim, null); - PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); - BulletShape newShape = cPrim.PhysShape; - cPrim.PhysShape = saveShape; - BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, lci.OffsetPos, lci.OffsetRot); - } - else - { - // For the shared shapes (meshes and hulls), just use the shape in the child. - // The reference count added here will be decremented when the compound shape - // is destroyed in BSShapeCollection (the child shapes are looped over and dereferenced). - if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape)) - { - PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", - LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); - } - BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, lci.OffsetPos, lci.OffsetRot); - } - } - return false; // 'false' says to move onto the next child in the list - }); - - // With all of the linkset packed into the root prim, it has the mass of everyone. - LinksetMass = LinksetMass; - LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true); - } - finally - { - Rebuilding = false; - } - - BulletSimAPI.RecalculateCompoundShapeLocalAabb2(LinksetRoot.PhysShape.ptr); - - // DEBUG: see of inter-linkset collisions are causing problems for constraint linksets. - // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, - // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - - } -} -} \ No newline at end of file diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSNPlugin/BSLinksetConstraints.cs deleted file mode 100644 index 46ff99f..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BSLinksetConstraints.cs +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OMV = OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSNPlugin -{ -public sealed class BSLinksetConstraints : BSLinkset -{ - // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; - - public BSLinksetConstraints(BSScene scene, BSPhysObject parent) : base(scene, parent) - { - } - - // When physical properties are changed the linkset needs to recalculate - // its internal properties. - // This is queued in the 'post taint' queue so the - // refresh will happen once after all the other taints are applied. - public override void Refresh(BSPhysObject requestor) - { - base.Refresh(requestor); - - // Queue to happen after all the other taint processing - PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() - { - if (HasAnyChildren && IsRoot(requestor)) - RecomputeLinksetConstraints(); - }); - } - - // The object is going dynamic (physical). Do any setup necessary - // for a dynamic linkset. - // Only the state of the passed object can be modified. The rest of the linkset - // has not yet been fully constructed. - // Return 'true' if any properties updated on the passed object. - // Called at taint-time! - public override bool MakeDynamic(BSPhysObject child) - { - // What is done for each object in BSPrim is what we want. - return false; - } - - // The object is going static (non-physical). Do any setup necessary for a static linkset. - // Return 'true' if any properties updated on the passed object. - // This doesn't normally happen -- OpenSim removes the objects from the physical - // world if it is a static linkset. - // Called at taint-time! - public override bool MakeStatic(BSPhysObject child) - { - // What is done for each object in BSPrim is what we want. - return false; - } - - // Called at taint-time!! - public override void UpdateProperties(BSPhysObject updated, bool inTaintTime) - { - // Nothing to do for constraints on property updates - } - - // Routine called when rebuilding the body of some member of the linkset. - // Destroy all the constraints have have been made to root and set - // up to rebuild the constraints before the next simulation step. - // Returns 'true' of something was actually removed and would need restoring - // Called at taint-time!! - public override bool RemoveBodyDependencies(BSPrim child) - { - bool ret = false; - - DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString()); - - lock (m_linksetActivityLock) - { - // Just undo all the constraints for this linkset. Rebuild at the end of the step. - ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); - // Cause the constraints, et al to be rebuilt before the next simulation step. - Refresh(LinksetRoot); - } - return ret; - } - - // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', - // this routine will restore the removed constraints. - // Called at taint-time!! - public override void RestoreBodyDependencies(BSPrim child) - { - // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints. - } - - // ================================================================ - - // Add a new child to the linkset. - // Called while LinkActivity is locked. - protected override void AddChildToLinkset(BSPhysObject child) - { - if (!HasChild(child)) - { - m_children.Add(child); - - DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); - - // Cause constraints and assorted properties to be recomputed before the next simulation step. - Refresh(LinksetRoot); - } - return; - } - - // Remove the specified child from the linkset. - // Safe to call even if the child is not really in my linkset. - protected override void RemoveChildFromLinkset(BSPhysObject child) - { - if (m_children.Remove(child)) - { - BSPhysObject rootx = LinksetRoot; // capture the root and body as of now - BSPhysObject childx = child; - - DetailLog("{0},BSLinksetConstraints.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", - childx.LocalID, - rootx.LocalID, rootx.PhysBody.ptr.ToString(), - childx.LocalID, childx.PhysBody.ptr.ToString()); - - PhysicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate() - { - PhysicallyUnlinkAChildFromRoot(rootx, childx); - }); - // See that the linkset parameters are recomputed at the end of the taint time. - Refresh(LinksetRoot); - } - else - { - // Non-fatal occurance. - // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); - } - return; - } - - // Create a constraint between me (root of linkset) and the passed prim (the child). - // Called at taint time! - private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim) - { - // Don't build the constraint when asked. Put it off until just before the simulation step. - Refresh(rootPrim); - } - - private BSConstraint BuildConstraint(BSPhysObject rootPrim, BSPhysObject childPrim) - { - // Zero motion for children so they don't interpolate - childPrim.ZeroMotion(true); - - // Relative position normalized to the root prim - // Essentually a vector pointing from center of rootPrim to center of childPrim - OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position; - - // real world coordinate of midpoint between the two objects - OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); - - DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", - rootPrim.LocalID, - rootPrim.LocalID, rootPrim.PhysBody.ptr.ToString(), - childPrim.LocalID, childPrim.PhysBody.ptr.ToString(), - rootPrim.Position, childPrim.Position, midPoint); - - // create a constraint that allows no freedom of movement between the two objects - // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - - BSConstraint6Dof constrain = new BSConstraint6Dof( - PhysicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true ); - // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true ); - - /* NOTE: below is an attempt to build constraint with full frame computation, etc. - * Using the midpoint is easier since it lets the Bullet code manipulate the transforms - * of the objects. - * Code left for future programmers. - // ================================================================================== - // relative position normalized to the root prim - OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); - OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation; - - // relative rotation of the child to the parent - OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; - OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation); - - DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); - BS6DofConstraint constrain = new BS6DofConstraint( - PhysicsScene.World, rootPrim.Body, childPrim.Body, - OMV.Vector3.Zero, - OMV.Quaternion.Inverse(rootPrim.Orientation), - OMV.Vector3.Zero, - OMV.Quaternion.Inverse(childPrim.Orientation), - true, - true - ); - // ================================================================================== - */ - - PhysicsScene.Constraints.AddConstraint(constrain); - - // zero linear and angular limits makes the objects unable to move in relation to each other - constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); - constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); - - // tweek the constraint to increase stability - constrain.UseFrameOffset(BSParam.BoolNumeric(BSParam.LinkConstraintUseFrameOffset)); - constrain.TranslationalLimitMotor(BSParam.BoolNumeric(BSParam.LinkConstraintEnableTransMotor), - BSParam.LinkConstraintTransMotorMaxVel, - BSParam.LinkConstraintTransMotorMaxForce); - constrain.SetCFMAndERP(BSParam.LinkConstraintCFM, BSParam.LinkConstraintERP); - if (BSParam.LinkConstraintSolverIterations != 0f) - { - constrain.SetSolverIterations(BSParam.LinkConstraintSolverIterations); - } - return constrain; - } - - // Remove linkage between the linkset root and a particular child - // The root and child bodies are passed in because we need to remove the constraint between - // the bodies that were present at unlink time. - // Called at taint time! - private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim) - { - bool ret = false; - DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", - rootPrim.LocalID, - rootPrim.LocalID, rootPrim.PhysBody.ptr.ToString(), - childPrim.LocalID, childPrim.PhysBody.ptr.ToString()); - - // Find the constraint for this link and get rid of it from the overall collection and from my list - if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody)) - { - // Make the child refresh its location - BulletSimAPI.PushUpdate2(childPrim.PhysBody.ptr); - ret = true; - } - - return ret; - } - - // Remove linkage between myself and any possible children I might have. - // Returns 'true' of any constraints were destroyed. - // Called at taint time! - private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) - { - DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); - - return PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody); - } - - // Call each of the constraints that make up this linkset and recompute the - // various transforms and variables. Create constraints of not created yet. - // Called before the simulation step to make sure the constraint based linkset - // is all initialized. - // Called at taint time!! - private void RecomputeLinksetConstraints() - { - float linksetMass = LinksetMass; - LinksetRoot.UpdatePhysicalMassProperties(linksetMass, true); - - // DEBUG: see of inter-linkset collisions are causing problems - // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, - // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}", - LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString(), linksetMass); - - foreach (BSPhysObject child in m_children) - { - // A child in the linkset physically shows the mass of the whole linkset. - // This allows Bullet to apply enough force on the child to move the whole linkset. - // (Also do the mass stuff before recomputing the constraint so mass is not zero.) - child.UpdatePhysicalMassProperties(linksetMass, true); - - BSConstraint constrain; - if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain)) - { - // If constraint doesn't exist yet, create it. - constrain = BuildConstraint(LinksetRoot, child); - } - constrain.RecomputeConstraintVariables(linksetMass); - - // DEBUG: see of inter-linkset collisions are causing problems - // BulletSimAPI.SetCollisionFilterMask2(child.BSBody.ptr, - // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - - // BulletSimAPI.DumpConstraint2(PhysicsScene.World.ptr, constrain.Constraint.ptr); // DEBUG DEBUG - } - - } -} -} diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSMaterials.cs b/OpenSim/Region/Physics/BulletSNPlugin/BSMaterials.cs deleted file mode 100644 index d7941b6..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BSMaterials.cs +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using System.Reflection; -using Nini.Config; - -namespace OpenSim.Region.Physics.BulletSNPlugin -{ - -public struct MaterialAttributes -{ - // Material type values that correspond with definitions for LSL - public enum Material : int - { - Stone = 0, - Metal, - Glass, - Wood, - Flesh, - Plastic, - Rubber, - Light, - // Hereafter are BulletSim additions - Avatar, - NumberOfTypes // the count of types in the enum. - } - - // Names must be in the order of the above enum. - // These names must coorespond to the lower case field names in the MaterialAttributes - // structure as reflection is used to select the field to put the value in. - public static readonly string[] MaterialAttribs = { "Density", "Friction", "Restitution"}; - - public MaterialAttributes(string t, float d, float f, float r) - { - type = t; - density = d; - friction = f; - restitution = r; - } - public string type; - public float density; - public float friction; - public float restitution; -} - -public static class BSMaterials -{ - // Attributes for each material type - private static readonly MaterialAttributes[] Attributes; - - // Map of material name to material type code - public static readonly Dictionary MaterialMap; - - static BSMaterials() - { - // Attribute sets for both the non-physical and physical instances of materials. - Attributes = new MaterialAttributes[(int)MaterialAttributes.Material.NumberOfTypes * 2]; - - // Map of name to type code. - MaterialMap = new Dictionary(); - MaterialMap.Add("Stone", MaterialAttributes.Material.Stone); - MaterialMap.Add("Metal", MaterialAttributes.Material.Metal); - MaterialMap.Add("Glass", MaterialAttributes.Material.Glass); - MaterialMap.Add("Wood", MaterialAttributes.Material.Wood); - MaterialMap.Add("Flesh", MaterialAttributes.Material.Flesh); - MaterialMap.Add("Plastic", MaterialAttributes.Material.Plastic); - MaterialMap.Add("Rubber", MaterialAttributes.Material.Rubber); - MaterialMap.Add("Light", MaterialAttributes.Material.Light); - MaterialMap.Add("Avatar", MaterialAttributes.Material.Avatar); - } - - // This is where all the default material attributes are defined. - public static void InitializeFromDefaults(ConfigurationParameters parms) - { - // Values from http://wiki.secondlife.com/wiki/PRIM_MATERIAL - float dDensity = parms.defaultDensity; - float dFriction = parms.defaultFriction; - float dRestitution = parms.defaultRestitution; - Attributes[(int)MaterialAttributes.Material.Stone] = - new MaterialAttributes("stone",dDensity, 0.8f, 0.4f); - Attributes[(int)MaterialAttributes.Material.Metal] = - new MaterialAttributes("metal",dDensity, 0.3f, 0.4f); - Attributes[(int)MaterialAttributes.Material.Glass] = - new MaterialAttributes("glass",dDensity, 0.2f, 0.7f); - Attributes[(int)MaterialAttributes.Material.Wood] = - new MaterialAttributes("wood",dDensity, 0.6f, 0.5f); - Attributes[(int)MaterialAttributes.Material.Flesh] = - new MaterialAttributes("flesh",dDensity, 0.9f, 0.3f); - Attributes[(int)MaterialAttributes.Material.Plastic] = - new MaterialAttributes("plastic",dDensity, 0.4f, 0.7f); - Attributes[(int)MaterialAttributes.Material.Rubber] = - new MaterialAttributes("rubber",dDensity, 0.9f, 0.9f); - Attributes[(int)MaterialAttributes.Material.Light] = - new MaterialAttributes("light",dDensity, dFriction, dRestitution); - Attributes[(int)MaterialAttributes.Material.Avatar] = - new MaterialAttributes("avatar",3.5f, 0.2f, 0f); - - Attributes[(int)MaterialAttributes.Material.Stone + (int)MaterialAttributes.Material.NumberOfTypes] = - new MaterialAttributes("stonePhysical",dDensity, 0.8f, 0.4f); - Attributes[(int)MaterialAttributes.Material.Metal + (int)MaterialAttributes.Material.NumberOfTypes] = - new MaterialAttributes("metalPhysical",dDensity, 0.3f, 0.4f); - Attributes[(int)MaterialAttributes.Material.Glass + (int)MaterialAttributes.Material.NumberOfTypes] = - new MaterialAttributes("glassPhysical",dDensity, 0.2f, 0.7f); - Attributes[(int)MaterialAttributes.Material.Wood + (int)MaterialAttributes.Material.NumberOfTypes] = - new MaterialAttributes("woodPhysical",dDensity, 0.6f, 0.5f); - Attributes[(int)MaterialAttributes.Material.Flesh + (int)MaterialAttributes.Material.NumberOfTypes] = - new MaterialAttributes("fleshPhysical",dDensity, 0.9f, 0.3f); - Attributes[(int)MaterialAttributes.Material.Plastic + (int)MaterialAttributes.Material.NumberOfTypes] = - new MaterialAttributes("plasticPhysical",dDensity, 0.4f, 0.7f); - Attributes[(int)MaterialAttributes.Material.Rubber + (int)MaterialAttributes.Material.NumberOfTypes] = - new MaterialAttributes("rubberPhysical",dDensity, 0.9f, 0.9f); - Attributes[(int)MaterialAttributes.Material.Light + (int)MaterialAttributes.Material.NumberOfTypes] = - new MaterialAttributes("lightPhysical",dDensity, dFriction, dRestitution); - Attributes[(int)MaterialAttributes.Material.Avatar + (int)MaterialAttributes.Material.NumberOfTypes] = - new MaterialAttributes("avatarPhysical",3.5f, 0.2f, 0f); - } - - // Under the [BulletSim] section, one can change the individual material - // attribute values. The format of the configuration parameter is: - // ["Physical"] = floatValue - // For instance: - // [BulletSim] - // StoneFriction = 0.2 - // FleshRestitutionPhysical = 0.8 - // Materials can have different parameters for their static and - // physical instantiations. When setting the non-physical value, - // both values are changed. Setting the physical value only changes - // the physical value. - public static void InitializefromParameters(IConfig pConfig) - { - foreach (KeyValuePair kvp in MaterialMap) - { - string matName = kvp.Key; - foreach (string attribName in MaterialAttributes.MaterialAttribs) - { - string paramName = matName + attribName; - if (pConfig.Contains(paramName)) - { - float paramValue = pConfig.GetFloat(paramName); - SetAttributeValue((int)kvp.Value, attribName, paramValue); - // set the physical value also - SetAttributeValue((int)kvp.Value + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue); - } - paramName += "Physical"; - if (pConfig.Contains(paramName)) - { - float paramValue = pConfig.GetFloat(paramName); - SetAttributeValue((int)kvp.Value + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue); - } - } - } - } - - // Use reflection to set the value in the attribute structure. - private static void SetAttributeValue(int matType, string attribName, float val) - { - MaterialAttributes thisAttrib = Attributes[matType]; - FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName.ToLower()); - if (fieldInfo != null) - { - fieldInfo.SetValue(thisAttrib, val); - Attributes[matType] = thisAttrib; - } - } - - // Given a material type, return a structure of attributes. - public static MaterialAttributes GetAttributes(MaterialAttributes.Material type, bool isPhysical) - { - int ind = (int)type; - if (isPhysical) ind += (int)MaterialAttributes.Material.NumberOfTypes; - return Attributes[ind]; - } -} -} diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSMotors.cs b/OpenSim/Region/Physics/BulletSNPlugin/BSMotors.cs deleted file mode 100644 index 7abc9b2..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BSMotors.cs +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -using System; -using System.Collections.Generic; -using System.Text; -using OpenMetaverse; -using OpenSim.Framework; - -namespace OpenSim.Region.Physics.BulletSNPlugin -{ -public abstract class BSMotor -{ - // Timescales and other things can be turned off by setting them to 'infinite'. - public const float Infinite = 12345.6f; - public readonly static Vector3 InfiniteVector = new Vector3(BSMotor.Infinite, BSMotor.Infinite, BSMotor.Infinite); - - public BSMotor(string useName) - { - UseName = useName; - PhysicsScene = null; - Enabled = true; - } - public virtual bool Enabled { get; set; } - public virtual void Reset() { } - public virtual void Zero() { } - public virtual void GenerateTestOutput(float timeStep) { } - - // A name passed at motor creation for easily identifyable debugging messages. - public string UseName { get; private set; } - - // Used only for outputting debug information. Might not be set so check for null. - public BSScene PhysicsScene { get; set; } - protected void MDetailLog(string msg, params Object[] parms) - { - if (PhysicsScene != null) - { - if (PhysicsScene.VehicleLoggingEnabled) - { - PhysicsScene.DetailLog(msg, parms); - } - } - } -} - -// Motor which moves CurrentValue to TargetValue over TimeScale seconds. -// The TargetValue decays in TargetValueDecayTimeScale and -// the CurrentValue will be held back by FrictionTimeScale. -// This motor will "zero itself" over time in that the targetValue will -// decay to zero and the currentValue will follow it to that zero. -// The overall effect is for the returned correction value to go from large -// values (the total difference between current and target minus friction) -// to small and eventually zero values. -// TimeScale and TargetDelayTimeScale may be 'infinite' which means no decay. - -// For instance, if something is moving at speed X and the desired speed is Y, -// CurrentValue is X and TargetValue is Y. As the motor is stepped, new -// values of CurrentValue are returned that approach the TargetValue. -// The feature of decaying TargetValue is so vehicles will eventually -// come to a stop rather than run forever. This can be disabled by -// setting TargetValueDecayTimescale to 'infinite'. -// The change from CurrentValue to TargetValue is linear over TimeScale seconds. -public class BSVMotor : BSMotor -{ - // public Vector3 FrameOfReference { get; set; } - // public Vector3 Offset { get; set; } - - public virtual float TimeScale { get; set; } - public virtual float TargetValueDecayTimeScale { get; set; } - public virtual Vector3 FrictionTimescale { get; set; } - public virtual float Efficiency { get; set; } - - public virtual float ErrorZeroThreshold { get; set; } - - public virtual Vector3 TargetValue { get; protected set; } - public virtual Vector3 CurrentValue { get; protected set; } - public virtual Vector3 LastError { get; protected set; } - - public virtual bool ErrorIsZero - { get { - return (LastError == Vector3.Zero || LastError.LengthSquared() <= ErrorZeroThreshold); - } - } - - public BSVMotor(string useName) - : base(useName) - { - TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite; - Efficiency = 1f; - FrictionTimescale = BSMotor.InfiniteVector; - CurrentValue = TargetValue = Vector3.Zero; - ErrorZeroThreshold = 0.001f; - } - public BSVMotor(string useName, float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency) - : this(useName) - { - TimeScale = timeScale; - TargetValueDecayTimeScale = decayTimeScale; - FrictionTimescale = frictionTimeScale; - Efficiency = efficiency; - CurrentValue = TargetValue = Vector3.Zero; - } - public void SetCurrent(Vector3 current) - { - CurrentValue = current; - } - public void SetTarget(Vector3 target) - { - TargetValue = target; - } - public override void Zero() - { - base.Zero(); - CurrentValue = TargetValue = Vector3.Zero; - } - - // Compute the next step and return the new current value - public virtual Vector3 Step(float timeStep) - { - if (!Enabled) return TargetValue; - - Vector3 origTarget = TargetValue; // DEBUG - Vector3 origCurrVal = CurrentValue; // DEBUG - - Vector3 correction = Vector3.Zero; - Vector3 error = TargetValue - CurrentValue; - if (!error.ApproxEquals(Vector3.Zero, ErrorZeroThreshold)) - { - correction = Step(timeStep, error); - - CurrentValue += correction; - - // The desired value reduces to zero which also reduces the difference with current. - // If the decay time is infinite, don't decay at all. - float decayFactor = 0f; - if (TargetValueDecayTimeScale != BSMotor.Infinite) - { - decayFactor = (1.0f / TargetValueDecayTimeScale) * timeStep; - TargetValue *= (1f - decayFactor); - } - - // The amount we can correct the error is reduced by the friction - Vector3 frictionFactor = Vector3.Zero; - if (FrictionTimescale != BSMotor.InfiniteVector) - { - // frictionFactor = (Vector3.One / FrictionTimescale) * timeStep; - // Individual friction components can be 'infinite' so compute each separately. - frictionFactor.X = (FrictionTimescale.X == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.X); - frictionFactor.Y = (FrictionTimescale.Y == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.Y); - frictionFactor.Z = (FrictionTimescale.Z == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.Z); - frictionFactor *= timeStep; - CurrentValue *= (Vector3.One - frictionFactor); - } - - MDetailLog("{0}, BSVMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},err={5},corr={6}", - BSScene.DetailLogZero, UseName, origCurrVal, origTarget, - timeStep, error, correction); - MDetailLog("{0}, BSVMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},frictTS={4},frictFact={5},tgt={6},curr={7}", - BSScene.DetailLogZero, UseName, - TargetValueDecayTimeScale, decayFactor, FrictionTimescale, frictionFactor, - TargetValue, CurrentValue); - } - else - { - // Difference between what we have and target is small. Motor is done. - CurrentValue = TargetValue; - MDetailLog("{0}, BSVMotor.Step,zero,{1},origTgt={2},origCurr={3},ret={4}", - BSScene.DetailLogZero, UseName, origCurrVal, origTarget, CurrentValue); - } - - return CurrentValue; - } - public virtual Vector3 Step(float timeStep, Vector3 error) - { - if (!Enabled) return Vector3.Zero; - - LastError = error; - Vector3 returnCorrection = Vector3.Zero; - if (!error.ApproxEquals(Vector3.Zero, ErrorZeroThreshold)) - { - // correction = error / secondsItShouldTakeToCorrect - Vector3 correctionAmount; - if (TimeScale == 0f || TimeScale == BSMotor.Infinite) - correctionAmount = error * timeStep; - else - correctionAmount = error / TimeScale * timeStep; - - returnCorrection = correctionAmount; - MDetailLog("{0}, BSVMotor.Step,nonZero,{1},timeStep={2},timeScale={3},err={4},corr={5}", - BSScene.DetailLogZero, UseName, timeStep, TimeScale, error, correctionAmount); - } - return returnCorrection; - } - - // The user sets all the parameters and calls this which outputs values until error is zero. - public override void GenerateTestOutput(float timeStep) - { - // maximum number of outputs to generate. - int maxOutput = 50; - MDetailLog("{0},BSVMotor.Test,{1},===================================== BEGIN Test Output", BSScene.DetailLogZero, UseName); - MDetailLog("{0},BSVMotor.Test,{1},timeScale={2},targDlyTS={3},frictTS={4},eff={5},curr={6},tgt={7}", - BSScene.DetailLogZero, UseName, - TimeScale, TargetValueDecayTimeScale, FrictionTimescale, Efficiency, - CurrentValue, TargetValue); - - LastError = BSMotor.InfiniteVector; - while (maxOutput-- > 0 && !LastError.ApproxEquals(Vector3.Zero, ErrorZeroThreshold)) - { - Vector3 lastStep = Step(timeStep); - MDetailLog("{0},BSVMotor.Test,{1},cur={2},tgt={3},lastError={4},lastStep={5}", - BSScene.DetailLogZero, UseName, CurrentValue, TargetValue, LastError, lastStep); - } - MDetailLog("{0},BSVMotor.Test,{1},===================================== END Test Output", BSScene.DetailLogZero, UseName); - - - } - - public override string ToString() - { - return String.Format("<{0},curr={1},targ={2},decayTS={3},frictTS={4}>", - UseName, CurrentValue, TargetValue, TargetValueDecayTimeScale, FrictionTimescale); - } -} - -public class BSFMotor : BSMotor -{ - public float TimeScale { get; set; } - public float DecayTimeScale { get; set; } - public float Friction { get; set; } - public float Efficiency { get; set; } - - public float Target { get; private set; } - public float CurrentValue { get; private set; } - - public BSFMotor(string useName, float timeScale, float decayTimescale, float friction, float efficiency) - : base(useName) - { - } - public void SetCurrent(float target) - { - } - public void SetTarget(float target) - { - } - public virtual float Step(float timeStep) - { - return 0f; - } -} - -// Proportional, Integral, Derivitive Motor -// Good description at http://www.answers.com/topic/pid-controller . Includes processes for choosing p, i and d factors. -public class BSPIDVMotor : BSVMotor -{ - // Larger makes more overshoot, smaller means converge quicker. Range of 0.1 to 10. - public Vector3 proportionFactor { get; set; } - public Vector3 integralFactor { get; set; } - public Vector3 derivFactor { get; set; } - - // Arbritrary factor range. - // EfficiencyHigh means move quickly to the correct number. EfficiencyLow means might over correct. - public float EfficiencyHigh = 0.4f; - public float EfficiencyLow = 4.0f; - - // Running integration of the error - Vector3 RunningIntegration { get; set; } - - public BSPIDVMotor(string useName) - : base(useName) - { - proportionFactor = new Vector3(1.00f, 1.00f, 1.00f); - integralFactor = new Vector3(1.00f, 1.00f, 1.00f); - derivFactor = new Vector3(1.00f, 1.00f, 1.00f); - RunningIntegration = Vector3.Zero; - LastError = Vector3.Zero; - } - - public override void Zero() - { - base.Zero(); - } - - public override float Efficiency - { - get { return base.Efficiency; } - set - { - base.Efficiency = Util.Clamp(value, 0f, 1f); - // Compute factors based on efficiency. - // If efficiency is high (1f), use a factor value that moves the error value to zero with little overshoot. - // If efficiency is low (0f), use a factor value that overcorrects. - // TODO: might want to vary contribution of different factor depending on efficiency. - float factor = ((1f - this.Efficiency) * EfficiencyHigh + EfficiencyLow) / 3f; - // float factor = (1f - this.Efficiency) * EfficiencyHigh + EfficiencyLow; - proportionFactor = new Vector3(factor, factor, factor); - integralFactor = new Vector3(factor, factor, factor); - derivFactor = new Vector3(factor, factor, factor); - } - } - - // Ignore Current and Target Values and just advance the PID computation on this error. - public override Vector3 Step(float timeStep, Vector3 error) - { - if (!Enabled) return Vector3.Zero; - - // Add up the error so we can integrate over the accumulated errors - RunningIntegration += error * timeStep; - - // A simple derivitive is the rate of change from the last error. - Vector3 derivFactor = (error - LastError) * timeStep; - LastError = error; - - // Correction = -(proportionOfPresentError + accumulationOfPastError + rateOfChangeOfError) - Vector3 ret = -( - error * proportionFactor - + RunningIntegration * integralFactor - + derivFactor * derivFactor - ); - - return ret; - } -} -} diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSNPlugin/BSParam.cs deleted file mode 100644 index 5e93a03..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BSParam.cs +++ /dev/null @@ -1,559 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OpenSim.Region.Physics.Manager; - -using OpenMetaverse; -using Nini.Config; - -namespace OpenSim.Region.Physics.BulletSNPlugin -{ -public static class BSParam -{ - // Level of Detail values kept as float because that's what the Meshmerizer wants - public static float MeshLOD { get; private set; } - public static float MeshMegaPrimLOD { get; private set; } - public static float MeshMegaPrimThreshold { get; private set; } - public static float SculptLOD { get; private set; } - - public static float MinimumObjectMass { get; private set; } - public static float MaximumObjectMass { get; private set; } - - public static float LinearDamping { get; private set; } - public static float AngularDamping { get; private set; } - public static float DeactivationTime { get; private set; } - public static float LinearSleepingThreshold { get; private set; } - public static float AngularSleepingThreshold { get; private set; } - public static float CcdMotionThreshold { get; private set; } - public static float CcdSweptSphereRadius { get; private set; } - public static float ContactProcessingThreshold { get; private set; } - - public static bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed - public static bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes - public static bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects - - public static float TerrainImplementation { get; private set; } - public static float TerrainFriction { get; private set; } - public static float TerrainHitFraction { get; private set; } - public static float TerrainRestitution { get; private set; } - public static float TerrainCollisionMargin { get; private set; } - - // Avatar parameters - public static float AvatarFriction { get; private set; } - public static float AvatarStandingFriction { get; private set; } - public static float AvatarDensity { get; private set; } - public static float AvatarRestitution { get; private set; } - public static float AvatarCapsuleWidth { get; private set; } - public static float AvatarCapsuleDepth { get; private set; } - public static float AvatarCapsuleHeight { get; private set; } - public static float AvatarContactProcessingThreshold { get; private set; } - - public static float VehicleAngularDamping { get; private set; } - - public static float LinksetImplementation { get; private set; } - public static float LinkConstraintUseFrameOffset { get; private set; } - public static float LinkConstraintEnableTransMotor { get; private set; } - public static float LinkConstraintTransMotorMaxVel { get; private set; } - public static float LinkConstraintTransMotorMaxForce { get; private set; } - public static float LinkConstraintERP { get; private set; } - public static float LinkConstraintCFM { get; private set; } - public static float LinkConstraintSolverIterations { get; private set; } - - public static float PID_D { get; private set; } // derivative - public static float PID_P { get; private set; } // proportional - - public delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); - public delegate float ParamGet(BSScene scene); - public delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); - public delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val); - - public struct ParameterDefn - { - public string name; // string name of the parameter - public string desc; // a short description of what the parameter means - public float defaultValue; // default value if not specified anywhere else - public ParamUser userParam; // get the value from the configuration file - public ParamGet getter; // return the current value stored for this parameter - public ParamSet setter; // set the current value for this parameter - public SetOnObject onObject; // set the value on an object in the physical domain - public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) - { - name = n; - desc = d; - defaultValue = v; - userParam = u; - getter = g; - setter = s; - onObject = null; - } - public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o) - { - name = n; - desc = d; - defaultValue = v; - userParam = u; - getter = g; - setter = s; - onObject = o; - } - } - - // List of all of the externally visible parameters. - // For each parameter, this table maps a text name to getter and setters. - // To add a new externally referencable/settable parameter, add the paramter storage - // location somewhere in the program and make an entry in this table with the - // getters and setters. - // It is easiest to find an existing definition and copy it. - // Parameter values are floats. Booleans are converted to a floating value. - // - // A ParameterDefn() takes the following parameters: - // -- the text name of the parameter. This is used for console input and ini file. - // -- a short text description of the parameter. This shows up in the console listing. - // -- a default value (float) - // -- a delegate for fetching the parameter from the ini file. - // Should handle fetching the right type from the ini file and converting it. - // -- a delegate for getting the value as a float - // -- a delegate for setting the value from a float - // -- an optional delegate to update the value in the world. Most often used to - // push the new value to an in-world object. - // - // The single letter parameters for the delegates are: - // s = BSScene - // o = BSPhysObject - // p = string parameter name - // l = localID of referenced object - // v = value (float) - // cf = parameter configuration class (for fetching values from ini file) - private static ParameterDefn[] ParameterDefinitions = - { - new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", - ConfigurationParameters.numericTrue, - (s,cf,p,v) => { ShouldMeshSculptedPrim = cf.GetBoolean(p, BSParam.BoolNumeric(v)); }, - (s) => { return BSParam.NumericBool(ShouldMeshSculptedPrim); }, - (s,p,l,v) => { ShouldMeshSculptedPrim = BSParam.BoolNumeric(v); } ), - new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", - ConfigurationParameters.numericFalse, - (s,cf,p,v) => { ShouldForceSimplePrimMeshing = cf.GetBoolean(p, BSParam.BoolNumeric(v)); }, - (s) => { return BSParam.NumericBool(ShouldForceSimplePrimMeshing); }, - (s,p,l,v) => { ShouldForceSimplePrimMeshing = BSParam.BoolNumeric(v); } ), - new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects", - ConfigurationParameters.numericTrue, - (s,cf,p,v) => { ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, BSParam.BoolNumeric(v)); }, - (s) => { return BSParam.NumericBool(ShouldUseHullsForPhysicalObjects); }, - (s,p,l,v) => { ShouldUseHullsForPhysicalObjects = BSParam.BoolNumeric(v); } ), - - new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", - 8f, - (s,cf,p,v) => { MeshLOD = (float)cf.GetInt(p, (int)v); }, - (s) => { return MeshLOD; }, - (s,p,l,v) => { MeshLOD = v; } ), - new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters", - 16f, - (s,cf,p,v) => { MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); }, - (s) => { return MeshMegaPrimLOD; }, - (s,p,l,v) => { MeshMegaPrimLOD = v; } ), - new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD", - 10f, - (s,cf,p,v) => { MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); }, - (s) => { return MeshMegaPrimThreshold; }, - (s,p,l,v) => { MeshMegaPrimThreshold = v; } ), - new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", - 32f, - (s,cf,p,v) => { SculptLOD = (float)cf.GetInt(p, (int)v); }, - (s) => { return SculptLOD; }, - (s,p,l,v) => { SculptLOD = v; } ), - - new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps", - 10f, - (s,cf,p,v) => { s.m_maxSubSteps = cf.GetInt(p, (int)v); }, - (s) => { return (float)s.m_maxSubSteps; }, - (s,p,l,v) => { s.m_maxSubSteps = (int)v; } ), - new ParameterDefn("FixedTimeStep", "In simulation step, seconds of one substep (1/60)", - 1f / 60f, - (s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); }, - (s) => { return (float)s.m_fixedTimeStep; }, - (s,p,l,v) => { s.m_fixedTimeStep = v; } ), - new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame", - 2048f, - (s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); }, - (s) => { return (float)s.m_maxCollisionsPerFrame; }, - (s,p,l,v) => { s.m_maxCollisionsPerFrame = (int)v; } ), - new ParameterDefn("MaxUpdatesPerFrame", "Max updates returned at end of each frame", - 8000f, - (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); }, - (s) => { return (float)s.m_maxUpdatesPerFrame; }, - (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), - new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step", - 500f, - (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); }, - (s) => { return (float)s.m_taintsToProcessPerStep; }, - (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ), - new ParameterDefn("MinObjectMass", "Minimum object mass (0.0001)", - 0.0001f, - (s,cf,p,v) => { MinimumObjectMass = cf.GetFloat(p, v); }, - (s) => { return (float)MinimumObjectMass; }, - (s,p,l,v) => { MinimumObjectMass = v; } ), - new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", - 10000.01f, - (s,cf,p,v) => { MaximumObjectMass = cf.GetFloat(p, v); }, - (s) => { return (float)MaximumObjectMass; }, - (s,p,l,v) => { MaximumObjectMass = v; } ), - - new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", - 2200f, - (s,cf,p,v) => { PID_D = cf.GetFloat(p, v); }, - (s) => { return (float)PID_D; }, - (s,p,l,v) => { PID_D = v; } ), - new ParameterDefn("PID_P", "Parameteric factor for motion smoothing", - 900f, - (s,cf,p,v) => { PID_P = cf.GetFloat(p, v); }, - (s) => { return (float)PID_P; }, - (s,p,l,v) => { PID_P = v; } ), - - new ParameterDefn("DefaultFriction", "Friction factor used on new objects", - 0.2f, - (s,cf,p,v) => { s.UnmanagedParams[0].defaultFriction = cf.GetFloat(p, v); }, - (s) => { return s.UnmanagedParams[0].defaultFriction; }, - (s,p,l,v) => { s.UnmanagedParams[0].defaultFriction = v; } ), - new ParameterDefn("DefaultDensity", "Density for new objects" , - 10.000006836f, // Aluminum g/cm3 - (s,cf,p,v) => { s.UnmanagedParams[0].defaultDensity = cf.GetFloat(p, v); }, - (s) => { return s.UnmanagedParams[0].defaultDensity; }, - (s,p,l,v) => { s.UnmanagedParams[0].defaultDensity = v; } ), - new ParameterDefn("DefaultRestitution", "Bouncyness of an object" , - 0f, - (s,cf,p,v) => { s.UnmanagedParams[0].defaultRestitution = cf.GetFloat(p, v); }, - (s) => { return s.UnmanagedParams[0].defaultRestitution; }, - (s,p,l,v) => { s.UnmanagedParams[0].defaultRestitution = v; } ), - new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)", - 0.04f, - (s,cf,p,v) => { s.UnmanagedParams[0].collisionMargin = cf.GetFloat(p, v); }, - (s) => { return s.UnmanagedParams[0].collisionMargin; }, - (s,p,l,v) => { s.UnmanagedParams[0].collisionMargin = v; } ), - new ParameterDefn("Gravity", "Vertical force of gravity (negative means down)", - -9.80665f, - (s,cf,p,v) => { s.UnmanagedParams[0].gravity = cf.GetFloat(p, v); }, - (s) => { return s.UnmanagedParams[0].gravity; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{s.UnmanagedParams[0].gravity=x;}, p, PhysParameterEntry.APPLY_TO_NONE, v); }, - (s,o,v) => { BulletSimAPI.SetGravity2(s.World.ptr, new Vector3(0f,0f,v)); } ), - - - new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)", - 0f, - (s,cf,p,v) => { LinearDamping = cf.GetFloat(p, v); }, - (s) => { return LinearDamping; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{LinearDamping=x;}, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, AngularDamping); } ), - new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", - 0f, - (s,cf,p,v) => { AngularDamping = cf.GetFloat(p, v); }, - (s) => { return AngularDamping; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{AngularDamping=x;}, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, LinearDamping, v); } ), - new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", - 0.2f, - (s,cf,p,v) => { DeactivationTime = cf.GetFloat(p, v); }, - (s) => { return DeactivationTime; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{DeactivationTime=x;}, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.PhysBody.ptr, v); } ), - new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", - 0.8f, - (s,cf,p,v) => { LinearSleepingThreshold = cf.GetFloat(p, v); }, - (s) => { return LinearSleepingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{LinearSleepingThreshold=x;}, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ), - new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", - 1.0f, - (s,cf,p,v) => { AngularSleepingThreshold = cf.GetFloat(p, v); }, - (s) => { return AngularSleepingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{AngularSleepingThreshold=x;}, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ), - new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , - 0f, // set to zero to disable - (s,cf,p,v) => { CcdMotionThreshold = cf.GetFloat(p, v); }, - (s) => { return CcdMotionThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{CcdMotionThreshold=x;}, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.PhysBody.ptr, v); } ), - new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , - 0f, - (s,cf,p,v) => { CcdSweptSphereRadius = cf.GetFloat(p, v); }, - (s) => { return CcdSweptSphereRadius; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{CcdSweptSphereRadius=x;}, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetCcdSweptSphereRadius2(o.PhysBody.ptr, v); } ), - new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , - 0.1f, - (s,cf,p,v) => { ContactProcessingThreshold = cf.GetFloat(p, v); }, - (s) => { return ContactProcessingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{ContactProcessingThreshold=x;}, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ), - - new ParameterDefn("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)", - (float)BSTerrainPhys.TerrainImplementation.Heightmap, - (s,cf,p,v) => { TerrainImplementation = cf.GetFloat(p,v); }, - (s) => { return TerrainImplementation; }, - (s,p,l,v) => { TerrainImplementation = v; } ), - new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , - 0.3f, - (s,cf,p,v) => { TerrainFriction = cf.GetFloat(p, v); }, - (s) => { return TerrainFriction; }, - (s,p,l,v) => { TerrainFriction = v; /* TODO: set on real terrain */} ), - new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" , - 0.8f, - (s,cf,p,v) => { TerrainHitFraction = cf.GetFloat(p, v); }, - (s) => { return TerrainHitFraction; }, - (s,p,l,v) => { TerrainHitFraction = v; /* TODO: set on real terrain */ } ), - new ParameterDefn("TerrainRestitution", "Bouncyness" , - 0f, - (s,cf,p,v) => { TerrainRestitution = cf.GetFloat(p, v); }, - (s) => { return TerrainRestitution; }, - (s,p,l,v) => { TerrainRestitution = v; /* TODO: set on real terrain */ } ), - new ParameterDefn("TerrainCollisionMargin", "Margin where collision checking starts" , - 0.04f, - (s,cf,p,v) => { TerrainCollisionMargin = cf.GetFloat(p, v); }, - (s) => { return TerrainCollisionMargin; }, - (s,p,l,v) => { TerrainCollisionMargin = v; /* TODO: set on real terrain */ } ), - - new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", - 0.2f, - (s,cf,p,v) => { AvatarFriction = cf.GetFloat(p, v); }, - (s) => { return AvatarFriction; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarFriction=x;}, p, l, v); } ), - new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.", - 10.0f, - (s,cf,p,v) => { AvatarStandingFriction = cf.GetFloat(p, v); }, - (s) => { return AvatarStandingFriction; }, - (s,p,l,v) => { AvatarStandingFriction = v; } ), - new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", - 3.5f, - (s,cf,p,v) => { AvatarDensity = cf.GetFloat(p, v); }, - (s) => { return AvatarDensity; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarDensity=x;}, p, l, v); } ), - new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", - 0f, - (s,cf,p,v) => { AvatarRestitution = cf.GetFloat(p, v); }, - (s) => { return AvatarRestitution; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarRestitution=x;}, p, l, v); } ), - new ParameterDefn("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule", - 0.6f, - (s,cf,p,v) => { AvatarCapsuleWidth = cf.GetFloat(p, v); }, - (s) => { return AvatarCapsuleWidth; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarCapsuleWidth=x;}, p, l, v); } ), - new ParameterDefn("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule", - 0.45f, - (s,cf,p,v) => { AvatarCapsuleDepth = cf.GetFloat(p, v); }, - (s) => { return AvatarCapsuleDepth; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarCapsuleDepth=x;}, p, l, v); } ), - new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", - 1.5f, - (s,cf,p,v) => { AvatarCapsuleHeight = cf.GetFloat(p, v); }, - (s) => { return AvatarCapsuleHeight; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarCapsuleHeight=x;}, p, l, v); } ), - new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", - 0.1f, - (s,cf,p,v) => { AvatarContactProcessingThreshold = cf.GetFloat(p, v); }, - (s) => { return AvatarContactProcessingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarContactProcessingThreshold=x;}, p, l, v); } ), - - new ParameterDefn("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)", - 0.95f, - (s,cf,p,v) => { VehicleAngularDamping = cf.GetFloat(p, v); }, - (s) => { return VehicleAngularDamping; }, - (s,p,l,v) => { VehicleAngularDamping = v; } ), - - new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", - 0f, - (s,cf,p,v) => { s.UnmanagedParams[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); }, - (s) => { return s.UnmanagedParams[0].maxPersistantManifoldPoolSize; }, - (s,p,l,v) => { s.UnmanagedParams[0].maxPersistantManifoldPoolSize = v; } ), - new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)", - 0f, - (s,cf,p,v) => { s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); }, - (s) => { return s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize; }, - (s,p,l,v) => { s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize = v; } ), - new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count", - ConfigurationParameters.numericFalse, - (s,cf,p,v) => { s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, - (s) => { return s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation; }, - (s,p,l,v) => { s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = v; } ), - new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step", - ConfigurationParameters.numericFalse, - (s,cf,p,v) => { s.UnmanagedParams[0].shouldForceUpdateAllAabbs = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, - (s) => { return s.UnmanagedParams[0].shouldForceUpdateAllAabbs; }, - (s,p,l,v) => { s.UnmanagedParams[0].shouldForceUpdateAllAabbs = v; } ), - new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction", - ConfigurationParameters.numericTrue, - (s,cf,p,v) => { s.UnmanagedParams[0].shouldRandomizeSolverOrder = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, - (s) => { return s.UnmanagedParams[0].shouldRandomizeSolverOrder; }, - (s,p,l,v) => { s.UnmanagedParams[0].shouldRandomizeSolverOrder = v; } ), - new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands", - ConfigurationParameters.numericTrue, - (s,cf,p,v) => { s.UnmanagedParams[0].shouldSplitSimulationIslands = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, - (s) => { return s.UnmanagedParams[0].shouldSplitSimulationIslands; }, - (s,p,l,v) => { s.UnmanagedParams[0].shouldSplitSimulationIslands = v; } ), - new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching", - ConfigurationParameters.numericFalse, - (s,cf,p,v) => { s.UnmanagedParams[0].shouldEnableFrictionCaching = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, - (s) => { return s.UnmanagedParams[0].shouldEnableFrictionCaching; }, - (s,p,l,v) => { s.UnmanagedParams[0].shouldEnableFrictionCaching = v; } ), - new ParameterDefn("NumberOfSolverIterations", "Number of internal iterations (0 means default)", - 0f, // zero says use Bullet default - (s,cf,p,v) => { s.UnmanagedParams[0].numberOfSolverIterations = cf.GetFloat(p, v); }, - (s) => { return s.UnmanagedParams[0].numberOfSolverIterations; }, - (s,p,l,v) => { s.UnmanagedParams[0].numberOfSolverIterations = v; } ), - - new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)", - (float)BSLinkset.LinksetImplementation.Compound, - (s,cf,p,v) => { LinksetImplementation = cf.GetFloat(p,v); }, - (s) => { return LinksetImplementation; }, - (s,p,l,v) => { LinksetImplementation = v; } ), - new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", - ConfigurationParameters.numericFalse, - (s,cf,p,v) => { LinkConstraintUseFrameOffset = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, - (s) => { return LinkConstraintUseFrameOffset; }, - (s,p,l,v) => { LinkConstraintUseFrameOffset = v; } ), - new ParameterDefn("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints", - ConfigurationParameters.numericTrue, - (s,cf,p,v) => { LinkConstraintEnableTransMotor = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, - (s) => { return LinkConstraintEnableTransMotor; }, - (s,p,l,v) => { LinkConstraintEnableTransMotor = v; } ), - new ParameterDefn("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints", - 5.0f, - (s,cf,p,v) => { LinkConstraintTransMotorMaxVel = cf.GetFloat(p, v); }, - (s) => { return LinkConstraintTransMotorMaxVel; }, - (s,p,l,v) => { LinkConstraintTransMotorMaxVel = v; } ), - new ParameterDefn("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints", - 0.1f, - (s,cf,p,v) => { LinkConstraintTransMotorMaxForce = cf.GetFloat(p, v); }, - (s) => { return LinkConstraintTransMotorMaxForce; }, - (s,p,l,v) => { LinkConstraintTransMotorMaxForce = v; } ), - new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", - 0.1f, - (s,cf,p,v) => { LinkConstraintCFM = cf.GetFloat(p, v); }, - (s) => { return LinkConstraintCFM; }, - (s,p,l,v) => { LinkConstraintCFM = v; } ), - new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", - 0.1f, - (s,cf,p,v) => { LinkConstraintERP = cf.GetFloat(p, v); }, - (s) => { return LinkConstraintERP; }, - (s,p,l,v) => { LinkConstraintERP = v; } ), - new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)", - 40, - (s,cf,p,v) => { LinkConstraintSolverIterations = cf.GetFloat(p, v); }, - (s) => { return LinkConstraintSolverIterations; }, - (s,p,l,v) => { LinkConstraintSolverIterations = v; } ), - - new ParameterDefn("LogPhysicsStatisticsFrames", "Frames between outputting detailed phys stats. (0 is off)", - 0f, - (s,cf,p,v) => { s.UnmanagedParams[0].physicsLoggingFrames = cf.GetInt(p, (int)v); }, - (s) => { return (float)s.UnmanagedParams[0].physicsLoggingFrames; }, - (s,p,l,v) => { s.UnmanagedParams[0].physicsLoggingFrames = (int)v; } ), - }; - - // Convert a boolean to our numeric true and false values - public static float NumericBool(bool b) - { - return (b ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse); - } - - // Convert numeric true and false values to a boolean - public static bool BoolNumeric(float b) - { - return (b == ConfigurationParameters.numericTrue ? true : false); - } - - // Search through the parameter definitions and return the matching - // ParameterDefn structure. - // Case does not matter as names are compared after converting to lower case. - // Returns 'false' if the parameter is not found. - internal static bool TryGetParameter(string paramName, out ParameterDefn defn) - { - bool ret = false; - ParameterDefn foundDefn = new ParameterDefn(); - string pName = paramName.ToLower(); - - foreach (ParameterDefn parm in ParameterDefinitions) - { - if (pName == parm.name.ToLower()) - { - foundDefn = parm; - ret = true; - break; - } - } - defn = foundDefn; - return ret; - } - - // Pass through the settable parameters and set the default values - internal static void SetParameterDefaultValues(BSScene physicsScene) - { - foreach (ParameterDefn parm in ParameterDefinitions) - { - parm.setter(physicsScene, parm.name, PhysParameterEntry.APPLY_TO_NONE, parm.defaultValue); - } - } - - // Get user set values out of the ini file. - internal static void SetParameterConfigurationValues(BSScene physicsScene, IConfig cfg) - { - foreach (ParameterDefn parm in ParameterDefinitions) - { - parm.userParam(physicsScene, cfg, parm.name, parm.defaultValue); - } - } - - internal static PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1]; - - // This creates an array in the correct format for returning the list of - // parameters. This is used by the 'list' option of the 'physics' command. - internal static void BuildParameterTable() - { - if (SettableParameters.Length < ParameterDefinitions.Length) - { - List entries = new List(); - for (int ii = 0; ii < ParameterDefinitions.Length; ii++) - { - ParameterDefn pd = ParameterDefinitions[ii]; - entries.Add(new PhysParameterEntry(pd.name, pd.desc)); - } - - // make the list in alphabetical order for estetic reasons - entries.Sort(delegate(PhysParameterEntry ppe1, PhysParameterEntry ppe2) - { - return ppe1.name.CompareTo(ppe2.name); - }); - - SettableParameters = entries.ToArray(); - } - } - - -} -} diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSNPlugin/BSPhysObject.cs deleted file mode 100644 index 689da7f..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BSPhysObject.cs +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OMV = OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.BulletSNPlugin -{ -/* - * Class to wrap all objects. - * The rest of BulletSim doesn't need to keep checking for avatars or prims - * unless the difference is significant. - * - * Variables in the physicsl objects are in three forms: - * VariableName: used by the simulator and performs taint operations, etc - * RawVariableName: direct reference to the BulletSim storage for the variable value - * ForceVariableName: direct reference (store and fetch) to the value in the physics engine. - * The last two (and certainly the last one) should be referenced only in taint-time. - */ - -/* - * As of 20121221, the following are the call sequences (going down) for different script physical functions: - * llApplyImpulse llApplyRotImpulse llSetTorque llSetForce - * SOP.ApplyImpulse SOP.ApplyAngularImpulse SOP.SetAngularImpulse SOP.SetForce - * SOG.ApplyImpulse SOG.ApplyAngularImpulse SOG.SetAngularImpulse - * PA.AddForce PA.AddAngularForce PA.Torque = v PA.Force = v - * BS.ApplyCentralForce BS.ApplyTorque - */ - -public abstract class BSPhysObject : PhysicsActor -{ - protected BSPhysObject() - { - } - protected BSPhysObject(BSScene parentScene, uint localID, string name, string typeName) - { - PhysicsScene = parentScene; - LocalID = localID; - PhysObjectName = name; - TypeName = typeName; - - Linkset = BSLinkset.Factory(PhysicsScene, this); - LastAssetBuildFailed = false; - - // Default material type - Material = MaterialAttributes.Material.Wood; - - CollisionCollection = new CollisionEventUpdate(); - SubscribedEventsMs = 0; - CollidingStep = 0; - CollidingGroundStep = 0; - } - - // Tell the object to clean up. - public virtual void Destroy() - { - UnRegisterAllPreStepActions(); - } - - public BSScene PhysicsScene { get; protected set; } - // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor - public string PhysObjectName { get; protected set; } - public string TypeName { get; protected set; } - - public BSLinkset Linkset { get; set; } - public BSLinksetInfo LinksetInfo { get; set; } - - // Return the object mass without calculating it or having side effects - public abstract float RawMass { get; } - // Set the raw mass but also update physical mass properties (inertia, ...) - // 'inWorld' true if the object has already been added to the dynamic world. - public abstract void UpdatePhysicalMassProperties(float mass, bool inWorld); - - // The last value calculated for the prim's inertia - public OMV.Vector3 Inertia { get; set; } - - // Reference to the physical body (btCollisionObject) of this object - public BulletBody PhysBody; - // Reference to the physical shape (btCollisionShape) of this object - public BulletShape PhysShape; - - // 'true' if the mesh's underlying asset failed to build. - // This will keep us from looping after the first time the build failed. - public bool LastAssetBuildFailed { get; set; } - - // The objects base shape information. Null if not a prim type shape. - public PrimitiveBaseShape BaseShape { get; protected set; } - // Some types of objects have preferred physical representations. - // Returns SHAPE_UNKNOWN if there is no preference. - public virtual BSPhysicsShapeType PreferredPhysicalShape - { - get { return BSPhysicsShapeType.SHAPE_UNKNOWN; } - } - - // When the physical properties are updated, an EntityProperty holds the update values. - // Keep the current and last EntityProperties to enable computation of differences - // between the current update and the previous values. - public EntityProperties CurrentEntityProperties { get; set; } - public EntityProperties LastEntityProperties { get; set; } - - public virtual OMV.Vector3 Scale { get; set; } - public abstract bool IsSolid { get; } - public abstract bool IsStatic { get; } - - // Materialness - public MaterialAttributes.Material Material { get; private set; } - public override void SetMaterial(int material) - { - Material = (MaterialAttributes.Material)material; - } - - // Stop all physical motion. - public abstract void ZeroMotion(bool inTaintTime); - public abstract void ZeroAngularMotion(bool inTaintTime); - - // Step the vehicle simulation for this object. A NOOP if the vehicle was not configured. - public virtual void StepVehicle(float timeStep) { } - - // Update the physical location and motion of the object. Called with data from Bullet. - public abstract void UpdateProperties(EntityProperties entprop); - - public abstract OMV.Vector3 RawPosition { get; set; } - public abstract OMV.Vector3 ForcePosition { get; set; } - - public abstract OMV.Quaternion RawOrientation { get; set; } - public abstract OMV.Quaternion ForceOrientation { get; set; } - - // The system is telling us the velocity it wants to move at. - // protected OMV.Vector3 m_targetVelocity; // use the definition in PhysicsActor - public override OMV.Vector3 TargetVelocity - { - get { return m_targetVelocity; } - set - { - m_targetVelocity = value; - Velocity = value; - } - } - public abstract OMV.Vector3 ForceVelocity { get; set; } - - public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } - - public abstract float ForceBuoyancy { get; set; } - - public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } - - #region Collisions - - // Requested number of milliseconds between collision events. Zero means disabled. - protected int SubscribedEventsMs { get; set; } - // Given subscription, the time that a collision may be passed up - protected int NextCollisionOkTime { get; set; } - // The simulation step that last had a collision - protected long CollidingStep { get; set; } - // The simulation step that last had a collision with the ground - protected long CollidingGroundStep { get; set; } - // The collision flags we think are set in Bullet - protected CollisionFlags CurrentCollisionFlags { get; set; } - - // The collisions that have been collected this tick - protected CollisionEventUpdate CollisionCollection; - - // The simulation step is telling this object about a collision. - // Return 'true' if a collision was processed and should be sent up. - // Called at taint time from within the Step() function - public virtual bool Collide(uint collidingWith, BSPhysObject collidee, - OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) - { - bool ret = false; - - // The following lines make IsColliding() and IsCollidingGround() work - CollidingStep = PhysicsScene.SimulationStep; - if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID) - { - CollidingGroundStep = PhysicsScene.SimulationStep; - } - - // prims in the same linkset cannot collide with each other - if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) - { - return ret; - } - - // if someone has subscribed for collision events.... - if (SubscribedEvents()) { - CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); - DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}", - LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth); - - ret = true; - } - return ret; - } - - // Send the collected collisions into the simulator. - // Called at taint time from within the Step() function thus no locking problems - // with CollisionCollection and ObjectsWithNoMoreCollisions. - // Return 'true' if there were some actual collisions passed up - public virtual bool SendCollisions() - { - bool ret = true; - // If the 'no collision' call, force it to happen right now so quick collision_end - bool force = (CollisionCollection.Count == 0); - - // throttle the collisions to the number of milliseconds specified in the subscription - if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) - { - NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs; - - // We are called if we previously had collisions. If there are no collisions - // this time, send up one last empty event so OpenSim can sense collision end. - if (CollisionCollection.Count == 0) - { - // If I have no collisions this time, remove me from the list of objects with collisions. - ret = false; - } - - // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count); - base.SendCollisionUpdate(CollisionCollection); - - // The CollisionCollection instance is passed around in the simulator. - // Make sure we don't have a handle to that one and that a new one is used for next time. - // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here, - // a race condition is created for the other users of this instance. - CollisionCollection = new CollisionEventUpdate(); - } - return ret; - } - - // Subscribe for collision events. - // Parameter is the millisecond rate the caller wishes collision events to occur. - public override void SubscribeEvents(int ms) { - // DetailLog("{0},{1}.SubscribeEvents,subscribing,ms={2}", LocalID, TypeName, ms); - SubscribedEventsMs = ms; - if (ms > 0) - { - // make sure first collision happens - NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs); - - PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() - { - if (PhysBody.HasPhysicalBody) - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - }); - } - else - { - // Subscribing for zero or less is the same as unsubscribing - UnSubscribeEvents(); - } - } - public override void UnSubscribeEvents() { - // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName); - SubscribedEventsMs = 0; - PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() - { - // Make sure there is a body there because sometimes destruction happens in an un-ideal order. - if (PhysBody.HasPhysicalBody) - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - }); - } - // Return 'true' if the simulator wants collision events - public override bool SubscribedEvents() { - return (SubscribedEventsMs > 0); - } - - #endregion // Collisions - - #region Per Simulation Step actions - // There are some actions that must be performed for a physical object before each simulation step. - // These actions are optional so, rather than scanning all the physical objects and asking them - // if they have anything to do, a physical object registers for an event call before the step is performed. - // This bookkeeping makes it easy to add, remove and clean up after all these registrations. - private Dictionary RegisteredActions = new Dictionary(); - protected void RegisterPreStepAction(string op, uint id, BSScene.PreStepAction actn) - { - string identifier = op + "-" + id.ToString(); - RegisteredActions[identifier] = actn; - PhysicsScene.BeforeStep += actn; - DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier); - } - - // Unregister a pre step action. Safe to call if the action has not been registered. - protected void UnRegisterPreStepAction(string op, uint id) - { - string identifier = op + "-" + id.ToString(); - bool removed = false; - if (RegisteredActions.ContainsKey(identifier)) - { - PhysicsScene.BeforeStep -= RegisteredActions[identifier]; - RegisteredActions.Remove(identifier); - removed = true; - } - DetailLog("{0},BSPhysObject.UnRegisterPreStepAction,id={1},removed={2}", LocalID, identifier, removed); - } - - protected void UnRegisterAllPreStepActions() - { - foreach (KeyValuePair kvp in RegisteredActions) - { - PhysicsScene.BeforeStep -= kvp.Value; - } - RegisteredActions.Clear(); - DetailLog("{0},BSPhysObject.UnRegisterAllPreStepActions,", LocalID); - } - - - #endregion // Per Simulation Step actions - - // High performance detailed logging routine used by the physical objects. - protected void DetailLog(string msg, params Object[] args) - { - if (PhysicsScene.PhysicsLogging.Enabled) - PhysicsScene.DetailLog(msg, args); - } - -} -} diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSPlugin.cs b/OpenSim/Region/Physics/BulletSNPlugin/BSPlugin.cs deleted file mode 100644 index 75963ee..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BSPlugin.cs +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSNPlugin -{ - /// - /// Entry for a port of Bullet (http://bulletphysics.org/) to OpenSim. - /// This module interfaces to an unmanaged C++ library which makes the - /// actual calls into the Bullet physics engine. - /// The unmanaged library is found in opensim-libs::trunk/unmanaged/BulletSim/. - /// The unmanaged library is compiled and linked statically with Bullet - /// to create BulletSim.dll and libBulletSim.so (for both 32 and 64 bit). - /// -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) - { - - // If not Windows, loading is performed by the - // Mono loader as specified in - // "bin/Physics/OpenSim.Region.Physics.BulletSNPlugin.dll.config". - - _mScene = new BSScene(sceneIdentifier); - } - return (_mScene); - } - - public string GetName() - { - return ("BulletSimN"); - } - - public void Dispose() - { - } -} -} diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSNPlugin/BSPrim.cs deleted file mode 100644 index aadb5b2..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BSPrim.cs +++ /dev/null @@ -1,1494 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Reflection; -using System.Collections.Generic; -using System.Xml; -using log4net; -using OMV = OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; -using OpenSim.Region.Physics.ConvexDecompositionDotNet; - -namespace OpenSim.Region.Physics.BulletSNPlugin -{ - - [Serializable] -public sealed class BSPrim : BSPhysObject -{ - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private static readonly string LogHeader = "[BULLETS PRIM]"; - - // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. - private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user - - private bool _grabbed; - private bool _isSelected; - private bool _isVolumeDetect; - private OMV.Vector3 _position; - private float _mass; // the mass of this object - private float _density; - private OMV.Vector3 _force; - private OMV.Vector3 _velocity; - private OMV.Vector3 _torque; - private float _collisionScore; - private OMV.Vector3 _acceleration; - private OMV.Quaternion _orientation; - private int _physicsActorType; - private bool _isPhysical; - private bool _flying; - private float _friction; - private float _restitution; - private bool _setAlwaysRun; - private bool _throttleUpdates; - private bool _isColliding; - private bool _collidingGround; - private bool _collidingObj; - private bool _floatOnWater; - private OMV.Vector3 _rotationalVelocity; - private bool _kinematic; - private float _buoyancy; - - private BSDynamics _vehicle; - - private OMV.Vector3 _PIDTarget; - private bool _usePID; - private float _PIDTau; - private bool _useHoverPID; - private float _PIDHoverHeight; - private PIDHoverType _PIDHoverType; - private float _PIDHoverTao; - - public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, - OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) - : base(parent_scene, localID, primName, "BSPrim") - { - // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); - _physicsActorType = (int)ActorTypes.Prim; - _position = pos; - _size = size; - Scale = size; // prims are the size the user wants them to be (different for BSCharactes). - _orientation = rotation; - _buoyancy = 1f; - _velocity = OMV.Vector3.Zero; - _rotationalVelocity = OMV.Vector3.Zero; - BaseShape = pbs; - _isPhysical = pisPhysical; - _isVolumeDetect = false; - - // Someday set default attributes based on the material but, for now, we don't know the prim material yet. - // MaterialAttributes primMat = BSMaterials.GetAttributes(Material, pisPhysical); - _density = PhysicsScene.Params.defaultDensity; - _friction = PhysicsScene.Params.defaultFriction; - _restitution = PhysicsScene.Params.defaultRestitution; - - _vehicle = new BSDynamics(PhysicsScene, this); // add vehicleness - - _mass = CalculateMass(); - - Linkset.Refresh(this); - - DetailLog("{0},BSPrim.constructor,call", LocalID); - // do the actual object creation at taint time - PhysicsScene.TaintedObject("BSPrim.create", delegate() - { - CreateGeomAndObject(true); - - CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(PhysBody.ptr); - }); - } - - // called when this prim is being destroyed and we should free all the resources - public override void Destroy() - { - // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); - base.Destroy(); - - // Undo any links between me and any other object - BSPhysObject parentBefore = Linkset.LinksetRoot; - int childrenBefore = Linkset.NumberOfChildren; - - Linkset = Linkset.RemoveMeFromLinkset(this); - - DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}", - LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); - - // Undo any vehicle properties - this.VehicleType = (int)Vehicle.TYPE_NONE; - - PhysicsScene.TaintedObject("BSPrim.destroy", delegate() - { - DetailLog("{0},BSPrim.Destroy,taint,", LocalID); - // If there are physical body and shape, release my use of same. - PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); - PhysBody.Clear(); - PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); - PhysShape.Clear(); - }); - } - - // No one uses this property. - public override bool Stopped { - get { return false; } - } - public override OMV.Vector3 Size { - get { return _size; } - set { - // We presume the scale and size are the same. If scale must be changed for - // the physical shape, that is done when the geometry is built. - _size = value; - Scale = _size; - ForceBodyShapeRebuild(false); - } - } - - public override PrimitiveBaseShape Shape { - set { - BaseShape = value; - ForceBodyShapeRebuild(false); - } - } - // Whatever the linkset wants is what I want. - public override BSPhysicsShapeType PreferredPhysicalShape - { get { return Linkset.PreferredPhysicalShape(this); } } - - public override bool ForceBodyShapeRebuild(bool inTaintTime) - { - LastAssetBuildFailed = false; - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate() - { - _mass = CalculateMass(); // changing the shape changes the mass - CreateGeomAndObject(true); - }); - return true; - } - public override bool Grabbed { - set { _grabbed = value; - } - } - public override bool Selected { - set - { - if (value != _isSelected) - { - _isSelected = value; - PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() - { - DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); - SetObjectDynamic(false); - }); - } - } - } - public override void CrossingFailure() { return; } - - // link me to the specified parent - public override void link(PhysicsActor obj) { - BSPrim parent = obj as BSPrim; - if (parent != null) - { - BSPhysObject parentBefore = Linkset.LinksetRoot; - int childrenBefore = Linkset.NumberOfChildren; - - Linkset = parent.Linkset.AddMeToLinkset(this); - - DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", - LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); - } - return; - } - - // delink me from my linkset - public override void delink() { - // TODO: decide if this parent checking needs to happen at taint time - // Race condition here: if link() and delink() in same simulation tick, the delink will not happen - - BSPhysObject parentBefore = Linkset.LinksetRoot; - int childrenBefore = Linkset.NumberOfChildren; - - Linkset = Linkset.RemoveMeFromLinkset(this); - - DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", - LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); - return; - } - - // Set motion values to zero. - // Do it to the properties so the values get set in the physics engine. - // Push the setting of the values to the viewer. - // Called at taint time! - public override void ZeroMotion(bool inTaintTime) - { - _velocity = OMV.Vector3.Zero; - _acceleration = OMV.Vector3.Zero; - _rotationalVelocity = OMV.Vector3.Zero; - - // Zero some other properties in the physics engine - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() - { - if (PhysBody.HasPhysicalBody) - BulletSimAPI.ClearAllForces2(PhysBody.ptr); - }); - } - public override void ZeroAngularMotion(bool inTaintTime) - { - _rotationalVelocity = OMV.Vector3.Zero; - // Zero some other properties in the physics engine - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() - { - // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity); - if (PhysBody.HasPhysicalBody) - { - BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, _rotationalVelocity); - BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity); - } - }); - } - - public override void LockAngularMotion(OMV.Vector3 axis) - { - DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); - return; - } - - public override OMV.Vector3 RawPosition - { - get { return _position; } - set { _position = value; } - } - public override OMV.Vector3 Position { - get { - /* NOTE: this refetch is not necessary. The simulator knows about linkset children - * and does not fetch this position info for children. Thus this is commented out. - // child prims move around based on their parent. Need to get the latest location - if (!Linkset.IsRoot(this)) - _position = Linkset.PositionGet(this); - */ - - // don't do the GetObjectPosition for root elements because this function is called a zillion times. - // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); - return _position; - } - set { - // If the position must be forced into the physics engine, use ForcePosition. - // All positions are given in world positions. - if (_position == value) - { - DetailLog("{0},BSPrim.setPosition,taint,positionNotChanging,pos={1},orient={2}", LocalID, _position, _orientation); - return; - } - _position = value; - PositionSanityCheck(false); - - // A linkset might need to know if a component information changed. - Linkset.UpdateProperties(this, false); - - PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() - { - DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); - ForcePosition = _position; - }); - } - } - public override OMV.Vector3 ForcePosition { - get { - _position = BulletSimAPI.GetPosition2(PhysBody.ptr); - return _position; - } - set { - _position = value; - if (PhysBody.HasPhysicalBody) - { - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - ActivateIfPhysical(false); - } - } - } - - // Check that the current position is sane and, if not, modify the position to make it so. - // Check for being below terrain and being out of bounds. - // Returns 'true' of the position was made sane by some action. - private bool PositionSanityCheck(bool inTaintTime) - { - bool ret = false; - - if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(_position)) - { - // The physical object is out of the known/simulated area. - // Upper levels of code will handle the transition to other areas so, for - // the time, we just ignore the position. - return ret; - } - - float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); - OMV.Vector3 upForce = OMV.Vector3.Zero; - if (RawPosition.Z < terrainHeight) - { - DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); - float targetHeight = terrainHeight + (Size.Z / 2f); - // Upforce proportional to the distance away from the terrain. Correct the error in 1 sec. - upForce.Z = (terrainHeight - RawPosition.Z) * 1f; - ret = true; - } - - if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) - { - float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position); - // TODO: a floating motor so object will bob in the water - if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f) - { - // Upforce proportional to the distance away from the water. Correct the error in 1 sec. - upForce.Z = (waterHeight - RawPosition.Z) * 1f; - ret = true; - } - } - - // The above code computes a force to apply to correct any out-of-bounds problems. Apply same. - // TODO: This should be intergrated with a geneal physics action mechanism. - // TODO: This should be moderated with PID'ness. - if (ret) - { - // Apply upforce and overcome gravity. - OMV.Vector3 correctionForce = upForce - PhysicsScene.DefaultGravity; - DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, _position, upForce, correctionForce); - AddForce(correctionForce, false, inTaintTime); - } - return ret; - } - - // Return the effective mass of the object. - // The definition of this call is to return the mass of the prim. - // If the simulator cares about the mass of the linkset, it will sum it itself. - public override float Mass - { - get - { - return _mass; - } - } - - // used when we only want this prim's mass and not the linkset thing - public override float RawMass { - get { return _mass; } - } - // Set the physical mass to the passed mass. - // Note that this does not change _mass! - public override void UpdatePhysicalMassProperties(float physMass, bool inWorld) - { - if (PhysBody.HasPhysicalBody) - { - if (IsStatic) - { - Inertia = OMV.Vector3.Zero; - BulletSimAPI.SetMassProps2(PhysBody.ptr, 0f, Inertia); - BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr); - } - else - { - if (inWorld) - { - // Changing interesting properties doesn't change proxy and collision cache - // information. The Bullet solution is to re-add the object to the world - // after parameters are changed. - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr); - } - - Inertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass); - BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, Inertia); - BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr); - - // center of mass is at the zero of the object - // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation); - DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2},inWorld={3}", LocalID, physMass, Inertia, inWorld); - - if (inWorld) - { - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr,_position,_orientation); - } - - // Must set gravity after it has been added to the world because, for unknown reasons, - // adding the object resets the object's gravity to world gravity - OMV.Vector3 grav = PhysicsScene.DefaultGravity * (1f - Buoyancy); - BulletSimAPI.SetGravity2(PhysBody.ptr, grav); - - } - } - } - - // Is this used? - public override OMV.Vector3 CenterOfMass - { - get { return Linkset.CenterOfMass; } - } - - // Is this used? - public override OMV.Vector3 GeometricCenter - { - get { return Linkset.GeometricCenter; } - } - - public override OMV.Vector3 Force { - get { return _force; } - set { - _force = value; - if (_force != OMV.Vector3.Zero) - { - // If the force is non-zero, it must be reapplied each tick because - // Bullet clears the forces applied last frame. - RegisterPreStepAction("BSPrim.setForce", LocalID, - delegate(float timeStep) - { - DetailLog("{0},BSPrim.setForce,preStep,force={1}", LocalID, _force); - if (PhysBody.HasPhysicalBody) - { - BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, _force); - ActivateIfPhysical(false); - } - } - ); - } - else - { - UnRegisterPreStepAction("BSPrim.setForce", LocalID); - } - } - } - - public override int VehicleType { - get { - return (int)_vehicle.Type; // if we are a vehicle, return that type - } - set { - Vehicle type = (Vehicle)value; - - PhysicsScene.TaintedObject("setVehicleType", delegate() - { - // Done at taint time so we're sure the physics engine is not using the variables - // Vehicle code changes the parameters for this vehicle type. - _vehicle.ProcessTypeChange(type); - ActivateIfPhysical(false); - - // If an active vehicle, register the vehicle code to be called before each step - if (_vehicle.Type == Vehicle.TYPE_NONE) - UnRegisterPreStepAction("BSPrim.Vehicle", LocalID); - else - RegisterPreStepAction("BSPrim.Vehicle", LocalID, _vehicle.Step); - }); - } - } - public override void VehicleFloatParam(int param, float value) - { - PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() - { - _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); - ActivateIfPhysical(false); - }); - } - public override void VehicleVectorParam(int param, OMV.Vector3 value) - { - PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() - { - _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); - ActivateIfPhysical(false); - }); - } - public override void VehicleRotationParam(int param, OMV.Quaternion rotation) - { - PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() - { - _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); - ActivateIfPhysical(false); - }); - } - public override void VehicleFlags(int param, bool remove) - { - PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate() - { - _vehicle.ProcessVehicleFlags(param, remove); - }); - } - - // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more - public override void SetVolumeDetect(int param) { - bool newValue = (param != 0); - if (_isVolumeDetect != newValue) - { - _isVolumeDetect = newValue; - PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate() - { - // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); - SetObjectDynamic(true); - }); - } - return; - } - public override OMV.Vector3 Velocity { - get { return _velocity; } - set { - _velocity = value; - PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() - { - // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); - ForceVelocity = _velocity; - }); - } - } - public override OMV.Vector3 ForceVelocity { - get { return _velocity; } - set { - PhysicsScene.AssertInTaintTime("BSPrim.ForceVelocity"); - - _velocity = value; - if (PhysBody.HasPhysicalBody) - { - BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); - ActivateIfPhysical(false); - } - } - } - public override OMV.Vector3 Torque { - get { return _torque; } - set { - _torque = value; - if (_torque != OMV.Vector3.Zero) - { - // If the torque is non-zero, it must be reapplied each tick because - // Bullet clears the forces applied last frame. - RegisterPreStepAction("BSPrim.setTorque", LocalID, - delegate(float timeStep) - { - if (PhysBody.HasPhysicalBody) - AddAngularForce(_torque, false, true); - } - ); - } - else - { - UnRegisterPreStepAction("BSPrim.setTorque", LocalID); - } - // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); - } - } - public override float CollisionScore { - get { return _collisionScore; } - set { _collisionScore = value; - } - } - public override OMV.Vector3 Acceleration { - get { return _acceleration; } - set { _acceleration = value; } - } - public override OMV.Quaternion RawOrientation - { - get { return _orientation; } - set { _orientation = value; } - } - public override OMV.Quaternion Orientation { - get { - /* NOTE: this refetch is not necessary. The simulator knows about linkset children - * and does not fetch this position info for children. Thus this is commented out. - // Children move around because tied to parent. Get a fresh value. - if (!Linkset.IsRoot(this)) - { - _orientation = Linkset.OrientationGet(this); - } - */ - return _orientation; - } - set { - if (_orientation == value) - return; - _orientation = value; - - // A linkset might need to know if a component information changed. - Linkset.UpdateProperties(this, false); - - PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() - { - if (PhysBody.HasPhysicalBody) - { - // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); - // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - } - }); - } - } - // Go directly to Bullet to get/set the value. - public override OMV.Quaternion ForceOrientation - { - get - { - _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr); - return _orientation; - } - set - { - _orientation = value; - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - } - } - public override int PhysicsActorType { - get { return _physicsActorType; } - set { _physicsActorType = value; } - } - public override bool IsPhysical { - get { return _isPhysical; } - set { - if (_isPhysical != value) - { - _isPhysical = value; - PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate() - { - // DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); - SetObjectDynamic(true); - // whether phys-to-static or static-to-phys, the object is not moving. - ZeroMotion(true); - }); - } - } - } - - // An object is static (does not move) if selected or not physical - public override bool IsStatic - { - get { return _isSelected || !IsPhysical; } - } - - // An object is solid if it's not phantom and if it's not doing VolumeDetect - public override bool IsSolid - { - get { return !IsPhantom && !_isVolumeDetect; } - } - - // Make gravity work if the object is physical and not selected - // Called at taint-time!! - private void SetObjectDynamic(bool forceRebuild) - { - // Recreate the physical object if necessary - CreateGeomAndObject(forceRebuild); - } - - // Convert the simulator's physical properties into settings on BulletSim objects. - // There are four flags we're interested in: - // IsStatic: Object does not move, otherwise the object has mass and moves - // isSolid: other objects bounce off of this object - // isVolumeDetect: other objects pass through but can generate collisions - // collisionEvents: whether this object returns collision events - private void UpdatePhysicalParameters() - { - // DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape); - - // Mangling all the physical properties requires the object not be in the physical world. - // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr); - - // Set up the object physicalness (does gravity and collisions move this object) - MakeDynamic(IsStatic); - - // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters) - _vehicle.Refresh(); - - // Arrange for collision events if the simulator wants them - EnableCollisions(SubscribedEvents()); - - // Make solid or not (do things bounce off or pass through this object). - MakeSolid(IsSolid); - - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr, _position, _orientation); - - // Rebuild its shape - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); - - // Collision filter can be set only when the object is in the world - PhysBody.ApplyCollisionMask(); - - // Recompute any linkset parameters. - // When going from non-physical to physical, this re-enables the constraints that - // had been automatically disabled when the mass was set to zero. - // For compound based linksets, this enables and disables interactions of the children. - Linkset.Refresh(this); - - DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", - LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody, PhysShape); - } - - // "Making dynamic" means changing to and from static. - // When static, gravity does not effect the object and it is fixed in space. - // When dynamic, the object can fall and be pushed by others. - // This is independent of its 'solidness' which controls what passes through - // this object and what interacts with it. - private void MakeDynamic(bool makeStatic) - { - if (makeStatic) - { - // Become a Bullet 'static' object type - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - // Stop all movement - ZeroMotion(true); - - // Set various physical properties so other object interact properly - MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false); - BulletSimAPI.SetFriction2(PhysBody.ptr, matAttrib.friction); - BulletSimAPI.SetRestitution2(PhysBody.ptr, matAttrib.restitution); - - // Mass is zero which disables a bunch of physics stuff in Bullet - UpdatePhysicalMassProperties(0f, false); - // Set collision detection parameters - if (BSParam.CcdMotionThreshold > 0f) - { - BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, BSParam.CcdMotionThreshold); - BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, BSParam.CcdSweptSphereRadius); - } - - // The activation state is 'disabled' so Bullet will not try to act on it. - // BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_SIMULATION); - // Start it out sleeping and physical actions could wake it up. - BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ISLAND_SLEEPING); - - // This collides like a static object - PhysBody.collisionType = CollisionType.Static; - - // There can be special things needed for implementing linksets - Linkset.MakeStatic(this); - } - else - { - // Not a Bullet static object - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - - // Set various physical properties so other object interact properly - MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, true); - BulletSimAPI.SetFriction2(PhysBody.ptr, matAttrib.friction); - BulletSimAPI.SetRestitution2(PhysBody.ptr, matAttrib.restitution); - - // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 - // Since this can be called multiple times, only zero forces when becoming physical - // BulletSimAPI.ClearAllForces2(BSBody.ptr); - - // For good measure, make sure the transform is set through to the motion state - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - - // Center of mass is at the center of the object - // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation); - - // A dynamic object has mass - UpdatePhysicalMassProperties(RawMass, false); - - // Set collision detection parameters - if (BSParam.CcdMotionThreshold > 0f) - { - BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, BSParam.CcdMotionThreshold); - BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, BSParam.CcdSweptSphereRadius); - } - - // Various values for simulation limits - BulletSimAPI.SetDamping2(PhysBody.ptr, BSParam.LinearDamping, BSParam.AngularDamping); - BulletSimAPI.SetDeactivationTime2(PhysBody.ptr, BSParam.DeactivationTime); - BulletSimAPI.SetSleepingThresholds2(PhysBody.ptr, BSParam.LinearSleepingThreshold, BSParam.AngularSleepingThreshold); - BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, BSParam.ContactProcessingThreshold); - - // This collides like an object. - PhysBody.collisionType = CollisionType.Dynamic; - - // Force activation of the object so Bullet will act on it. - // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. - BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG); - - // There might be special things needed for implementing linksets. - Linkset.MakeDynamic(this); - } - } - - // "Making solid" means that other object will not pass through this object. - // To make transparent, we create a Bullet ghost object. - // Note: This expects to be called from the UpdatePhysicalParameters() routine as - // the functions after this one set up the state of a possibly newly created collision body. - private void MakeSolid(bool makeSolid) - { - CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(PhysBody.ptr); - if (makeSolid) - { - // Verify the previous code created the correct shape for this type of thing. - if ((bodyType & CollisionObjectTypes.CO_RIGID_BODY) == 0) - { - m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType); - } - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); - } - else - { - if ((bodyType & CollisionObjectTypes.CO_GHOST_OBJECT) == 0) - { - m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); - } - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); - - // Change collision info from a static object to a ghosty collision object - PhysBody.collisionType = CollisionType.VolumeDetect; - } - } - - // Enable physical actions. Bullet will keep sleeping non-moving physical objects so - // they need waking up when parameters are changed. - // Called in taint-time!! - private void ActivateIfPhysical(bool forceIt) - { - if (IsPhysical && PhysBody.HasPhysicalBody) - BulletSimAPI.Activate2(PhysBody.ptr, forceIt); - } - - // Turn on or off the flag controlling whether collision events are returned to the simulator. - private void EnableCollisions(bool wantsCollisionEvents) - { - if (wantsCollisionEvents) - { - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - } - else - { - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - } - } - - // prims don't fly - public override bool Flying { - get { return _flying; } - set { - _flying = value; - } - } - 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 == PhysicsScene.SimulationStep); } - set { _isColliding = value; } - } - public override bool CollidingGround { - get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } - set { _collidingGround = value; } - } - public override bool CollidingObj { - get { return _collidingObj; } - set { _collidingObj = value; } - } - public bool IsPhantom { - get { - // SceneObjectPart removes phantom objects from the physics scene - // so, although we could implement touching and such, we never - // are invoked as a phantom object - return false; - } - } - public override bool FloatOnWater { - set { - _floatOnWater = value; - PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate() - { - if (_floatOnWater) - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); - else - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); - }); - } - } - public override OMV.Vector3 RotationalVelocity { - get { - return _rotationalVelocity; - } - set { - _rotationalVelocity = value; - // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); - PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() - { - DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); - ForceRotationalVelocity = _rotationalVelocity; - }); - } - } - public override OMV.Vector3 ForceRotationalVelocity { - get { - return _rotationalVelocity; - } - set { - _rotationalVelocity = value; - if (PhysBody.HasPhysicalBody) - { - BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity); - ActivateIfPhysical(false); - } - } - } - public override bool Kinematic { - get { return _kinematic; } - set { _kinematic = value; - // m_log.DebugFormat("{0}: Kinematic={1}", LogHeader, _kinematic); - } - } - public override float Buoyancy { - get { return _buoyancy; } - set { - _buoyancy = value; - PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() - { - ForceBuoyancy = _buoyancy; - }); - } - } - public override float ForceBuoyancy { - get { return _buoyancy; } - set { - _buoyancy = value; - // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - // Force the recalculation of the various inertia,etc variables in the object - UpdatePhysicalMassProperties(_mass, true); - ActivateIfPhysical(false); - } - } - - // Used for MoveTo - public override OMV.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 OMV.Quaternion APIDTarget { set { return; } } - public override bool APIDActive { set { return; } } - public override float APIDStrength { set { return; } } - public override float APIDDamping { set { return; } } - - public override void AddForce(OMV.Vector3 force, bool pushforce) { - // Since this force is being applied in only one step, make this a force per second. - OMV.Vector3 addForce = force / PhysicsScene.LastTimeStep; - AddForce(addForce, pushforce, false); - } - // Applying a force just adds this to the total force on the object. - // This added force will only last the next simulation tick. - public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { - // for an object, doesn't matter if force is a pushforce or not - if (force.IsFinite()) - { - float magnitude = force.Length(); - if (magnitude > 20000f) - { - // Force has a limit - force = force / magnitude * 20000f; - } - - OMV.Vector3 addForce = force; - DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce); - - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() - { - // Bullet adds this central force to the total force for this tick - DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce); - if (PhysBody.HasPhysicalBody) - { - BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, addForce); - ActivateIfPhysical(false); - } - }); - } - else - { - m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); - return; - } - } - - public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { - AddAngularForce(force, pushforce, false); - } - public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) - { - if (force.IsFinite()) - { - OMV.Vector3 angForce = force; - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate() - { - if (PhysBody.HasPhysicalBody) - { - BulletSimAPI.ApplyTorque2(PhysBody.ptr, angForce); - ActivateIfPhysical(false); - } - }); - } - else - { - m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); - return; - } - } - - // A torque impulse. - // ApplyTorqueImpulse adds torque directly to the angularVelocity. - // AddAngularForce accumulates the force and applied it to the angular velocity all at once. - // Computed as: angularVelocity += impulse * inertia; - public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) - { - OMV.Vector3 applyImpulse = impulse; - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() - { - if (PhysBody.HasPhysicalBody) - { - BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse); - ActivateIfPhysical(false); - } - }); - } - - public override void SetMomentum(OMV.Vector3 momentum) { - // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); - } - #region Mass Calculation - - private float CalculateMass() - { - float volume = _size.X * _size.Y * _size.Z; // default - float tmp; - - float returnMass = 0; - float hollowAmount = (float)BaseShape.ProfileHollow * 2.0e-5f; - float hollowVolume = hollowAmount * hollowAmount; - - switch (BaseShape.ProfileShape) - { - case ProfileShape.Square: - // default box - - if (BaseShape.PathCurve == (byte)Extrusion.Straight) - { - if (hollowAmount > 0.0) - { - switch (BaseShape.HollowShape) - { - case HollowShape.Square: - case HollowShape.Same: - break; - - case HollowShape.Circle: - - hollowVolume *= 0.78539816339f; - break; - - case HollowShape.Triangle: - - hollowVolume *= (0.5f * .5f); - break; - - default: - hollowVolume = 0; - break; - } - volume *= (1.0f - hollowVolume); - } - } - - else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) - { - //a tube - - volume *= 0.78539816339e-2f * (float)(200 - BaseShape.PathScaleX); - tmp= 1.0f -2.0e-2f * (float)(200 - BaseShape.PathScaleY); - volume -= volume*tmp*tmp; - - if (hollowAmount > 0.0) - { - hollowVolume *= hollowAmount; - - switch (BaseShape.HollowShape) - { - case HollowShape.Square: - case HollowShape.Same: - break; - - case HollowShape.Circle: - hollowVolume *= 0.78539816339f;; - break; - - case HollowShape.Triangle: - hollowVolume *= 0.5f * 0.5f; - break; - default: - hollowVolume = 0; - break; - } - volume *= (1.0f - hollowVolume); - } - } - - break; - - case ProfileShape.Circle: - - if (BaseShape.PathCurve == (byte)Extrusion.Straight) - { - volume *= 0.78539816339f; // elipse base - - if (hollowAmount > 0.0) - { - switch (BaseShape.HollowShape) - { - case HollowShape.Same: - case HollowShape.Circle: - break; - - case HollowShape.Square: - hollowVolume *= 0.5f * 2.5984480504799f; - break; - - case HollowShape.Triangle: - hollowVolume *= .5f * 1.27323954473516f; - break; - - default: - hollowVolume = 0; - break; - } - volume *= (1.0f - hollowVolume); - } - } - - else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) - { - volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - BaseShape.PathScaleX); - tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY); - volume *= (1.0f - tmp * tmp); - - if (hollowAmount > 0.0) - { - - // calculate the hollow volume by it's shape compared to the prim shape - hollowVolume *= hollowAmount; - - switch (BaseShape.HollowShape) - { - case HollowShape.Same: - case HollowShape.Circle: - break; - - case HollowShape.Square: - hollowVolume *= 0.5f * 2.5984480504799f; - break; - - case HollowShape.Triangle: - hollowVolume *= .5f * 1.27323954473516f; - break; - - default: - hollowVolume = 0; - break; - } - volume *= (1.0f - hollowVolume); - } - } - break; - - case ProfileShape.HalfCircle: - if (BaseShape.PathCurve == (byte)Extrusion.Curve1) - { - volume *= 0.52359877559829887307710723054658f; - } - break; - - case ProfileShape.EquilateralTriangle: - - if (BaseShape.PathCurve == (byte)Extrusion.Straight) - { - volume *= 0.32475953f; - - if (hollowAmount > 0.0) - { - - // calculate the hollow volume by it's shape compared to the prim shape - switch (BaseShape.HollowShape) - { - case HollowShape.Same: - case HollowShape.Triangle: - hollowVolume *= .25f; - break; - - case HollowShape.Square: - hollowVolume *= 0.499849f * 3.07920140172638f; - break; - - case HollowShape.Circle: - // Hollow shape is a perfect cyllinder in respect to the cube's scale - // Cyllinder hollow volume calculation - - hollowVolume *= 0.1963495f * 3.07920140172638f; - break; - - default: - hollowVolume = 0; - break; - } - volume *= (1.0f - hollowVolume); - } - } - else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) - { - volume *= 0.32475953f; - volume *= 0.01f * (float)(200 - BaseShape.PathScaleX); - tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY); - volume *= (1.0f - tmp * tmp); - - if (hollowAmount > 0.0) - { - - hollowVolume *= hollowAmount; - - switch (BaseShape.HollowShape) - { - case HollowShape.Same: - case HollowShape.Triangle: - hollowVolume *= .25f; - break; - - case HollowShape.Square: - hollowVolume *= 0.499849f * 3.07920140172638f; - break; - - case HollowShape.Circle: - - hollowVolume *= 0.1963495f * 3.07920140172638f; - break; - - default: - hollowVolume = 0; - break; - } - volume *= (1.0f - hollowVolume); - } - } - break; - - default: - break; - } - - - - float taperX1; - float taperY1; - float taperX; - float taperY; - float pathBegin; - float pathEnd; - float profileBegin; - float profileEnd; - - if (BaseShape.PathCurve == (byte)Extrusion.Straight || BaseShape.PathCurve == (byte)Extrusion.Flexible) - { - taperX1 = BaseShape.PathScaleX * 0.01f; - if (taperX1 > 1.0f) - taperX1 = 2.0f - taperX1; - taperX = 1.0f - taperX1; - - taperY1 = BaseShape.PathScaleY * 0.01f; - if (taperY1 > 1.0f) - taperY1 = 2.0f - taperY1; - taperY = 1.0f - taperY1; - } - else - { - taperX = BaseShape.PathTaperX * 0.01f; - if (taperX < 0.0f) - taperX = -taperX; - taperX1 = 1.0f - taperX; - - taperY = BaseShape.PathTaperY * 0.01f; - if (taperY < 0.0f) - taperY = -taperY; - taperY1 = 1.0f - taperY; - - } - - - volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); - - pathBegin = (float)BaseShape.PathBegin * 2.0e-5f; - pathEnd = 1.0f - (float)BaseShape.PathEnd * 2.0e-5f; - volume *= (pathEnd - pathBegin); - - // this is crude aproximation - profileBegin = (float)BaseShape.ProfileBegin * 2.0e-5f; - profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f; - volume *= (profileEnd - profileBegin); - - returnMass = _density * volume; - - /* Comment out code that computes the mass of the linkset. That is done in the Linkset class. - if (IsRootOfLinkset) - { - foreach (BSPrim prim in _childrenPrims) - { - returnMass += prim.CalculateMass(); - } - } - */ - - returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass); - - return returnMass; - }// end CalculateMass - #endregion Mass Calculation - - // Rebuild the geometry and object. - // This is called when the shape changes so we need to recreate the mesh/hull. - // Called at taint-time!!! - public void CreateGeomAndObject(bool forceRebuild) - { - // If this prim is part of a linkset, we must remove and restore the physical - // links if the body is rebuilt. - bool needToRestoreLinkset = false; - bool needToRestoreVehicle = false; - - // Create the correct physical representation for this type of object. - // Updates PhysBody and PhysShape with the new information. - // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. - PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody) - { - // Called if the current prim body is about to be destroyed. - // Remove all the physical dependencies on the old body. - // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...) - needToRestoreLinkset = Linkset.RemoveBodyDependencies(this); - needToRestoreVehicle = _vehicle.RemoveBodyDependencies(this); - }); - - if (needToRestoreLinkset) - { - // If physical body dependencies were removed, restore them - Linkset.RestoreBodyDependencies(this); - } - if (needToRestoreVehicle) - { - // If physical body dependencies were removed, restore them - _vehicle.RestoreBodyDependencies(this); - } - - // Make sure the properties are set on the new object - UpdatePhysicalParameters(); - return; - } - - // The physics engine says that properties have updated. Update same and inform - // the world that things have changed. - // TODO: do we really need to check for changed? Maybe just copy values and call RequestPhysicsterseUpdate() - enum UpdatedProperties { - Position = 1 << 0, - Rotation = 1 << 1, - Velocity = 1 << 2, - Acceleration = 1 << 3, - RotationalVel = 1 << 4 - } - - const float ROTATION_TOLERANCE = 0.01f; - const float VELOCITY_TOLERANCE = 0.001f; - const float POSITION_TOLERANCE = 0.05f; - const float ACCELERATION_TOLERANCE = 0.01f; - const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; - - public override void UpdateProperties(EntityProperties entprop) - { - // Updates only for individual prims and for the root object of a linkset. - if (Linkset.IsRoot(this)) - { - // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet - // TODO: handle physics introduced by Bullet with computed vehicle physics. - if (_vehicle.IsActive) - { - entprop.RotationalVelocity = OMV.Vector3.Zero; - } - - // Assign directly to the local variables so the normal set action does not happen - _position = entprop.Position; - _orientation = entprop.Rotation; - _velocity = entprop.Velocity; - _acceleration = entprop.Acceleration; - _rotationalVelocity = entprop.RotationalVelocity; - - // The sanity check can change the velocity and/or position. - if (IsPhysical && PositionSanityCheck(true)) - { - entprop.Position = _position; - entprop.Velocity = _velocity; - } - - OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG - DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", - LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); - - // remember the current and last set values - LastEntityProperties = CurrentEntityProperties; - CurrentEntityProperties = entprop; - - base.RequestPhysicsterseUpdate(); - } - /* - else - { - // For debugging, report the movement of children - DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", - LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, - entprop.Acceleration, entprop.RotationalVelocity); - } - */ - - // The linkset implimentation might want to know about this. - Linkset.UpdateProperties(this, true); - } -} -} diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSNPlugin/BSScene.cs deleted file mode 100644 index 1a7c34b..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BSScene.cs +++ /dev/null @@ -1,957 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading; -using OpenSim.Framework; -using OpenSim.Region.Framework; -using OpenSim.Region.CoreModules; -using Logging = OpenSim.Region.CoreModules.Framework.Statistics.Logging; -using OpenSim.Region.Physics.Manager; -using Nini.Config; -using log4net; -using OpenMetaverse; - -// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) -// Based on material, set density and friction -// More efficient memory usage when passing hull information from BSPrim to BulletSim -// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect -// Implement LockAngularMotion -// Add PID movement operations. What does ScenePresence.MoveToTarget do? -// Check terrain size. 128 or 127? -// Raycast -// -namespace OpenSim.Region.Physics.BulletSNPlugin -{ -public sealed class BSScene : PhysicsScene, IPhysicsParameters -{ - private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - private static readonly string LogHeader = "[BULLETS SCENE]"; - - // The name of the region we're working for. - public string RegionName { get; private set; } - - public string BulletSimVersion = "?"; - - public Dictionary PhysObjects; - public BSShapeCollection Shapes; - - // Keeping track of the objects with collisions so we can report begin and end of a collision - public HashSet ObjectsWithCollisions = new HashSet(); - public HashSet ObjectsWithNoMoreCollisions = new HashSet(); - // Keep track of all the avatars so we can send them a collision event - // every tick so OpenSim will update its animation. - private HashSet m_avatars = new HashSet(); - - // let my minuions use my logger - public ILog Logger { get { return m_log; } } - - public IMesher mesher; - public uint WorldID { get; private set; } - public BulletWorld World { get; private set; } - - // All the constraints that have been allocated in this instance. - public BSConstraintCollection Constraints { get; private set; } - - // Simulation parameters - internal int m_maxSubSteps; - internal float m_fixedTimeStep; - internal long m_simulationStep = 0; - public long SimulationStep { get { return m_simulationStep; } } - internal int m_taintsToProcessPerStep; - internal float LastTimeStep { get; private set; } - - // Physical objects can register for prestep or poststep events - public delegate void PreStepAction(float timeStep); - public delegate void PostStepAction(float timeStep); - public event PreStepAction BeforeStep; - public event PreStepAction AfterStep; - - // A value of the time now so all the collision and update routines do not have to get their own - // Set to 'now' just before all the prims and actors are called for collisions and updates - public int SimulationNowTime { get; private set; } - - // True if initialized and ready to do simulation steps - private bool m_initialized = false; - - // Flag which is true when processing taints. - // Not guaranteed to be correct all the time (don't depend on this) but good for debugging. - public bool InTaintTime { get; private set; } - - // Pinned memory used to pass step information between managed and unmanaged - internal int m_maxCollisionsPerFrame; - private List m_collisionArray; - //private GCHandle m_collisionArrayPinnedHandle; - - internal int m_maxUpdatesPerFrame; - private List m_updateArray; - //private GCHandle m_updateArrayPinnedHandle; - - - public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero - public const uint GROUNDPLANE_ID = 1; - public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here - - public float SimpleWaterLevel { get; set; } - public BSTerrainManager TerrainManager { get; private set; } - - public ConfigurationParameters Params - { - get { return UnmanagedParams[0]; } - } - public Vector3 DefaultGravity - { - get { return new Vector3(0f, 0f, Params.gravity); } - } - // Just the Z value of the gravity - public float DefaultGravityZ - { - get { return Params.gravity; } - } - - // When functions in the unmanaged code must be called, it is only - // done at a known time just before the simulation step. The taint - // system saves all these function calls and executes them in - // order before the simulation. - public delegate void TaintCallback(); - private struct TaintCallbackEntry - { - public String ident; - public TaintCallback callback; - public TaintCallbackEntry(string i, TaintCallback c) - { - ident = i; - callback = c; - } - } - private Object _taintLock = new Object(); // lock for using the next object - private List _taintOperations; - private Dictionary _postTaintOperations; - private List _postStepOperations; - - // A pointer to an instance if this structure is passed to the C++ code - // Used to pass basic configuration values to the unmanaged code. - internal ConfigurationParameters[] UnmanagedParams; - //GCHandle m_paramsHandle; - - // Handle to the callback used by the unmanaged code to call into the managed code. - // Used for debug logging. - // Need to store the handle in a persistant variable so it won't be freed. - private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; - - // Sometimes you just have to log everything. - public Logging.LogWriter PhysicsLogging; - private bool m_physicsLoggingEnabled; - private string m_physicsLoggingDir; - private string m_physicsLoggingPrefix; - private int m_physicsLoggingFileMinutes; - private bool m_physicsLoggingDoFlush; - // 'true' of the vehicle code is to log lots of details - public bool VehicleLoggingEnabled { get; private set; } - public bool VehiclePhysicalLoggingEnabled { get; private set; } - - #region Construction and Initialization - public BSScene(string identifier) - { - m_initialized = false; - // we are passed the name of the region we're working for. - RegionName = identifier; - } - - public override void Initialise(IMesher meshmerizer, IConfigSource config) - { - mesher = meshmerizer; - _taintOperations = new List(); - _postTaintOperations = new Dictionary(); - _postStepOperations = new List(); - PhysObjects = new Dictionary(); - Shapes = new BSShapeCollection(this); - - // Allocate pinned memory to pass parameters. - UnmanagedParams = new ConfigurationParameters[1]; - //m_paramsHandle = GCHandle.Alloc(UnmanagedParams, GCHandleType.Pinned); - - // Set default values for physics parameters plus any overrides from the ini file - GetInitialParameterValues(config); - - // allocate more pinned memory close to the above in an attempt to get the memory all together - m_collisionArray = new List(); - //m_collisionArrayPinnedHandle = GCHandle.Alloc(m_collisionArray, GCHandleType.Pinned); - m_updateArray = new List(); - //m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned); - - // Enable very detailed logging. - // By creating an empty logger when not logging, the log message invocation code - // can be left in and every call doesn't have to check for null. - if (m_physicsLoggingEnabled) - { - PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes); - PhysicsLogging.ErrorLogger = m_log; // for DEBUG. Let's the logger output error messages. - } - else - { - PhysicsLogging = new Logging.LogWriter(); - } - - // If Debug logging level, enable logging from the unmanaged code - m_DebugLogCallbackHandle = null; - if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) - { - m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); - if (PhysicsLogging.Enabled) - // The handle is saved in a variable to make sure it doesn't get freed after this call - m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog); - else - m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); - } - - // Get the version of the DLL - // TODO: this doesn't work yet. Something wrong with marshaling the returned string. - // BulletSimVersion = BulletSimAPI.GetVersion(); - // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion); - - // The bounding box for the simulated world. The origin is 0,0,0 unless we're - // a child in a mega-region. - // Bullet actually doesn't care about the extents of the simulated - // area. It tracks active objects no matter where they are. - Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); - - // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); - - World = new BulletWorld(0, this, BulletSimAPI.Initialize2(worldExtent, UnmanagedParams, - m_maxCollisionsPerFrame, ref m_collisionArray, - m_maxUpdatesPerFrame,ref m_updateArray, - m_DebugLogCallbackHandle)); - - Constraints = new BSConstraintCollection(World); - - TerrainManager = new BSTerrainManager(this); - TerrainManager.CreateInitialGroundPlaneAndTerrain(); - - m_log.WarnFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)BSParam.LinksetImplementation); - - InTaintTime = false; - m_initialized = true; - } - - // All default parameter values are set here. There should be no values set in the - // variable definitions. - private void GetInitialParameterValues(IConfigSource config) - { - ConfigurationParameters parms = new ConfigurationParameters(); - UnmanagedParams[0] = parms; - - BSParam.SetParameterDefaultValues(this); - - if (config != null) - { - // If there are specifications in the ini file, use those values - IConfig pConfig = config.Configs["BulletSim"]; - if (pConfig != null) - { - BSParam.SetParameterConfigurationValues(this, pConfig); - - // Very detailed logging for physics debugging - m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); - m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", "."); - m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-"); - m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); - m_physicsLoggingDoFlush = pConfig.GetBoolean("PhysicsLoggingDoFlush", false); - // Very detailed logging for vehicle debugging - VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); - VehiclePhysicalLoggingEnabled = pConfig.GetBoolean("VehiclePhysicalLoggingEnabled", false); - - // Do any replacements in the parameters - m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName); - } - - // The material characteristics. - BSMaterials.InitializeFromDefaults(Params); - if (pConfig != null) - { - // Let the user add new and interesting material property values. - BSMaterials.InitializefromParameters(pConfig); - } - } - } - - // A helper function that handles a true/false parameter and returns the proper float number encoding - float ParamBoolean(IConfig config, string parmName, float deflt) - { - float ret = deflt; - if (config.Contains(parmName)) - { - ret = ConfigurationParameters.numericFalse; - if (config.GetBoolean(parmName, false)) - { - ret = ConfigurationParameters.numericTrue; - } - } - return ret; - } - - // Called directly from unmanaged code so don't do much - private void BulletLogger(string msg) - { - m_log.Debug("[BULLETS UNMANAGED]:" + msg); - } - - // Called directly from unmanaged code so don't do much - private void BulletLoggerPhysLog(string msg) - { - DetailLog("[BULLETS UNMANAGED]:" + msg); - } - - public override void Dispose() - { - // m_log.DebugFormat("{0}: Dispose()", LogHeader); - - // make sure no stepping happens while we're deleting stuff - m_initialized = false; - - foreach (KeyValuePair kvp in PhysObjects) - { - kvp.Value.Destroy(); - } - PhysObjects.Clear(); - - // Now that the prims are all cleaned up, there should be no constraints left - if (Constraints != null) - { - Constraints.Dispose(); - Constraints = null; - } - - if (Shapes != null) - { - Shapes.Dispose(); - Shapes = null; - } - - if (TerrainManager != null) - { - TerrainManager.ReleaseGroundPlaneAndTerrain(); - TerrainManager.Dispose(); - TerrainManager = null; - } - - // Anything left in the unmanaged code should be cleaned out - BulletSimAPI.Shutdown2(World.ptr); - - // Not logging any more - PhysicsLogging.Close(); - } - #endregion // Construction and Initialization - - #region Prim and Avatar addition and removal - - 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); - - if (!m_initialized) return null; - - BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying); - lock (PhysObjects) PhysObjects.Add(localID, actor); - - // TODO: Remove kludge someday. - // We must generate a collision for avatars whether they collide or not. - // This is required by OpenSim to update avatar animations, etc. - lock (m_avatars) m_avatars.Add(actor); - - return actor; - } - - public override void RemoveAvatar(PhysicsActor actor) - { - // m_log.DebugFormat("{0}: RemoveAvatar", LogHeader); - - if (!m_initialized) return; - - BSCharacter bsactor = actor as BSCharacter; - if (bsactor != null) - { - try - { - lock (PhysObjects) PhysObjects.Remove(actor.LocalID); - // Remove kludge someday - lock (m_avatars) m_avatars.Remove(bsactor); - } - catch (Exception e) - { - m_log.WarnFormat("{0}: Attempt to remove avatar that is not in physics scene: {1}", LogHeader, e); - } - bsactor.Destroy(); - // bsactor.dispose(); - } - } - - public override void RemovePrim(PhysicsActor prim) - { - if (!m_initialized) return; - - BSPrim bsprim = prim as BSPrim; - if (bsprim != null) - { - DetailLog("{0},RemovePrim,call", bsprim.LocalID); - // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); - try - { - lock (PhysObjects) PhysObjects.Remove(bsprim.LocalID); - } - catch (Exception e) - { - m_log.ErrorFormat("{0}: Attempt to remove prim that is not in physics scene: {1}", LogHeader, e); - } - bsprim.Destroy(); - // bsprim.dispose(); - } - else - { - m_log.ErrorFormat("{0}: Attempt to remove prim that is not a BSPrim type.", LogHeader); - } - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, - Vector3 size, Quaternion rotation, bool isPhysical, uint localID) - { - // m_log.DebugFormat("{0}: AddPrimShape2: {1}", LogHeader, primName); - - if (!m_initialized) return null; - - DetailLog("{0},AddPrimShape,call", localID); - - BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); - lock (PhysObjects) PhysObjects.Add(localID, prim); - return prim; - } - - // This is a call from the simulator saying that some physical property has been updated. - // The BulletSim driver senses the changing of relevant properties so this taint - // information call is not needed. - public override void AddPhysicsActorTaint(PhysicsActor prim) { } - - #endregion // Prim and Avatar addition and removal - - #region Simulation - // Simulate one timestep - public override float Simulate(float timeStep) - { - // prevent simulation until we've been initialized - if (!m_initialized) return 5.0f; - - LastTimeStep = timeStep; - - int updatedEntityCount = 0; - //Object updatedEntitiesPtr; - int collidersCount = 0; - //Object collidersPtr; - - int beforeTime = 0; - int simTime = 0; - - // update the prim states while we know the physics engine is not busy - int numTaints = _taintOperations.Count; - - InTaintTime = true; // Only used for debugging so locking is not necessary. - - ProcessTaints(); - - // Some of the physical objects requre individual, pre-step calls - TriggerPreStepEvent(timeStep); - - // the prestep actions might have added taints - ProcessTaints(); - - InTaintTime = false; // Only used for debugging so locking is not necessary. - - // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world. - // Only enable this in a limited test world with few objects. - // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG - - // step the physical world one interval - m_simulationStep++; - int numSubSteps = 0; - - try - { - if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); - - numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, - out updatedEntityCount, out m_updateArray, out collidersCount, out m_collisionArray); - - if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); - DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}", - DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, - updatedEntityCount, collidersCount, ObjectsWithCollisions.Count); - } - catch (Exception e) - { - m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}", - LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e); - DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}", - DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount); - updatedEntityCount = 0; - collidersCount = 0; - } - - // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in. - - // Get a value for 'now' so all the collision and update routines don't have to get their own. - SimulationNowTime = Util.EnvironmentTickCount(); - - // If there were collisions, process them by sending the event to the prim. - // Collisions must be processed before updates. - if (collidersCount > 0) - { - for (int ii = 0; ii < collidersCount; ii++) - { - uint cA = m_collisionArray[ii].aID; - uint cB = m_collisionArray[ii].bID; - Vector3 point = new Vector3(m_collisionArray[ii].point.X, m_collisionArray[ii].point.Y, - m_collisionArray[ii].point.Z); - Vector3 normal = new Vector3(m_collisionArray[ii].normal.X, m_collisionArray[ii].normal.Y, - m_collisionArray[ii].normal.Z); - SendCollision(cA, cB, point, normal, 0.01f); - SendCollision(cB, cA, point, -normal, 0.01f); - } - } - - // The above SendCollision's batch up the collisions on the objects. - // Now push the collisions into the simulator. - if (ObjectsWithCollisions.Count > 0) - { - foreach (BSPhysObject bsp in ObjectsWithCollisions) - if (!bsp.SendCollisions()) - { - // If the object is done colliding, see that it's removed from the colliding list - ObjectsWithNoMoreCollisions.Add(bsp); - } - } - - // This is a kludge to get avatar movement updates. - // The simulator expects collisions for avatars even if there are have been no collisions. - // The event updates avatar animations and stuff. - // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. - foreach (BSPhysObject bsp in m_avatars) - if (!ObjectsWithCollisions.Contains(bsp)) // don't call avatars twice - bsp.SendCollisions(); - - // Objects that are done colliding are removed from the ObjectsWithCollisions list. - // Not done above because it is inside an iteration of ObjectWithCollisions. - // This complex collision processing is required to create an empty collision - // event call after all collisions have happened on an object. This enables - // the simulator to generate the 'collision end' event. - if (ObjectsWithNoMoreCollisions.Count > 0) - { - foreach (BSPhysObject po in ObjectsWithNoMoreCollisions) - ObjectsWithCollisions.Remove(po); - ObjectsWithNoMoreCollisions.Clear(); - } - // Done with collisions. - - // If any of the objects had updated properties, tell the object it has been changed by the physics engine - if (updatedEntityCount > 0) - { - for (int ii = 0; ii < updatedEntityCount; ii++) - { - - BulletXNA.EntityProperties entprop = m_updateArray[ii]; - BSPhysObject pobj; - if (PhysObjects.TryGetValue(entprop.ID, out pobj)) - { - EntityProperties prop = new EntityProperties() - { - Acceleration = new Vector3(entprop.Acceleration.X, entprop.Acceleration.Y, entprop.Acceleration.Z), - ID = entprop.ID, - Position = new Vector3(entprop.Position.X,entprop.Position.Y,entprop.Position.Z), - Rotation = new Quaternion(entprop.Rotation.X,entprop.Rotation.Y,entprop.Rotation.Z,entprop.Rotation.W), - RotationalVelocity = new Vector3(entprop.AngularVelocity.X,entprop.AngularVelocity.Y,entprop.AngularVelocity.Z), - Velocity = new Vector3(entprop.Velocity.X,entprop.Velocity.Y,entprop.Velocity.Z) - }; - //m_log.Debug(pobj.Name + ":" + prop.ToString() + "\n"); - pobj.UpdateProperties(prop); - } - } - } - - TriggerPostStepEvent(timeStep); - - // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world. - // Only enable this in a limited test world with few objects. - // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG - - // The physics engine returns the number of milliseconds it simulated this call. - // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. - // Multiply by 55 to give a nominal frame rate of 55. - return (float)numSubSteps * m_fixedTimeStep * 1000f * 55f; - } - - // Something has collided - private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penetration) - { - if (localID <= TerrainManager.HighestTerrainID) - { - return; // don't send collisions to the terrain - } - - BSPhysObject collider; - if (!PhysObjects.TryGetValue(localID, out collider)) - { - // If the object that is colliding cannot be found, just ignore the collision. - DetailLog("{0},BSScene.SendCollision,colliderNotInObjectList,id={1},with={2}", DetailLogZero, localID, collidingWith); - return; - } - - // The terrain is not in the physical object list so 'collidee' can be null when Collide() is called. - BSPhysObject collidee = null; - PhysObjects.TryGetValue(collidingWith, out collidee); - - // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); - - if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration)) - { - // If a collision was posted, remember to send it to the simulator - ObjectsWithCollisions.Add(collider); - } - - return; - } - - #endregion // Simulation - - public override void GetResults() { } - - #region Terrain - - public override void SetTerrain(float[] heightMap) { - TerrainManager.SetTerrain(heightMap); - } - - public override void SetWaterLevel(float baseheight) - { - SimpleWaterLevel = baseheight; - } - - public override void DeleteTerrain() - { - // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader); - } - - // Although no one seems to check this, I do support combining. - public override bool SupportsCombining() - { - return TerrainManager.SupportsCombining(); - } - // This call says I am a child to region zero in a mega-region. 'pScene' is that - // of region zero, 'offset' is my offset from regions zero's origin, and - // 'extents' is the largest XY that is handled in my region. - public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) - { - TerrainManager.Combine(pScene, offset, extents); - } - - // Unhook all the combining that I know about. - public override void UnCombine(PhysicsScene pScene) - { - TerrainManager.UnCombine(pScene); - } - - #endregion // Terrain - - public override Dictionary GetTopColliders() - { - return new Dictionary(); - } - - public override bool IsThreaded { get { return false; } } - - #region Taints - // The simulation execution order is: - // Simulate() - // DoOneTimeTaints - // TriggerPreStepEvent - // DoOneTimeTaints - // Step() - // ProcessAndForwardCollisions - // ProcessAndForwardPropertyUpdates - // TriggerPostStepEvent - - // Calls to the PhysicsActors can't directly call into the physics engine - // because it might be busy. 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(String ident, TaintCallback callback) - { - if (!m_initialized) return; - - lock (_taintLock) - { - _taintOperations.Add(new TaintCallbackEntry(ident, callback)); - } - - return; - } - - // Sometimes a potentially tainted operation can be used in and out of taint time. - // This routine executes the command immediately if in taint-time otherwise it is queued. - public void TaintedObject(bool inTaintTime, string ident, TaintCallback callback) - { - if (inTaintTime) - callback(); - else - TaintedObject(ident, callback); - } - - private void TriggerPreStepEvent(float timeStep) - { - PreStepAction actions = BeforeStep; - if (actions != null) - actions(timeStep); - - } - - private void TriggerPostStepEvent(float timeStep) - { - PreStepAction actions = AfterStep; - if (actions != null) - actions(timeStep); - - } - - // 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() - { - ProcessRegularTaints(); - ProcessPostTaintTaints(); - } - - private void ProcessRegularTaints() - { - if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process - { - // swizzle a new list into the list location so we can process what's there - List oldList; - lock (_taintLock) - { - oldList = _taintOperations; - _taintOperations = new List(); - } - - foreach (TaintCallbackEntry tcbe in oldList) - { - try - { - DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG - tcbe.callback(); - } - catch (Exception e) - { - m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e); - } - } - oldList.Clear(); - } - } - - // Schedule an update to happen after all the regular taints are processed. - // Note that new requests for the same operation ("ident") for the same object ("ID") - // will replace any previous operation by the same object. - public void PostTaintObject(String ident, uint ID, TaintCallback callback) - { - string uniqueIdent = ident + "-" + ID.ToString(); - lock (_taintLock) - { - _postTaintOperations[uniqueIdent] = new TaintCallbackEntry(uniqueIdent, callback); - } - - return; - } - - // Taints that happen after the normal taint processing but before the simulation step. - private void ProcessPostTaintTaints() - { - if (_postTaintOperations.Count > 0) - { - Dictionary oldList; - lock (_taintLock) - { - oldList = _postTaintOperations; - _postTaintOperations = new Dictionary(); - } - - foreach (KeyValuePair kvp in oldList) - { - try - { - DetailLog("{0},BSScene.ProcessPostTaintTaints,doTaint,id={1}", DetailLogZero, kvp.Key); // DEBUG DEBUG DEBUG - kvp.Value.callback(); - } - catch (Exception e) - { - m_log.ErrorFormat("{0}: ProcessPostTaintTaints: {1}: Exception: {2}", LogHeader, kvp.Key, e); - } - } - oldList.Clear(); - } - } - - // Only used for debugging. Does not change state of anything so locking is not necessary. - public bool AssertInTaintTime(string whereFrom) - { - if (!InTaintTime) - { - DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom); - m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom); - Util.PrintCallStack(DetailLog); - } - return InTaintTime; - } - - #endregion // Taints - - #region INI and command line parameter processing - - #region IPhysicsParameters - // Get the list of parameters this physics engine supports - public PhysParameterEntry[] GetParameterList() - { - BSParam.BuildParameterTable(); - return BSParam.SettableParameters; - } - - // Set parameter on a specific or all instances. - // Return 'false' if not able to set the parameter. - // Setting the value in the m_params block will change the value the physics engine - // will use the next time since it's pinned and shared memory. - // Some of the values require calling into the physics engine to get the new - // value activated ('terrainFriction' for instance). - public bool SetPhysicsParameter(string parm, float val, uint localID) - { - bool ret = false; - BSParam.ParameterDefn theParam; - if (BSParam.TryGetParameter(parm, out theParam)) - { - theParam.setter(this, parm, localID, val); - ret = true; - } - return ret; - } - - // update all the localIDs specified - // If the local ID is APPLY_TO_NONE, just change the default value - // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs - // If the localID is a specific object, apply the parameter change to only that object - internal delegate void AssignVal(float x); - internal void UpdateParameterObject(AssignVal setDefault, string parm, uint localID, float val) - { - List objectIDs = new List(); - switch (localID) - { - case PhysParameterEntry.APPLY_TO_NONE: - setDefault(val); // setting only the default value - // This will cause a call into the physical world if some operation is specified (SetOnObject). - objectIDs.Add(TERRAIN_ID); - TaintedUpdateParameter(parm, objectIDs, val); - break; - case PhysParameterEntry.APPLY_TO_ALL: - setDefault(val); // setting ALL also sets the default value - lock (PhysObjects) objectIDs = new List(PhysObjects.Keys); - TaintedUpdateParameter(parm, objectIDs, val); - break; - default: - // setting only one localID - objectIDs.Add(localID); - TaintedUpdateParameter(parm, objectIDs, val); - break; - } - } - - // schedule the actual updating of the paramter to when the phys engine is not busy - private void TaintedUpdateParameter(string parm, List lIDs, float val) - { - float xval = val; - List xlIDs = lIDs; - string xparm = parm; - TaintedObject("BSScene.UpdateParameterSet", delegate() { - BSParam.ParameterDefn thisParam; - if (BSParam.TryGetParameter(xparm, out thisParam)) - { - if (thisParam.onObject != null) - { - foreach (uint lID in xlIDs) - { - BSPhysObject theObject = null; - PhysObjects.TryGetValue(lID, out theObject); - thisParam.onObject(this, theObject, xval); - } - } - } - }); - } - - // Get parameter. - // Return 'false' if not able to get the parameter. - public bool GetPhysicsParameter(string parm, out float value) - { - float val = 0f; - bool ret = false; - BSParam.ParameterDefn theParam; - if (BSParam.TryGetParameter(parm, out theParam)) - { - val = theParam.getter(this); - ret = true; - } - value = val; - return ret; - } - - #endregion IPhysicsParameters - - #endregion Runtime settable parameters - - // Invoke the detailed logger and output something if it's enabled. - public void DetailLog(string msg, params Object[] args) - { - PhysicsLogging.Write(msg, args); - // Add the Flush() if debugging crashes. Gets all the messages written out. - if (m_physicsLoggingDoFlush) PhysicsLogging.Flush(); - } - // Used to fill in the LocalID when there isn't one. It's the correct number of characters. - public const string DetailLogZero = "0000000000"; - -} -} diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSNPlugin/BSShapeCollection.cs deleted file mode 100644 index 47fb768..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BSShapeCollection.cs +++ /dev/null @@ -1,1015 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using OMV = OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; -using OpenSim.Region.Physics.ConvexDecompositionDotNet; - -namespace OpenSim.Region.Physics.BulletSNPlugin -{ -public sealed class BSShapeCollection : IDisposable -{ - private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; - - private BSScene PhysicsScene { get; set; } - - private Object m_collectionActivityLock = new Object(); - - // Description of a Mesh - private struct MeshDesc - { - public Object ptr; - public int referenceCount; - public DateTime lastReferenced; - public UInt64 shapeKey; - } - - // Description of a hull. - // Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations. - private struct HullDesc - { - public Object ptr; - public int referenceCount; - public DateTime lastReferenced; - public UInt64 shapeKey; - } - - // The sharable set of meshes and hulls. Indexed by their shape hash. - private Dictionary Meshes = new Dictionary(); - private Dictionary Hulls = new Dictionary(); - - private bool DDetail = false; - - public BSShapeCollection(BSScene physScene) - { - PhysicsScene = physScene; - // Set the next to 'true' for very detailed shape update detailed logging (detailed details?) - // While detailed debugging is still active, this is better than commenting out all the - // DetailLog statements. When debugging slows down, this and the protected logging - // statements can be commented/removed. - DDetail = true; - } - - public void Dispose() - { - // TODO!!!!!!!!! - } - - // Callbacks called just before either the body or shape is destroyed. - // Mostly used for changing bodies out from under Linksets. - // Useful for other cases where parameters need saving. - // Passing 'null' says no callback. - public delegate void ShapeDestructionCallback(BulletShape shape); - public delegate void BodyDestructionCallback(BulletBody body); - - // Called to update/change the body and shape for an object. - // First checks the shape and updates that if necessary then makes - // sure the body is of the right type. - // Return 'true' if either the body or the shape changed. - // 'shapeCallback' and 'bodyCallback' are, if non-null, functions called just before - // the current shape or body is destroyed. This allows the caller to remove any - // higher level dependencies on the shape or body. Mostly used for LinkSets to - // remove the physical constraints before the body is destroyed. - // Called at taint-time!! - public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim, - ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) - { - PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape"); - - bool ret = false; - - // This lock could probably be pushed down lower but building shouldn't take long - lock (m_collectionActivityLock) - { - // Do we have the correct geometry for this type of object? - // Updates prim.BSShape with information/pointers to shape. - // Returns 'true' of BSShape is changed to a new shape. - bool newGeom = CreateGeom(forceRebuild, prim, shapeCallback); - // If we had to select a new shape geometry for the object, - // rebuild the body around it. - // Updates prim.BSBody with information/pointers to requested body - // Returns 'true' if BSBody was changed. - bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, - prim.PhysShape, bodyCallback); - ret = newGeom || newBody; - } - DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", - prim.LocalID, forceRebuild, ret, prim.PhysBody, prim.PhysShape); - - return ret; - } - - public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim) - { - return GetBodyAndShape(forceRebuild, sim, prim, null, null); - } - - // Track another user of a body. - // We presume the caller has allocated the body. - // Bodies only have one user so the body is just put into the world if not already there. - public void ReferenceBody(BulletBody body, bool inTaintTime) - { - lock (m_collectionActivityLock) - { - if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body); - PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate() - { - if (!BulletSimAPI.IsInWorld2(PhysicsScene.World.ptr, body.ptr)) - { - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); - if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); - } - }); - } - } - - // Release the usage of a body. - // Called when releasing use of a BSBody. BSShape is handled separately. - public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback ) - { - if (!body.HasPhysicalBody) - return; - - lock (m_collectionActivityLock) - { - PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate() - { - if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}", - body.ID, body, inTaintTime); - // If the caller needs to know the old body is going away, pass the event up. - if (bodyCallback != null) bodyCallback(body); - - if (BulletSimAPI.IsInWorld2(PhysicsScene.World.ptr, body.ptr)) - { - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); - if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body); - } - - // Zero any reference to the shape so it is not freed when the body is deleted. - BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, null); - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); - }); - } - } - - // Track the datastructures and use count for a shape. - // When creating a hull, this is called first to reference the mesh - // and then again to reference the hull. - // Meshes and hulls for the same shape have the same hash key. - // NOTE that native shapes are not added to the mesh list or removed. - // Returns 'true' if this is the initial reference to the shape. Otherwise reused. - public bool ReferenceShape(BulletShape shape) - { - bool ret = false; - switch (shape.type) - { - case BSPhysicsShapeType.SHAPE_MESH: - MeshDesc meshDesc; - if (Meshes.TryGetValue(shape.shapeKey, out meshDesc)) - { - // There is an existing instance of this mesh. - meshDesc.referenceCount++; - if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}", - BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); - } - else - { - // This is a new reference to a mesh - meshDesc.ptr = shape.ptr; - meshDesc.shapeKey = shape.shapeKey; - // We keep a reference to the underlying IMesh data so a hull can be built - meshDesc.referenceCount = 1; - if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}", - BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); - ret = true; - } - meshDesc.lastReferenced = System.DateTime.Now; - Meshes[shape.shapeKey] = meshDesc; - break; - case BSPhysicsShapeType.SHAPE_HULL: - HullDesc hullDesc; - if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) - { - // There is an existing instance of this hull. - hullDesc.referenceCount++; - if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}", - BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); - } - else - { - // This is a new reference to a hull - hullDesc.ptr = shape.ptr; - hullDesc.shapeKey = shape.shapeKey; - hullDesc.referenceCount = 1; - if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}", - BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); - ret = true; - - } - hullDesc.lastReferenced = System.DateTime.Now; - Hulls[shape.shapeKey] = hullDesc; - break; - case BSPhysicsShapeType.SHAPE_UNKNOWN: - break; - default: - // Native shapes are not tracked and they don't go into any list - break; - } - return ret; - } - - // Release the usage of a shape. - public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback) - { - if (!shape.HasPhysicalShape) - return; - - PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate() - { - if (shape.HasPhysicalShape) - { - if (shape.isNativeShape) - { - // Native shapes are not tracked and are released immediately - if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", - BSScene.DetailLogZero, shape.ptr.ToString(), inTaintTime); - if (shapeCallback != null) shapeCallback(shape); - BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); - } - else - { - switch (shape.type) - { - case BSPhysicsShapeType.SHAPE_HULL: - DereferenceHull(shape, shapeCallback); - break; - case BSPhysicsShapeType.SHAPE_MESH: - DereferenceMesh(shape, shapeCallback); - break; - case BSPhysicsShapeType.SHAPE_COMPOUND: - DereferenceCompound(shape, shapeCallback); - break; - case BSPhysicsShapeType.SHAPE_UNKNOWN: - break; - default: - break; - } - } - } - }); - } - - // Count down the reference count for a mesh shape - // Called at taint-time. - private void DereferenceMesh(BulletShape shape, ShapeDestructionCallback shapeCallback) - { - MeshDesc meshDesc; - if (Meshes.TryGetValue(shape.shapeKey, out meshDesc)) - { - meshDesc.referenceCount--; - // TODO: release the Bullet storage - if (shapeCallback != null) shapeCallback(shape); - meshDesc.lastReferenced = System.DateTime.Now; - Meshes[shape.shapeKey] = meshDesc; - if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}", - BSScene.DetailLogZero, shape, meshDesc.referenceCount); - - } - } - - // Count down the reference count for a hull shape - // Called at taint-time. - private void DereferenceHull(BulletShape shape, ShapeDestructionCallback shapeCallback) - { - HullDesc hullDesc; - if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) - { - hullDesc.referenceCount--; - // TODO: release the Bullet storage (aging old entries?) - - // Tell upper layers that, if they have dependencies on this shape, this link is going away - if (shapeCallback != null) shapeCallback(shape); - - hullDesc.lastReferenced = System.DateTime.Now; - Hulls[shape.shapeKey] = hullDesc; - if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}", - BSScene.DetailLogZero, shape, hullDesc.referenceCount); - } - } - - // Remove a reference to a compound shape. - // Taking a compound shape apart is a little tricky because if you just delete the - // physical shape, it will free all the underlying children. We can't do that because - // they could be shared. So, this removes each of the children from the compound and - // dereferences them separately before destroying the compound collision object itself. - // Called at taint-time. - private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback) - { - if (!BulletSimAPI.IsCompound2(shape.ptr)) - { - // Failed the sanity check!! - PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}", - LogHeader, shape.type, shape.ptr.ToString()); - if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}", - BSScene.DetailLogZero, shape.type, shape.ptr.ToString()); - return; - } - - int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr); - if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren); - - for (int ii = numChildren - 1; ii >= 0; ii--) - { - Object childShape = BulletSimAPI.RemoveChildShapeFromCompoundShapeIndex2(shape.ptr, ii); - DereferenceAnonCollisionShape(childShape); - } - BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); - } - - // Sometimes we have a pointer to a collision shape but don't know what type it is. - // Figure out type and call the correct dereference routine. - // Called at taint-time. - private void DereferenceAnonCollisionShape(Object cShape) - { - MeshDesc meshDesc; - HullDesc hullDesc; - - BulletShape shapeInfo = new BulletShape(cShape); - if (TryGetMeshByPtr(cShape, out meshDesc)) - { - shapeInfo.type = BSPhysicsShapeType.SHAPE_MESH; - shapeInfo.shapeKey = meshDesc.shapeKey; - } - else - { - if (TryGetHullByPtr(cShape, out hullDesc)) - { - shapeInfo.type = BSPhysicsShapeType.SHAPE_HULL; - shapeInfo.shapeKey = hullDesc.shapeKey; - } - else - { - if (BulletSimAPI.IsCompound2(cShape)) - { - shapeInfo.type = BSPhysicsShapeType.SHAPE_COMPOUND; - } - else - { - if (BulletSimAPI.IsNativeShape2(cShape)) - { - shapeInfo.isNativeShape = true; - shapeInfo.type = BSPhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) - } - } - } - } - - if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo); - - if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN) - { - DereferenceShape(shapeInfo, true, null); - } - else - { - PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}", - LogHeader, PhysicsScene.RegionName, cShape.ToString()); - } - } - - // Create the geometry information in Bullet for later use. - // The objects needs a hull if it's physical otherwise a mesh is enough. - // if 'forceRebuild' is true, the geometry is unconditionally rebuilt. For meshes and hulls, - // shared geometries will be used. If the parameters of the existing shape are the same - // as this request, the shape is not rebuilt. - // Info in prim.BSShape is updated to the new shape. - // Returns 'true' if the geometry was rebuilt. - // Called at taint-time! - private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - bool ret = false; - bool haveShape = false; - - if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE) - { - // an avatar capsule is close to a native shape (it is not shared) - GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE, - FixedShapeKey.KEY_CAPSULE, shapeCallback); - if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); - ret = true; - haveShape = true; - } - - // Compound shapes are handled special as they are rebuilt from scratch. - // This isn't too great a hardship since most of the child shapes will have already been created. - if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND) - { - ret = GetReferenceToCompoundShape(prim, shapeCallback); - if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape); - haveShape = true; - } - - if (!haveShape) - { - ret = CreateGeomNonSpecial(forceRebuild, prim, shapeCallback); - } - - return ret; - } - - // Create a mesh/hull shape or a native shape if 'nativeShapePossible' is 'true'. - public bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - bool ret = false; - bool haveShape = false; - bool nativeShapePossible = true; - PrimitiveBaseShape pbs = prim.BaseShape; - - // If the prim attributes are simple, this could be a simple Bullet native shape - if (!haveShape - && pbs != null - && nativeShapePossible - && ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) - || (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) ) ) - { - // Get the scale of any existing shape so we can see if the new shape is same native type and same size. - OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero; - if (prim.PhysShape.HasPhysicalShape) - scaleOfExistingShape = BulletSimAPI.GetLocalScaling2(prim.PhysShape.ptr); - - if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}", - prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.type); - - // It doesn't look like Bullet scales spheres so make sure the scales are all equal - if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) - && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z) - { - haveShape = true; - if (forceRebuild - || prim.Scale != scaleOfExistingShape - || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE - ) - { - ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE, - FixedShapeKey.KEY_SPHERE, shapeCallback); - if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", - prim.LocalID, forceRebuild, prim.PhysShape); - } - } - if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) - { - haveShape = true; - if (forceRebuild - || prim.Scale != scaleOfExistingShape - || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX - ) - { - ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX, - FixedShapeKey.KEY_BOX, shapeCallback); - if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", - prim.LocalID, forceRebuild, prim.PhysShape); - } - } - } - - // If a simple shape is not happening, create a mesh and possibly a hull. - if (!haveShape && pbs != null) - { - ret = CreateGeomMeshOrHull(prim, shapeCallback); - } - - return ret; - } - - public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - - bool ret = false; - // Note that if it's a native shape, the check for physical/non-physical is not - // made. Native shapes work in either case. - if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects) - { - // Update prim.BSShape to reference a hull of this shape. - ret = GetReferenceToHull(prim,shapeCallback); - if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", - prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); - } - else - { - ret = GetReferenceToMesh(prim, shapeCallback); - if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", - prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); - } - return ret; - } - - // Creates a native shape and assignes it to prim.BSShape. - // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape(). - private bool GetReferenceToNativeShape(BSPhysObject prim, - BSPhysicsShapeType shapeType, FixedShapeKey shapeKey, - ShapeDestructionCallback shapeCallback) - { - // release any previous shape - DereferenceShape(prim.PhysShape, true, shapeCallback); - - BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey); - - // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. - if (DDetail) DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", - prim.LocalID, newShape, prim.Scale); - - // native shapes are scaled by Bullet - prim.PhysShape = newShape; - return true; - } - - private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, BSPhysicsShapeType shapeType, - FixedShapeKey shapeKey) - { - BulletShape newShape; - // Need to make sure the passed shape information is for the native type. - ShapeData nativeShapeData = new ShapeData(); - nativeShapeData.Type = shapeType; - nativeShapeData.ID = prim.LocalID; - nativeShapeData.Scale = prim.Scale; - nativeShapeData.Size = prim.Scale; // unneeded, I think. - nativeShapeData.MeshKey = (ulong)shapeKey; - nativeShapeData.HullKey = (ulong)shapeKey; - - if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE) - { - // The proper scale has been calculated in the prim. - newShape = new BulletShape( - BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale) - , shapeType); - if (DDetail) DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); - } - else - { - // Native shapes are scaled in Bullet so set the scaling to the size - newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType); - } - if (!newShape.HasPhysicalShape) - { - PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", - LogHeader, prim.LocalID, shapeType); - } - newShape.shapeKey = (System.UInt64)shapeKey; - newShape.isNativeShape = true; - - return newShape; - } - - // Builds a mesh shape in the physical world and updates prim.BSShape. - // Dereferences previous shape in BSShape and adds a reference for this new shape. - // Returns 'true' of a mesh was actually built. Otherwise . - // Called at taint-time! - private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - BulletShape newShape = new BulletShape(); - - float lod; - System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); - - // if this new shape is the same as last time, don't recreate the mesh - if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH) - return false; - - if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}", - prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); - - // Since we're recreating new, get rid of the reference to the previous shape - DereferenceShape(prim.PhysShape, true, shapeCallback); - - newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, prim.BaseShape, prim.Size, lod); - // Take evasive action if the mesh was not constructed. - newShape = VerifyMeshCreated(newShape, prim); - - ReferenceShape(newShape); - - prim.PhysShape = newShape; - - return true; // 'true' means a new shape has been added to this prim - } - - private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) - { - IMesh meshData = null; - Object meshPtr = null; - MeshDesc meshDesc; - if (Meshes.TryGetValue(newMeshKey, out meshDesc)) - { - // If the mesh has already been built just use it. - meshPtr = meshDesc.ptr; - } - else - { - meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false); - - if (meshData != null) - { - int[] indices = meshData.getIndexListAsInt(); - List vertices = meshData.getVertexList(); - - float[] verticesAsFloats = new float[vertices.Count * 3]; - int vi = 0; - foreach (OMV.Vector3 vv in vertices) - { - verticesAsFloats[vi++] = vv.X; - verticesAsFloats[vi++] = vv.Y; - verticesAsFloats[vi++] = vv.Z; - } - - // m_log.DebugFormat("{0}: BSShapeCollection.CreatePhysicalMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", - // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); - - meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, - indices.GetLength(0), indices, vertices.Count, verticesAsFloats); - } - } - BulletShape newShape = new BulletShape(meshPtr, BSPhysicsShapeType.SHAPE_MESH); - newShape.shapeKey = newMeshKey; - - return newShape; - } - - // See that hull shape exists in the physical world and update prim.BSShape. - // We could be creating the hull because scale changed or whatever. - private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - BulletShape newShape; - - float lod; - System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); - - // if the hull hasn't changed, don't rebuild it - if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL) - return false; - - if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}", - prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); - - // Remove usage of the previous shape. - DereferenceShape(prim.PhysShape, true, shapeCallback); - - newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod); - newShape = VerifyMeshCreated(newShape, prim); - - ReferenceShape(newShape); - - prim.PhysShape = newShape; - return true; // 'true' means a new shape has been added to this prim - } - - List m_hulls; - private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) - { - - Object hullPtr = null; - HullDesc hullDesc; - if (Hulls.TryGetValue(newHullKey, out hullDesc)) - { - // If the hull shape already is created, just use it. - hullPtr = hullDesc.ptr; - } - else - { - // Build a new hull in the physical world - // Pass true for physicalness as this creates some sort of bounding box which we don't need - IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false); - if (meshData != null) - { - - int[] indices = meshData.getIndexListAsInt(); - List vertices = meshData.getVertexList(); - - //format conversion from IMesh format to DecompDesc format - List convIndices = new List(); - List convVertices = new List(); - for (int ii = 0; ii < indices.GetLength(0); ii++) - { - convIndices.Add(indices[ii]); - } - foreach (OMV.Vector3 vv in vertices) - { - convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); - } - - // setup and do convex hull conversion - m_hulls = new List(); - DecompDesc dcomp = new DecompDesc(); - dcomp.mIndices = convIndices; - dcomp.mVertices = convVertices; - ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); - // create the hull into the _hulls variable - convexBuilder.process(dcomp); - - // Convert the vertices and indices for passing to unmanaged. - // The hull information is passed as a large floating point array. - // The format is: - // convHulls[0] = number of hulls - // convHulls[1] = number of vertices in first hull - // convHulls[2] = hull centroid X coordinate - // convHulls[3] = hull centroid Y coordinate - // convHulls[4] = hull centroid Z coordinate - // convHulls[5] = first hull vertex X - // convHulls[6] = first hull vertex Y - // convHulls[7] = first hull vertex Z - // convHulls[8] = second hull vertex X - // ... - // convHulls[n] = number of vertices in second hull - // convHulls[n+1] = second hull centroid X coordinate - // ... - // - // TODO: is is very inefficient. Someday change the convex hull generator to return - // data structures that do not need to be converted in order to pass to Bullet. - // And maybe put the values directly into pinned memory rather than marshaling. - int hullCount = m_hulls.Count; - int totalVertices = 1; // include one for the count of the hulls - foreach (ConvexResult cr in m_hulls) - { - totalVertices += 4; // add four for the vertex count and centroid - totalVertices += cr.HullIndices.Count * 3; // we pass just triangles - } - float[] convHulls = new float[totalVertices]; - - convHulls[0] = (float)hullCount; - int jj = 1; - foreach (ConvexResult cr in m_hulls) - { - // copy vertices for index access - float3[] verts = new float3[cr.HullVertices.Count]; - int kk = 0; - foreach (float3 ff in cr.HullVertices) - { - verts[kk++] = ff; - } - - // add to the array one hull's worth of data - convHulls[jj++] = cr.HullIndices.Count; - convHulls[jj++] = 0f; // centroid x,y,z - convHulls[jj++] = 0f; - convHulls[jj++] = 0f; - foreach (int ind in cr.HullIndices) - { - convHulls[jj++] = verts[ind].x; - convHulls[jj++] = verts[ind].y; - convHulls[jj++] = verts[ind].z; - } - } - // create the hull data structure in Bullet - hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls); - } - } - - BulletShape newShape = new BulletShape(hullPtr, BSPhysicsShapeType.SHAPE_HULL); - newShape.shapeKey = newHullKey; - - return newShape; - } - - // Callback from convex hull creater with a newly created hull. - // Just add it to our collection of hulls for this shape. - private void HullReturn(ConvexResult result) - { - m_hulls.Add(result); - return; - } - - // Compound shapes are always built from scratch. - // This shouldn't be to bad since most of the parts will be meshes that had been built previously. - private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - // Remove reference to the old shape - // Don't need to do this as the shape is freed when the new root shape is created below. - // DereferenceShape(prim.PhysShape, true, shapeCallback); - - BulletShape cShape = new BulletShape( - BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), BSPhysicsShapeType.SHAPE_COMPOUND); - - // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. - CreateGeomMeshOrHull(prim, shapeCallback); - BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, OMV.Vector3.Zero, OMV.Quaternion.Identity); - if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}", - prim.LocalID, cShape, prim.PhysShape); - - prim.PhysShape = cShape; - - return true; - } - - // Create a hash of all the shape parameters to be used as a key - // for this particular shape. - private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) - { - // level of detail based on size and type of the object - float lod = BSParam.MeshLOD; - if (pbs.SculptEntry) - lod = BSParam.SculptLOD; - - // Mega prims usually get more detail because one can interact with shape approximations at this size. - float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z)); - if (maxAxis > BSParam.MeshMegaPrimThreshold) - lod = BSParam.MeshMegaPrimLOD; - - retLod = lod; - return pbs.GetMeshKey(size, lod); - } - // For those who don't want the LOD - private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs) - { - float lod; - return ComputeShapeKey(size, pbs, out lod); - } - - // The creation of a mesh or hull can fail if an underlying asset is not available. - // There are two cases: 1) the asset is not in the cache and it needs to be fetched; - // and 2) the asset cannot be converted (like failed decompression of JPEG2000s). - // The first case causes the asset to be fetched. The second case requires - // us to not loop forever. - // Called after creating a physical mesh or hull. If the physical shape was created, - // just return. - private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim) - { - // If the shape was successfully created, nothing more to do - if (newShape.HasPhysicalShape) - return newShape; - - // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset - if (prim.BaseShape.SculptEntry && !prim.LastAssetBuildFailed && prim.BaseShape.SculptTexture != OMV.UUID.Zero) - { - prim.LastAssetBuildFailed = true; - BSPhysObject xprim = prim; - DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lID={1},lastFailed={2}", - LogHeader, prim.LocalID, prim.LastAssetBuildFailed); - Util.FireAndForget(delegate - { - RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; - if (assetProvider != null) - { - BSPhysObject yprim = xprim; // probably not necessary, but, just in case. - assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset) - { - if (!yprim.BaseShape.SculptEntry) - return; - if (yprim.BaseShape.SculptTexture.ToString() != asset.ID) - return; - - yprim.BaseShape.SculptData = asset.Data; - // This will cause the prim to see that the filler shape is not the right - // one and try again to build the object. - // No race condition with the normal shape setting since the rebuild is at taint time. - yprim.ForceBodyShapeRebuild(false); - - }); - } - }); - } - else - { - if (prim.LastAssetBuildFailed) - { - PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}", - LogHeader, prim.LocalID, prim.BaseShape.SculptTexture); - } - } - - // While we figure out the real problem, stick a simple native shape on the object. - BulletShape fillinShape = - BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); - - return fillinShape; - } - - // Create a body object in Bullet. - // Updates prim.BSBody with the information about the new body if one is created. - // Returns 'true' if an object was actually created. - // Called at taint-time. - private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, BulletShape shape, - BodyDestructionCallback bodyCallback) - { - bool ret = false; - - // the mesh, hull or native shape must have already been created in Bullet - bool mustRebuild = !prim.PhysBody.HasPhysicalBody; - - // If there is an existing body, verify it's of an acceptable type. - // If not a solid object, body is a GhostObject. Otherwise a RigidBody. - if (!mustRebuild) - { - CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(prim.PhysBody.ptr); - if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY - || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) - { - // If the collisionObject is not the correct type for solidness, rebuild what's there - mustRebuild = true; - } - } - - if (mustRebuild || forceRebuild) - { - // Free any old body - DereferenceBody(prim.PhysBody, true, bodyCallback); - - BulletBody aBody; - Object bodyPtr = null; - if (prim.IsSolid) - { - bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, - prim.LocalID, prim.RawPosition, prim.RawOrientation); - if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString()); - } - else - { - bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, - prim.LocalID, prim.RawPosition, prim.RawOrientation); - if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString()); - } - aBody = new BulletBody(prim.LocalID, bodyPtr); - - ReferenceBody(aBody, true); - - prim.PhysBody = aBody; - - ret = true; - } - - return ret; - } - - private bool TryGetMeshByPtr(Object addr, out MeshDesc outDesc) - { - bool ret = false; - MeshDesc foundDesc = new MeshDesc(); - foreach (MeshDesc md in Meshes.Values) - { - if (md.ptr == addr) - { - foundDesc = md; - ret = true; - break; - } - - } - outDesc = foundDesc; - return ret; - } - - private bool TryGetHullByPtr(Object addr, out HullDesc outDesc) - { - bool ret = false; - HullDesc foundDesc = new HullDesc(); - foreach (HullDesc hd in Hulls.Values) - { - if (hd.ptr == addr) - { - foundDesc = hd; - ret = true; - break; - } - - } - outDesc = foundDesc; - return ret; - } - - private void DetailLog(string msg, params Object[] args) - { - if (PhysicsScene.PhysicsLogging.Enabled) - PhysicsScene.DetailLog(msg, args); - } -} -} diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSNPlugin/BSShapes.cs deleted file mode 100644 index 8ff0275..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BSShapes.cs +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace OpenSim.Region.Physics.BulletSNPlugin -{ -public abstract class BSShape -{ - public Object ptr { get; set; } - public BSPhysicsShapeType type { get; set; } - public System.UInt64 key { get; set; } - public int referenceCount { get; set; } - public DateTime lastReferenced { get; set; } - - public BSShape() - { - ptr = null; - type = BSPhysicsShapeType.SHAPE_UNKNOWN; - key = 0; - referenceCount = 0; - lastReferenced = DateTime.Now; - } - - // Get a reference to a physical shape. Create if it doesn't exist - public static BSShape GetShapeReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) - { - BSShape ret = null; - - if (prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE) - { - // an avatar capsule is close to a native shape (it is not shared) - ret = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_CAPSULE, - FixedShapeKey.KEY_CAPSULE); - physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret); - } - - // Compound shapes are handled special as they are rebuilt from scratch. - // This isn't too great a hardship since most of the child shapes will already been created. - if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND) - { - // Getting a reference to a compound shape gets you the compound shape with the root prim shape added - ret = BSShapeCompound.GetReference(prim); - physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret); - } - - if (ret == null) - ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim); - - return ret; - } - public static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) - { - return null; - } - public static BSShape GetShapeReferenceNonNative(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) - { - return null; - } - - // Release the use of a physical shape. - public abstract void Dereference(BSScene physicsScene); - - // All shapes have a static call to get a reference to the physical shape - // protected abstract static BSShape GetReference(); - - public override string ToString() - { - StringBuilder buff = new StringBuilder(); - buff.Append(""); - return buff.ToString(); - } -} - -public class BSShapeNull : BSShape -{ - public BSShapeNull() : base() - { - } - public static BSShape GetReference() { return new BSShapeNull(); } - public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ } -} - -public class BSShapeNative : BSShape -{ - private static string LogHeader = "[BULLETSIM SHAPE NATIVE]"; - public BSShapeNative() : base() - { - } - public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim, - BSPhysicsShapeType shapeType, FixedShapeKey shapeKey) - { - // Native shapes are not shared and are always built anew. - return new BSShapeNative(physicsScene, prim, shapeType, shapeKey); - } - - private BSShapeNative(BSScene physicsScene, BSPhysObject prim, - BSPhysicsShapeType shapeType, FixedShapeKey shapeKey) - { - ShapeData nativeShapeData = new ShapeData(); - nativeShapeData.Type = shapeType; - nativeShapeData.ID = prim.LocalID; - nativeShapeData.Scale = prim.Scale; - nativeShapeData.Size = prim.Scale; - nativeShapeData.MeshKey = (ulong)shapeKey; - nativeShapeData.HullKey = (ulong)shapeKey; - - - if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE) - { - ptr = BulletSimAPI.BuildCapsuleShape2(physicsScene.World.ptr, 1f, 1f, prim.Scale); - physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); - } - else - { - ptr = BulletSimAPI.BuildNativeShape2(physicsScene.World.ptr, nativeShapeData); - } - if (ptr == null) - { - physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", - LogHeader, prim.LocalID, shapeType); - } - type = shapeType; - key = (UInt64)shapeKey; - } - // Make this reference to the physical shape go away since native shapes are not shared. - public override void Dereference(BSScene physicsScene) - { - // Native shapes are not tracked and are released immediately - physicsScene.DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this); - BulletSimAPI.DeleteCollisionShape2(physicsScene.World.ptr, ptr); - ptr = null; - // Garbage collection will free up this instance. - } -} - -public class BSShapeMesh : BSShape -{ - private static string LogHeader = "[BULLETSIM SHAPE MESH]"; - private static Dictionary Meshes = new Dictionary(); - - public BSShapeMesh() : base() - { - } - public static BSShape GetReference() { return new BSShapeNull(); } - public override void Dereference(BSScene physicsScene) { } -} - -public class BSShapeHull : BSShape -{ - private static string LogHeader = "[BULLETSIM SHAPE HULL]"; - private static Dictionary Hulls = new Dictionary(); - - public BSShapeHull() : base() - { - } - public static BSShape GetReference() { return new BSShapeNull(); } - public override void Dereference(BSScene physicsScene) { } -} - -public class BSShapeCompound : BSShape -{ - private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]"; - public BSShapeCompound() : base() - { - } - public static BSShape GetReference(BSPhysObject prim) - { - return new BSShapeNull(); - } - public override void Dereference(BSScene physicsScene) { } -} -} diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSNPlugin/BSTerrainHeightmap.cs deleted file mode 100644 index ba17059..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BSTerrainHeightmap.cs +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OpenSim.Framework; -using OpenSim.Region.Framework; -using OpenSim.Region.CoreModules; -using OpenSim.Region.Physics.Manager; - -using Nini.Config; -using log4net; - -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSNPlugin -{ -public sealed class BSTerrainHeightmap : BSTerrainPhys -{ - static string LogHeader = "[BULLETSIM TERRAIN HEIGHTMAP]"; - - BulletHeightMapInfo m_mapInfo = null; - - // Constructor to build a default, flat heightmap terrain. - public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize) - : base(physicsScene, regionBase, id) - { - Vector3 minTerrainCoords = new Vector3(0f, 0f, BSTerrainManager.HEIGHT_INITIALIZATION - BSTerrainManager.HEIGHT_EQUAL_FUDGE); - Vector3 maxTerrainCoords = new Vector3(regionSize.X, regionSize.Y, BSTerrainManager.HEIGHT_INITIALIZATION); - int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y; - float[] initialMap = new float[totalHeights]; - for (int ii = 0; ii < totalHeights; ii++) - { - initialMap[ii] = BSTerrainManager.HEIGHT_INITIALIZATION; - } - m_mapInfo = new BulletHeightMapInfo(id, initialMap, null); - m_mapInfo.minCoords = minTerrainCoords; - m_mapInfo.maxCoords = maxTerrainCoords; - m_mapInfo.terrainRegionBase = TerrainBase; - // Don't have to free any previous since we just got here. - BuildHeightmapTerrain(); - } - - // This minCoords and maxCoords passed in give the size of the terrain (min and max Z - // are the high and low points of the heightmap). - public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, - Vector3 minCoords, Vector3 maxCoords) - : base(physicsScene, regionBase, id) - { - m_mapInfo = new BulletHeightMapInfo(id, initialMap, null); - m_mapInfo.minCoords = minCoords; - m_mapInfo.maxCoords = maxCoords; - m_mapInfo.minZ = minCoords.Z; - m_mapInfo.maxZ = maxCoords.Z; - m_mapInfo.terrainRegionBase = TerrainBase; - - // Don't have to free any previous since we just got here. - BuildHeightmapTerrain(); - } - - public override void Dispose() - { - ReleaseHeightMapTerrain(); - } - - // Using the information in m_mapInfo, create the physical representation of the heightmap. - private void BuildHeightmapTerrain() - { - m_mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, m_mapInfo.ID, - m_mapInfo.minCoords, m_mapInfo.maxCoords, - m_mapInfo.heightMap, BSParam.TerrainCollisionMargin); - - // Create the terrain shape from the mapInfo - m_mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(m_mapInfo.Ptr), - BSPhysicsShapeType.SHAPE_TERRAIN); - - // The terrain object initial position is at the center of the object - Vector3 centerPos; - centerPos.X = m_mapInfo.minCoords.X + (m_mapInfo.sizeX / 2f); - centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f); - centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f - 0.5f); - - m_mapInfo.terrainBody = new BulletBody(m_mapInfo.ID, - BulletSimAPI.CreateBodyWithDefaultMotionState2(m_mapInfo.terrainShape.ptr, - m_mapInfo.ID, centerPos, Quaternion.Identity)); - - // Set current terrain attributes - BulletSimAPI.SetFriction2(m_mapInfo.terrainBody.ptr, BSParam.TerrainFriction); - BulletSimAPI.SetHitFraction2(m_mapInfo.terrainBody.ptr, BSParam.TerrainHitFraction); - BulletSimAPI.SetRestitution2(m_mapInfo.terrainBody.ptr, BSParam.TerrainRestitution); - BulletSimAPI.SetCollisionFlags2(m_mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - - // Return the new terrain to the world of physical objects - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr, centerPos, Quaternion.Identity); - - // redo its bounding box now that it is in the world - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); - - m_mapInfo.terrainBody.collisionType = CollisionType.Terrain; - m_mapInfo.terrainBody.ApplyCollisionMask(); - - // Make it so the terrain will not move or be considered for movement. - BulletSimAPI.ForceActivationState2(m_mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); - - return; - } - - // If there is information in m_mapInfo pointing to physical structures, release same. - private void ReleaseHeightMapTerrain() - { - if (m_mapInfo != null) - { - if (m_mapInfo.terrainBody.HasPhysicalBody) - { - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); - // Frees both the body and the shape. - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); - BulletSimAPI.ReleaseHeightMapInfo2(m_mapInfo.Ptr); - } - } - m_mapInfo = null; - } - - // The passed position is relative to the base of the region. - public override float GetTerrainHeightAtXYZ(Vector3 pos) - { - float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; - - int mapIndex = (int)pos.Y * (int)m_mapInfo.sizeY + (int)pos.X; - try - { - ret = m_mapInfo.heightMap[mapIndex]; - } - catch - { - // Sometimes they give us wonky values of X and Y. Give a warning and return something. - PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", - LogHeader, m_mapInfo.terrainRegionBase, pos); - ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; - } - return ret; - } - - // The passed position is relative to the base of the region. - public override float GetWaterLevelAtXYZ(Vector3 pos) - { - return PhysicsScene.SimpleWaterLevel; - } -} -} diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSNPlugin/BSTerrainManager.cs deleted file mode 100644 index 66d62f0..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BSTerrainManager.cs +++ /dev/null @@ -1,461 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OpenSim.Framework; -using OpenSim.Region.Framework; -using OpenSim.Region.CoreModules; -using OpenSim.Region.Physics.Manager; - -using Nini.Config; -using log4net; - -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSNPlugin -{ - -// The physical implementation of the terrain is wrapped in this class. -public abstract class BSTerrainPhys : IDisposable -{ - public enum TerrainImplementation - { - Heightmap = 0, - Mesh = 1 - } - - public BSScene PhysicsScene { get; private set; } - // Base of the region in world coordinates. Coordinates inside the region are relative to this. - public Vector3 TerrainBase { get; private set; } - public uint ID { get; private set; } - - public BSTerrainPhys(BSScene physicsScene, Vector3 regionBase, uint id) - { - PhysicsScene = physicsScene; - TerrainBase = regionBase; - ID = id; - } - public abstract void Dispose(); - public abstract float GetTerrainHeightAtXYZ(Vector3 pos); - public abstract float GetWaterLevelAtXYZ(Vector3 pos); -} - -// ========================================================================================== -public sealed class BSTerrainManager : IDisposable -{ - static string LogHeader = "[BULLETSIM TERRAIN MANAGER]"; - - // These height values are fractional so the odd values will be - // noticable when debugging. - public const float HEIGHT_INITIALIZATION = 24.987f; - public const float HEIGHT_INITIAL_LASTHEIGHT = 24.876f; - public const float HEIGHT_GETHEIGHT_RET = 24.765f; - public const float WATER_HEIGHT_GETHEIGHT_RET = 19.998f; - - // If the min and max height are equal, we reduce the min by this - // amount to make sure that a bounding box is built for the terrain. - public const float HEIGHT_EQUAL_FUDGE = 0.2f; - - // Until the whole simulator is changed to pass us the region size, we rely on constants. - public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); - - // The scene that I am part of - private BSScene PhysicsScene { get; set; } - - // The ground plane created to keep thing from falling to infinity. - private BulletBody m_groundPlane; - - // If doing mega-regions, if we're region zero we will be managing multiple - // region terrains since region zero does the physics for the whole mega-region. - private Dictionary m_terrains; - - // Flags used to know when to recalculate the height. - private bool m_terrainModified = false; - - // If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount. - // This is incremented before assigning to new region so it is the last ID allocated. - private uint m_terrainCount = BSScene.CHILDTERRAIN_ID - 1; - public uint HighestTerrainID { get {return m_terrainCount; } } - - // If doing mega-regions, this holds our offset from region zero of - // the mega-regions. "parentScene" points to the PhysicsScene of region zero. - private Vector3 m_worldOffset; - // If the parent region (region 0), this is the extent of the combined regions - // relative to the origin of region zero - private Vector3 m_worldMax; - private PhysicsScene MegaRegionParentPhysicsScene { get; set; } - - public BSTerrainManager(BSScene physicsScene) - { - PhysicsScene = physicsScene; - m_terrains = new Dictionary(); - - // Assume one region of default size - m_worldOffset = Vector3.Zero; - m_worldMax = new Vector3(DefaultRegionSize); - MegaRegionParentPhysicsScene = null; - } - - public void Dispose() - { - ReleaseGroundPlaneAndTerrain(); - } - - // Create the initial instance of terrain and the underlying ground plane. - // This is called from the initialization routine so we presume it is - // safe to call Bullet in real time. We hope no one is moving prims around yet. - public void CreateInitialGroundPlaneAndTerrain() - { - // The ground plane is here to catch things that are trying to drop to negative infinity - BulletShape groundPlaneShape = new BulletShape( - BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, - BSParam.TerrainCollisionMargin), - BSPhysicsShapeType.SHAPE_GROUNDPLANE); - m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, - BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, - Vector3.Zero, Quaternion.Identity)); - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr, Vector3.Zero, Quaternion.Identity); - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_groundPlane.ptr); - // Ground plane does not move - BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION); - // Everything collides with the ground plane. - m_groundPlane.collisionType = CollisionType.Groundplane; - m_groundPlane.ApplyCollisionMask(); - - // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain. - BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize); - m_terrains.Add(Vector3.Zero, initialTerrain); - } - - // Release all the terrain structures we might have allocated - public void ReleaseGroundPlaneAndTerrain() - { - if (m_groundPlane.HasPhysicalBody) - { - if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr)) - { - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_groundPlane.ptr); - } - m_groundPlane.Clear(); - } - - ReleaseTerrain(); - } - - // Release all the terrain we have allocated - public void ReleaseTerrain() - { - lock (m_terrains) - { - foreach (KeyValuePair kvp in m_terrains) - { - kvp.Value.Dispose(); - } - m_terrains.Clear(); - } - } - - // The simulator wants to set a new heightmap for the terrain. - public void SetTerrain(float[] heightMap) { - float[] localHeightMap = heightMap; - // If there are multiple requests for changes to the same terrain between ticks, - // only do that last one. - PhysicsScene.PostTaintObject("TerrainManager.SetTerrain-"+ m_worldOffset.ToString(), 0, delegate() - { - if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null) - { - // If a child of a mega-region, we shouldn't have any terrain allocated for us - ReleaseGroundPlaneAndTerrain(); - // If doing the mega-prim stuff and we are the child of the zero region, - // the terrain is added to our parent - if (MegaRegionParentPhysicsScene is BSScene) - { - DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", - BSScene.DetailLogZero, m_worldOffset, m_worldMax); - ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateTerrain( - BSScene.CHILDTERRAIN_ID, localHeightMap, - m_worldOffset, m_worldOffset + DefaultRegionSize, true); - } - } - else - { - // If not doing the mega-prim thing, just change the terrain - DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero); - - UpdateTerrain(BSScene.TERRAIN_ID, localHeightMap, - m_worldOffset, m_worldOffset + DefaultRegionSize, true); - } - }); - } - - // If called with no mapInfo for the terrain, this will create a new mapInfo and terrain - // based on the passed information. The 'id' should be either the terrain id or - // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used. - // The latter feature is for creating child terrains for mega-regions. - // If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new - // terrain shape is created and added to the body. - // This call is most often used to update the heightMap and parameters of the terrain. - // (The above does suggest that some simplification/refactoring is in order.) - // Called during taint-time. - private void UpdateTerrain(uint id, float[] heightMap, - Vector3 minCoords, Vector3 maxCoords, bool inTaintTime) - { - DetailLog("{0},BSTerrainManager.UpdateTerrain,call,minC={1},maxC={2},inTaintTime={3}", - BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime); - - // Find high and low points of passed heightmap. - // The min and max passed in is usually the area objects can be in (maximum - // object height, for instance). The terrain wants the bounding box for the - // terrain so replace passed min and max Z with the actual terrain min/max Z. - float minZ = float.MaxValue; - float maxZ = float.MinValue; - foreach (float height in heightMap) - { - if (height < minZ) minZ = height; - if (height > maxZ) maxZ = height; - } - if (minZ == maxZ) - { - // If min and max are the same, reduce min a little bit so a good bounding box is created. - minZ -= BSTerrainManager.HEIGHT_EQUAL_FUDGE; - } - minCoords.Z = minZ; - maxCoords.Z = maxZ; - - Vector3 terrainRegionBase = new Vector3(minCoords.X, minCoords.Y, 0f); - - lock (m_terrains) - { - BSTerrainPhys terrainPhys; - if (m_terrains.TryGetValue(terrainRegionBase, out terrainPhys)) - { - // There is already a terrain in this spot. Free the old and build the new. - DetailLog("{0},UpdateTerrain:UpdateExisting,call,id={1},base={2},minC={3},maxC={4}", - BSScene.DetailLogZero, id, terrainRegionBase, minCoords, minCoords); - - // Remove old terrain from the collection - m_terrains.Remove(terrainRegionBase); - // Release any physical memory it may be using. - terrainPhys.Dispose(); - - if (MegaRegionParentPhysicsScene == null) - { - BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords); - m_terrains.Add(terrainRegionBase, newTerrainPhys); - - m_terrainModified = true; - } - else - { - // It's possible that Combine() was called after this code was queued. - // If we are a child of combined regions, we don't create any terrain for us. - DetailLog("{0},BSTerrainManager.UpdateTerrain:AmACombineChild,taint", BSScene.DetailLogZero); - - // Get rid of any terrain that may have been allocated for us. - ReleaseGroundPlaneAndTerrain(); - - // I hate doing this, but just bail - return; - } - } - else - { - // We don't know about this terrain so either we are creating a new terrain or - // our mega-prim child is giving us a new terrain to add to the phys world - - // if this is a child terrain, calculate a unique terrain id - uint newTerrainID = id; - if (newTerrainID >= BSScene.CHILDTERRAIN_ID) - newTerrainID = ++m_terrainCount; - - DetailLog("{0},UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}", - BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); - BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords); - m_terrains.Add(terrainRegionBase, newTerrainPhys); - - m_terrainModified = true; - } - } - } - - // TODO: redo terrain implementation selection to allow other base types than heightMap. - private BSTerrainPhys BuildPhysicalTerrain(Vector3 terrainRegionBase, uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords) - { - PhysicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}", - LogHeader, PhysicsScene.RegionName, terrainRegionBase, - (BSTerrainPhys.TerrainImplementation)BSParam.TerrainImplementation); - BSTerrainPhys newTerrainPhys = null; - switch ((int)BSParam.TerrainImplementation) - { - case (int)BSTerrainPhys.TerrainImplementation.Heightmap: - newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, - heightMap, minCoords, maxCoords); - break; - case (int)BSTerrainPhys.TerrainImplementation.Mesh: - newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id, - heightMap, minCoords, maxCoords); - break; - default: - PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}", - LogHeader, - (int)BSParam.TerrainImplementation, - BSParam.TerrainImplementation, - PhysicsScene.RegionName, terrainRegionBase); - break; - } - return newTerrainPhys; - } - - // Return 'true' of this position is somewhere in known physical terrain space - public bool IsWithinKnownTerrain(Vector3 pos) - { - Vector3 terrainBaseXYZ; - BSTerrainPhys physTerrain; - return GetTerrainPhysicalAtXYZ(pos, out physTerrain, out terrainBaseXYZ); - } - - // Given an X and Y, find the height of the terrain. - // Since we could be handling multiple terrains for a mega-region, - // the base of the region is calcuated assuming all regions are - // the same size and that is the default. - // Once the heightMapInfo is found, we have all the information to - // compute the offset into the array. - private float lastHeightTX = 999999f; - private float lastHeightTY = 999999f; - private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT; - public float GetTerrainHeightAtXYZ(Vector3 pos) - { - float tX = pos.X; - float tY = pos.Y; - // You'd be surprized at the number of times this routine is called - // with the same parameters as last time. - if (!m_terrainModified && (lastHeightTX == tX) && (lastHeightTY == tY)) - return lastHeight; - m_terrainModified = false; - - lastHeightTX = tX; - lastHeightTY = tY; - float ret = HEIGHT_GETHEIGHT_RET; - - Vector3 terrainBaseXYZ; - BSTerrainPhys physTerrain; - if (GetTerrainPhysicalAtXYZ(pos, out physTerrain, out terrainBaseXYZ)) - { - ret = physTerrain.GetTerrainHeightAtXYZ(pos - terrainBaseXYZ); - } - else - { - PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", - LogHeader, PhysicsScene.RegionName, tX, tY); - DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,terrainNotFound,pos={1},base={2}", - BSScene.DetailLogZero, pos, terrainBaseXYZ); - } - - lastHeight = ret; - return ret; - } - - public float GetWaterLevelAtXYZ(Vector3 pos) - { - float ret = WATER_HEIGHT_GETHEIGHT_RET; - - Vector3 terrainBaseXYZ; - BSTerrainPhys physTerrain; - if (GetTerrainPhysicalAtXYZ(pos, out physTerrain, out terrainBaseXYZ)) - { - ret = physTerrain.GetWaterLevelAtXYZ(pos); - } - else - { - PhysicsScene.Logger.ErrorFormat("{0} GetWaterHeightAtXY: terrain not found: pos={1}, terrainBase={2}, height={3}", - LogHeader, PhysicsScene.RegionName, pos, terrainBaseXYZ, ret); - } - return ret; - } - - // Given an address, return 'true' of there is a description of that terrain and output - // the descriptor class and the 'base' fo the addresses therein. - private bool GetTerrainPhysicalAtXYZ(Vector3 pos, out BSTerrainPhys outPhysTerrain, out Vector3 outTerrainBase) - { - int offsetX = ((int)(pos.X / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X; - int offsetY = ((int)(pos.Y / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y; - Vector3 terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f); - - BSTerrainPhys physTerrain = null; - lock (m_terrains) - { - m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain); - } - outTerrainBase = terrainBaseXYZ; - outPhysTerrain = physTerrain; - return (physTerrain != null); - } - - // Although no one seems to check this, I do support combining. - public bool SupportsCombining() - { - return true; - } - - // This routine is called two ways: - // One with 'offset' and 'pScene' zero and null but 'extents' giving the maximum - // extent of the combined regions. This is to inform the parent of the size - // of the combined regions. - // and one with 'offset' as the offset of the child region to the base region, - // 'pScene' pointing to the parent and 'extents' of zero. This informs the - // child of its relative base and new parent. - public void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) - { - m_worldOffset = offset; - m_worldMax = extents; - MegaRegionParentPhysicsScene = pScene; - if (pScene != null) - { - // We are a child. - // We want m_worldMax to be the highest coordinate of our piece of terrain. - m_worldMax = offset + DefaultRegionSize; - } - DetailLog("{0},BSTerrainManager.Combine,offset={1},extents={2},wOffset={3},wMax={4}", - BSScene.DetailLogZero, offset, extents, m_worldOffset, m_worldMax); - } - - // Unhook all the combining that I know about. - public void UnCombine(PhysicsScene pScene) - { - // Just like ODE, we don't do anything yet. - DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero); - } - - - private void DetailLog(string msg, params Object[] args) - { - PhysicsScene.PhysicsLogging.Write(msg, args); - } -} -} diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSNPlugin/BSTerrainMesh.cs deleted file mode 100644 index 6083dd4..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BSTerrainMesh.cs +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OpenSim.Framework; -using OpenSim.Region.Framework; -using OpenSim.Region.CoreModules; -using OpenSim.Region.Physics.Manager; - -using Nini.Config; -using log4net; - -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSNPlugin -{ -public sealed class BSTerrainMesh : BSTerrainPhys -{ - static string LogHeader = "[BULLETSIM TERRAIN MESH]"; - - private float[] m_savedHeightMap; - int m_sizeX; - int m_sizeY; - - BulletShape m_terrainShape; - BulletBody m_terrainBody; - - public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize) - : base(physicsScene, regionBase, id) - { - } - - public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id /* parameters for making mesh */) - : base(physicsScene, regionBase, id) - { - } - - // Create terrain mesh from a heightmap. - public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, - Vector3 minCoords, Vector3 maxCoords) - : base(physicsScene, regionBase, id) - { - int indicesCount; - int[] indices; - int verticesCount; - float[] vertices; - - m_savedHeightMap = initialMap; - - m_sizeX = (int)(maxCoords.X - minCoords.X); - m_sizeY = (int)(maxCoords.Y - minCoords.Y); - - if (!BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene, initialMap, - m_sizeX, m_sizeY, - (float)m_sizeX, (float)m_sizeY, - Vector3.Zero, 1.0f, - out indicesCount, out indices, out verticesCount, out vertices)) - { - // DISASTER!! - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap", ID); - PhysicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase); - // Something is very messed up and a crash is in our future. - return; - } - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,indices={1},indSz={2},vertices={3},vertSz={4}", - ID, indicesCount, indices.Length, verticesCount, vertices.Length); - - m_terrainShape = new BulletShape(BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, - indicesCount, indices, verticesCount, vertices), - BSPhysicsShapeType.SHAPE_MESH); - if (!m_terrainShape.HasPhysicalShape) - { - // DISASTER!! - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID); - physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase); - // Something is very messed up and a crash is in our future. - return; - } - - Vector3 pos = regionBase; - Quaternion rot = Quaternion.Identity; - - m_terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2( m_terrainShape.ptr, ID, pos, rot)); - if (!m_terrainBody.HasPhysicalBody) - { - // DISASTER!! - physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase); - // Something is very messed up and a crash is in our future. - return; - } - - // Set current terrain attributes - BulletSimAPI.SetFriction2(m_terrainBody.ptr, BSParam.TerrainFriction); - BulletSimAPI.SetHitFraction2(m_terrainBody.ptr, BSParam.TerrainHitFraction); - BulletSimAPI.SetRestitution2(m_terrainBody.ptr, BSParam.TerrainRestitution); - BulletSimAPI.SetCollisionFlags2(m_terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - - // Static objects are not very massive. - BulletSimAPI.SetMassProps2(m_terrainBody.ptr, 0f, Vector3.Zero); - - // Put the new terrain to the world of physical objects - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr, pos, rot); - - // Redo its bounding box now that it is in the world - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_terrainBody.ptr); - - m_terrainBody.collisionType = CollisionType.Terrain; - m_terrainBody.ApplyCollisionMask(); - - // Make it so the terrain will not move or be considered for movement. - BulletSimAPI.ForceActivationState2(m_terrainBody.ptr, ActivationState.DISABLE_SIMULATION); - } - - public override void Dispose() - { - if (m_terrainBody.HasPhysicalBody) - { - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr); - // Frees both the body and the shape. - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_terrainBody.ptr); - } - } - - public override float GetTerrainHeightAtXYZ(Vector3 pos) - { - // For the moment use the saved heightmap to get the terrain height. - // TODO: raycast downward to find the true terrain below the position. - float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; - - int mapIndex = (int)pos.Y * m_sizeY + (int)pos.X; - try - { - ret = m_savedHeightMap[mapIndex]; - } - catch - { - // Sometimes they give us wonky values of X and Y. Give a warning and return something. - PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", - LogHeader, TerrainBase, pos); - ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; - } - return ret; - } - - // The passed position is relative to the base of the region. - public override float GetWaterLevelAtXYZ(Vector3 pos) - { - return PhysicsScene.SimpleWaterLevel; - } - - // Convert the passed heightmap to mesh information suitable for CreateMeshShape2(). - // Return 'true' if successfully created. - public static bool ConvertHeightmapToMesh( - BSScene physicsScene, - float[] heightMap, int sizeX, int sizeY, // parameters of incoming heightmap - float extentX, float extentY, // zero based range for output vertices - Vector3 extentBase, // base to be added to all vertices - float magnification, // number of vertices to create between heightMap coords - out int indicesCountO, out int[] indicesO, - out int verticesCountO, out float[] verticesO) - { - bool ret = false; - - int indicesCount = 0; - int verticesCount = 0; - int[] indices = new int[0]; - float[] vertices = new float[0]; - - // Simple mesh creation which assumes magnification == 1. - // TODO: do a more general solution that scales, adds new vertices and smoothes the result. - - // Create an array of vertices that is sizeX+1 by sizeY+1 (note the loop - // from zero to <= sizeX). The triangle indices are then generated as two triangles - // per heightmap point. There are sizeX by sizeY of these squares. The extra row and - // column of vertices are used to complete the triangles of the last row and column - // of the heightmap. - try - { - // One vertice per heightmap value plus the vertices off the top and bottom edge. - int totalVertices = (sizeX + 1) * (sizeY + 1); - vertices = new float[totalVertices * 3]; - int totalIndices = sizeX * sizeY * 6; - indices = new int[totalIndices]; - - float magX = (float)sizeX / extentX; - float magY = (float)sizeY / extentY; - physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2},extentBase={3},magX={4},magY={5}", - BSScene.DetailLogZero, totalVertices, totalIndices, extentBase, magX, magY); - float minHeight = float.MaxValue; - // Note that sizeX+1 vertices are created since there is land between this and the next region. - for (int yy = 0; yy <= sizeY; yy++) - { - for (int xx = 0; xx <= sizeX; xx++) // Hint: the "<=" means we go around sizeX + 1 times - { - int offset = yy * sizeX + xx; - // Extend the height with the height from the last row or column - if (yy == sizeY) offset -= sizeX; - if (xx == sizeX) offset -= 1; - float height = heightMap[offset]; - minHeight = Math.Min(minHeight, height); - vertices[verticesCount + 0] = (float)xx * magX + extentBase.X; - vertices[verticesCount + 1] = (float)yy * magY + extentBase.Y; - vertices[verticesCount + 2] = height + extentBase.Z; - verticesCount += 3; - } - } - verticesCount = verticesCount / 3; - - for (int yy = 0; yy < sizeY; yy++) - { - for (int xx = 0; xx < sizeX; xx++) - { - int offset = yy * (sizeX + 1) + xx; - // Each vertices is presumed to be the upper left corner of a box of two triangles - indices[indicesCount + 0] = offset; - indices[indicesCount + 1] = offset + 1; - indices[indicesCount + 2] = offset + sizeX + 1; // accounting for the extra column - indices[indicesCount + 3] = offset + 1; - indices[indicesCount + 4] = offset + sizeX + 2; - indices[indicesCount + 5] = offset + sizeX + 1; - indicesCount += 6; - } - } - - ret = true; - } - catch (Exception e) - { - physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. For={1}/{2}, e={3}", - LogHeader, physicsScene.RegionName, extentBase, e); - } - - indicesCountO = indicesCount; - indicesO = indices; - verticesCountO = verticesCount; - verticesO = vertices; - - return ret; - } -} -} diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSNPlugin/BulletSimAPI.cs deleted file mode 100644 index 93643c9..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BulletSimAPI.cs +++ /dev/null @@ -1,1603 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.IO; -using System.Runtime.InteropServices; -using System.Security; -using System.Text; -using BulletXNA; -using OpenMetaverse; -using BulletXNA.LinearMath; -using BulletXNA.BulletCollision; -using BulletXNA.BulletDynamics; -using BulletXNA.BulletCollision.CollisionDispatch; -using OpenSim.Framework; - -namespace OpenSim.Region.Physics.BulletSNPlugin { - -// Classes to allow some type checking for the API -// These hold pointers to allocated objects in the unmanaged space. - - - - // Constraint type values as defined by Bullet -public enum ConstraintType : int -{ - POINT2POINT_CONSTRAINT_TYPE = 3, - HINGE_CONSTRAINT_TYPE, - CONETWIST_CONSTRAINT_TYPE, - D6_CONSTRAINT_TYPE, - SLIDER_CONSTRAINT_TYPE, - CONTACT_CONSTRAINT_TYPE, - D6_SPRING_CONSTRAINT_TYPE, - MAX_CONSTRAINT_TYPE -} - -// =============================================================================== -[StructLayout(LayoutKind.Sequential)] -public struct ConvexHull -{ - Vector3 Offset; - int VertexCount; - Vector3[] Vertices; -} -public enum BSPhysicsShapeType -{ - SHAPE_UNKNOWN = 0, - SHAPE_CAPSULE = 1, - SHAPE_BOX = 2, - SHAPE_CONE = 3, - SHAPE_CYLINDER = 4, - SHAPE_SPHERE = 5, - SHAPE_MESH = 6, - SHAPE_HULL = 7, - // following defined by BulletSim - SHAPE_GROUNDPLANE = 20, - SHAPE_TERRAIN = 21, - SHAPE_COMPOUND = 22, - SHAPE_HEIGHTMAP = 23, -}; - -// The native shapes have predefined shape hash keys -public enum FixedShapeKey : ulong -{ - KEY_NONE = 0, - KEY_BOX = 1, - KEY_SPHERE = 2, - KEY_CONE = 3, - KEY_CYLINDER = 4, - KEY_CAPSULE = 5, -} - -[StructLayout(LayoutKind.Sequential)] -public struct ShapeData -{ - public uint ID; - public BSPhysicsShapeType Type; - public Vector3 Position; - public Quaternion Rotation; - public Vector3 Velocity; - public Vector3 Scale; - public float Mass; - public float Buoyancy; - public System.UInt64 HullKey; - public System.UInt64 MeshKey; - public float Friction; - public float Restitution; - public float Collidable; // true of things bump into this - public float Static; // true if a static object. Otherwise gravity, etc. - public float Solid; // true if object cannot be passed through - public Vector3 Size; - - // note that bools are passed as floats since bool size changes by language and architecture - public const float numericTrue = 1f; - public const float numericFalse = 0f; -} -[StructLayout(LayoutKind.Sequential)] -public struct SweepHit -{ - public uint ID; - public float Fraction; - public Vector3 Normal; - public Vector3 Point; -} -[StructLayout(LayoutKind.Sequential)] -public struct RaycastHit -{ - public uint ID; - public float Fraction; - public Vector3 Normal; -} -[StructLayout(LayoutKind.Sequential)] -public struct CollisionDesc -{ - public uint aID; - public uint bID; - public Vector3 point; - public Vector3 normal; -} -[StructLayout(LayoutKind.Sequential)] -public struct EntityProperties -{ - public uint ID; - public Vector3 Position; - public Quaternion Rotation; - public Vector3 Velocity; - public Vector3 Acceleration; - public Vector3 RotationalVelocity; - public override string ToString() - { - return string.Format("ID:{0}, Pos:<{1:F},{2:F},{3:F}>, Rot:<{4:F},{5:F},{6:F},{7:F}>, LVel:<{8:F},{9:F},{10:F}>, AVel:<{11:F},{12:F},{13:F}>", - ID.ToString(), - Position.X,Position.Y,Position.Z, - Rotation.X,Rotation.Y,Rotation.Z,Rotation.W, - Velocity.X,Velocity.Y,Velocity.Z, - RotationalVelocity.X,RotationalVelocity.Y,RotationalVelocity.Z - ); - } -} - -// Format of this structure must match the definition in the C++ code -// NOTE: adding the X causes compile breaks if used. These are unused symbols -// that can be removed from both here and the unmanaged definition of this structure. -[StructLayout(LayoutKind.Sequential)] -public struct ConfigurationParameters -{ - public float defaultFriction; - public float defaultDensity; - public float defaultRestitution; - public float collisionMargin; - public float gravity; - - public float XlinearDamping; - public float XangularDamping; - public float XdeactivationTime; - public float XlinearSleepingThreshold; - public float XangularSleepingThreshold; - public float XccdMotionThreshold; - public float XccdSweptSphereRadius; - public float XcontactProcessingThreshold; - - public float XterrainImplementation; - public float XterrainFriction; - public float XterrainHitFraction; - public float XterrainRestitution; - public float XterrainCollisionMargin; - - public float XavatarFriction; - public float XavatarStandingFriction; - public float XavatarDensity; - public float XavatarRestitution; - public float XavatarCapsuleWidth; - public float XavatarCapsuleDepth; - public float XavatarCapsuleHeight; - public float XavatarContactProcessingThreshold; - - public float XvehicleAngularDamping; - - public float maxPersistantManifoldPoolSize; - public float maxCollisionAlgorithmPoolSize; - public float shouldDisableContactPoolDynamicAllocation; - public float shouldForceUpdateAllAabbs; - public float shouldRandomizeSolverOrder; - public float shouldSplitSimulationIslands; - public float shouldEnableFrictionCaching; - public float numberOfSolverIterations; - - public float XlinksetImplementation; - public float XlinkConstraintUseFrameOffset; - public float XlinkConstraintEnableTransMotor; - public float XlinkConstraintTransMotorMaxVel; - public float XlinkConstraintTransMotorMaxForce; - public float XlinkConstraintERP; - public float XlinkConstraintCFM; - public float XlinkConstraintSolverIterations; - - public float physicsLoggingFrames; - - public const float numericTrue = 1f; - public const float numericFalse = 0f; -} - - -// The states a bullet collision object can have - -public enum ActivationState : uint -{ - UNDEFINED = 0, - ACTIVE_TAG = 1, - ISLAND_SLEEPING = 2, - WANTS_DEACTIVATION = 3, - DISABLE_DEACTIVATION = 4, - DISABLE_SIMULATION = 5, -} - -public enum CollisionObjectTypes : int -{ - CO_COLLISION_OBJECT = 1 << 0, - CO_RIGID_BODY = 1 << 1, - CO_GHOST_OBJECT = 1 << 2, - CO_SOFT_BODY = 1 << 3, - CO_HF_FLUID = 1 << 4, - CO_USER_TYPE = 1 << 5, -} - -// Values used by Bullet and BulletSim to control object properties. -// Bullet's "CollisionFlags" has more to do with operations on the -// object (if collisions happen, if gravity effects it, ...). - [Flags] -public enum CollisionFlags : uint -{ - CF_STATIC_OBJECT = 1 << 0, - CF_KINEMATIC_OBJECT = 1 << 1, - CF_NO_CONTACT_RESPONSE = 1 << 2, - CF_CUSTOM_MATERIAL_CALLBACK = 1 << 3, - CF_CHARACTER_OBJECT = 1 << 4, - CF_DISABLE_VISUALIZE_OBJECT = 1 << 5, - CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6, - // Following used by BulletSim to control collisions and updates - BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, - BS_FLOATS_ON_WATER = 1 << 11, - BS_VEHICLE_COLLISIONS = 1 << 12, - BS_NONE = 0, - BS_ALL = 0xFFFFFFFF, - - // These are the collision flags switched depending on physical state. - // The other flags are used for other things and should not be fooled with. - BS_ACTIVE = CF_STATIC_OBJECT - | CF_KINEMATIC_OBJECT - | CF_NO_CONTACT_RESPONSE -}; - -// Values for collisions groups and masks -public enum CollisionFilterGroups : uint -{ - // Don't use the bit definitions!! Define the use in a - // filter/mask definition below. This way collision interactions - // are more easily debugged. - BNoneGroup = 0, - BDefaultGroup = 1 << 0, - BStaticGroup = 1 << 1, - BKinematicGroup = 1 << 2, - BDebrisGroup = 1 << 3, - BSensorTrigger = 1 << 4, - BCharacterGroup = 1 << 5, - BAllGroup = 0xFFFFFFFF, - // Filter groups defined by BulletSim - BGroundPlaneGroup = 1 << 10, - BTerrainGroup = 1 << 11, - BRaycastGroup = 1 << 12, - BSolidGroup = 1 << 13, - // BLinksetGroup = xx // a linkset proper is either static or dynamic - BLinksetChildGroup = 1 << 14, - // The collsion filters and masked are defined in one place -- don't want them scattered - AvatarGroup = BCharacterGroup, - AvatarMask = BAllGroup, - ObjectGroup = BSolidGroup, - ObjectMask = BAllGroup, - StaticObjectGroup = BStaticGroup, - StaticObjectMask = AvatarGroup | ObjectGroup, // static things don't interact with much - LinksetGroup = BLinksetChildGroup, - LinksetMask = BAllGroup & ~BLinksetChildGroup, // linkset objects don't collide with each other - VolumeDetectGroup = BSensorTrigger, - VolumeDetectMask = ~BSensorTrigger, - TerrainGroup = BTerrainGroup, - TerrainMask = BAllGroup & ~BStaticGroup, // static objects on the ground don't collide - GroundPlaneGroup = BGroundPlaneGroup, - GroundPlaneMask = BAllGroup - -}; - -// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 -// ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2. -public enum ConstraintParams : int -{ - BT_CONSTRAINT_ERP = 1, // this one is not used in Bullet as of 20120730 - BT_CONSTRAINT_STOP_ERP, - BT_CONSTRAINT_CFM, - BT_CONSTRAINT_STOP_CFM, -}; -public enum ConstraintParamAxis : int -{ - AXIS_LINEAR_X = 0, - AXIS_LINEAR_Y, - AXIS_LINEAR_Z, - AXIS_ANGULAR_X, - AXIS_ANGULAR_Y, - AXIS_ANGULAR_Z, - AXIS_LINEAR_ALL = 20, // these last three added by BulletSim so we don't have to do zillions of calls - AXIS_ANGULAR_ALL, - AXIS_ALL -}; - -// =============================================================================== -static class BulletSimAPI { - private static int m_collisionsThisFrame; - public delegate void DebugLogCallback(string msg); - /// - /// - /// - /// - /// - internal static bool RemoveObjectFromWorld2(object pWorld, object pBody) - { - DiscreteDynamicsWorld world = pWorld as DiscreteDynamicsWorld; - RigidBody body = pBody as RigidBody; - world.RemoveRigidBody(body); - return true; - } - - internal static void SetRestitution2(object pBody, float pRestitution) - { - RigidBody body = pBody as RigidBody; - body.SetRestitution(pRestitution); - } - - internal static void SetMargin2(object pShape, float pMargin) - { - CollisionShape shape = pShape as CollisionShape; - shape.SetMargin(pMargin); - } - - internal static void SetLocalScaling2(object pShape, Vector3 pScale) - { - CollisionShape shape = pShape as CollisionShape; - IndexedVector3 vec = new IndexedVector3(pScale.X, pScale.Y, pScale.Z); - shape.SetLocalScaling(ref vec); - - } - - internal static void SetContactProcessingThreshold2(object pBody, float contactprocessingthreshold) - { - RigidBody body = pBody as RigidBody; - body.SetContactProcessingThreshold(contactprocessingthreshold); - } - - internal static void SetCcdMotionThreshold2(object pBody, float pccdMotionThreashold) - { - RigidBody body = pBody as RigidBody; - body.SetCcdMotionThreshold(pccdMotionThreashold); - } - - internal static void SetCcdSweptSphereRadius2(object pBody, float pCcdSweptSphereRadius) - { - RigidBody body = pBody as RigidBody; - body.SetCcdSweptSphereRadius(pCcdSweptSphereRadius); - } - - internal static void SetAngularFactorV2(object pBody, Vector3 pAngularFactor) - { - RigidBody body = pBody as RigidBody; - body.SetAngularFactor(new IndexedVector3(pAngularFactor.X, pAngularFactor.Y, pAngularFactor.Z)); - } - - internal static CollisionFlags AddToCollisionFlags2(object pBody, CollisionFlags pcollisionFlags) - { - CollisionObject body = pBody as CollisionObject; - CollisionFlags existingcollisionFlags = (CollisionFlags)(uint)body.GetCollisionFlags(); - existingcollisionFlags |= pcollisionFlags; - body.SetCollisionFlags((BulletXNA.BulletCollision.CollisionFlags)(uint)existingcollisionFlags); - return (CollisionFlags) (uint) existingcollisionFlags; - } - - internal static void AddObjectToWorld2(object pWorld, object pBody) - { - RigidBody body = pBody as RigidBody; - DiscreteDynamicsWorld world = pWorld as DiscreteDynamicsWorld; - //if (!(body.GetCollisionShape().GetShapeType() == BroadphaseNativeTypes.STATIC_PLANE_PROXYTYPE && body.GetCollisionShape().GetShapeType() == BroadphaseNativeTypes.TERRAIN_SHAPE_PROXYTYPE)) - - world.AddRigidBody(body); - - //if (body.GetBroadphaseHandle() != null) - // world.UpdateSingleAabb(body); - } - - internal static void AddObjectToWorld2(object pWorld, object pBody, Vector3 _position, Quaternion _orientation) - { - RigidBody body = pBody as RigidBody; - DiscreteDynamicsWorld world = pWorld as DiscreteDynamicsWorld; - //if (!(body.GetCollisionShape().GetShapeType() == BroadphaseNativeTypes.STATIC_PLANE_PROXYTYPE && body.GetCollisionShape().GetShapeType() == BroadphaseNativeTypes.TERRAIN_SHAPE_PROXYTYPE)) - - world.AddRigidBody(body); - IndexedVector3 vposition = new IndexedVector3(_position.X, _position.Y, _position.Z); - IndexedQuaternion vquaternion = new IndexedQuaternion(_orientation.X, _orientation.Y, _orientation.Z, - _orientation.W); - IndexedMatrix mat = IndexedMatrix.CreateFromQuaternion(vquaternion); - mat._origin = vposition; - body.SetWorldTransform(mat); - //if (body.GetBroadphaseHandle() != null) - // world.UpdateSingleAabb(body); - } - - internal static void ForceActivationState2(object pBody, ActivationState pActivationState) - { - CollisionObject body = pBody as CollisionObject; - body.ForceActivationState((BulletXNA.BulletCollision.ActivationState)(uint)pActivationState); - } - - internal static void UpdateSingleAabb2(object pWorld, object pBody) - { - CollisionObject body = pBody as CollisionObject; - DiscreteDynamicsWorld world = pWorld as DiscreteDynamicsWorld; - world.UpdateSingleAabb(body); - } - - internal static bool SetCollisionGroupMask2(object pBody, uint pGroup, uint pMask) - { - RigidBody body = pBody as RigidBody; - body.GetBroadphaseHandle().m_collisionFilterGroup = (BulletXNA.BulletCollision.CollisionFilterGroups) pGroup; - body.GetBroadphaseHandle().m_collisionFilterGroup = (BulletXNA.BulletCollision.CollisionFilterGroups) pGroup; - if ((uint) body.GetBroadphaseHandle().m_collisionFilterGroup == 0) - return false; - return true; - } - - internal static void ClearAllForces2(object pBody) - { - CollisionObject body = pBody as CollisionObject; - IndexedVector3 zeroVector = new IndexedVector3(0, 0, 0); - body.SetInterpolationLinearVelocity(ref zeroVector); - body.SetInterpolationAngularVelocity(ref zeroVector); - IndexedMatrix bodytransform = body.GetWorldTransform(); - - body.SetInterpolationWorldTransform(ref bodytransform); - - if (body is RigidBody) - { - RigidBody rigidbody = body as RigidBody; - rigidbody.SetLinearVelocity(zeroVector); - rigidbody.SetAngularVelocity(zeroVector); - rigidbody.ClearForces(); - } - } - - internal static void SetInterpolationAngularVelocity2(object pBody, Vector3 pVector3) - { - RigidBody body = pBody as RigidBody; - IndexedVector3 vec = new IndexedVector3(pVector3.X, pVector3.Y, pVector3.Z); - body.SetInterpolationAngularVelocity(ref vec); - } - - internal static void SetAngularVelocity2(object pBody, Vector3 pVector3) - { - RigidBody body = pBody as RigidBody; - IndexedVector3 vec = new IndexedVector3(pVector3.X, pVector3.Y, pVector3.Z); - body.SetAngularVelocity(ref vec); - } - - internal static void ClearForces2(object pBody) - { - RigidBody body = pBody as RigidBody; - body.ClearForces(); - } - - internal static void SetTranslation2(object pBody, Vector3 _position, Quaternion _orientation) - { - RigidBody body = pBody as RigidBody; - IndexedVector3 vposition = new IndexedVector3(_position.X, _position.Y, _position.Z); - IndexedQuaternion vquaternion = new IndexedQuaternion(_orientation.X, _orientation.Y, _orientation.Z, - _orientation.W); - IndexedMatrix mat = IndexedMatrix.CreateFromQuaternion(vquaternion); - mat._origin = vposition; - body.SetWorldTransform(mat); - - } - - internal static Vector3 GetPosition2(object pBody) - { - RigidBody body = pBody as RigidBody; - IndexedVector3 pos = body.GetInterpolationWorldTransform()._origin; - return new Vector3(pos.X, pos.Y, pos.Z); - } - - internal static Vector3 CalculateLocalInertia2(object pShape, float pphysMass) - { - CollisionShape shape = pShape as CollisionShape; - IndexedVector3 inertia = IndexedVector3.Zero; - shape.CalculateLocalInertia(pphysMass, out inertia); - return new Vector3(inertia.X, inertia.Y, inertia.Z); - } - - internal static void SetMassProps2(object pBody, float pphysMass, Vector3 plocalInertia) - { - RigidBody body = pBody as RigidBody; - IndexedVector3 inertia = new IndexedVector3(plocalInertia.X, plocalInertia.Y, plocalInertia.Z); - body.SetMassProps(pphysMass, inertia); - } - - - internal static void SetObjectForce2(object pBody, Vector3 _force) - { - RigidBody body = pBody as RigidBody; - IndexedVector3 force = new IndexedVector3(_force.X, _force.Y, _force.Z); - body.SetTotalForce(ref force); - } - - internal static void SetFriction2(object pBody, float _currentFriction) - { - RigidBody body = pBody as RigidBody; - body.SetFriction(_currentFriction); - } - - internal static void SetLinearVelocity2(object pBody, Vector3 _velocity) - { - RigidBody body = pBody as RigidBody; - IndexedVector3 velocity = new IndexedVector3(_velocity.X, _velocity.Y, _velocity.Z); - body.SetLinearVelocity(velocity); - } - - internal static void Activate2(object pBody, bool pforceactivation) - { - RigidBody body = pBody as RigidBody; - body.Activate(pforceactivation); - - } - - internal static Quaternion GetOrientation2(object pBody) - { - RigidBody body = pBody as RigidBody; - IndexedQuaternion mat = body.GetInterpolationWorldTransform().GetRotation(); - return new Quaternion(mat.X, mat.Y, mat.Z, mat.W); - } - - internal static CollisionFlags RemoveFromCollisionFlags2(object pBody, CollisionFlags pcollisionFlags) - { - RigidBody body = pBody as RigidBody; - CollisionFlags existingcollisionFlags = (CollisionFlags)(uint)body.GetCollisionFlags(); - existingcollisionFlags &= ~pcollisionFlags; - body.SetCollisionFlags((BulletXNA.BulletCollision.CollisionFlags)(uint)existingcollisionFlags); - return (CollisionFlags)(uint)existingcollisionFlags; - } - - internal static void SetGravity2(object pBody, Vector3 pGravity) - { - RigidBody body = pBody as RigidBody; - IndexedVector3 gravity = new IndexedVector3(pGravity.X, pGravity.Y, pGravity.Z); - body.SetGravity(gravity); - } - - internal static bool DestroyConstraint2(object pBody, object pConstraint) - { - RigidBody body = pBody as RigidBody; - TypedConstraint constraint = pConstraint as TypedConstraint; - body.RemoveConstraintRef(constraint); - return true; - } - - internal static bool SetLinearLimits2(object pConstraint, Vector3 low, Vector3 high) - { - Generic6DofConstraint constraint = pConstraint as Generic6DofConstraint; - IndexedVector3 lowlimit = new IndexedVector3(low.X, low.Y, low.Z); - IndexedVector3 highlimit = new IndexedVector3(high.X, high.Y, high.Z); - constraint.SetLinearLowerLimit(lowlimit); - constraint.SetLinearUpperLimit(highlimit); - return true; - } - - internal static bool SetAngularLimits2(object pConstraint, Vector3 low, Vector3 high) - { - Generic6DofConstraint constraint = pConstraint as Generic6DofConstraint; - IndexedVector3 lowlimit = new IndexedVector3(low.X, low.Y, low.Z); - IndexedVector3 highlimit = new IndexedVector3(high.X, high.Y, high.Z); - constraint.SetAngularLowerLimit(lowlimit); - constraint.SetAngularUpperLimit(highlimit); - return true; - } - - internal static void SetConstraintNumSolverIterations2(object pConstraint, float cnt) - { - Generic6DofConstraint constraint = pConstraint as Generic6DofConstraint; - constraint.SetOverrideNumSolverIterations((int)cnt); - } - - internal static void CalculateTransforms2(object pConstraint) - { - Generic6DofConstraint constraint = pConstraint as Generic6DofConstraint; - constraint.CalculateTransforms(); - } - - internal static void SetConstraintEnable2(object pConstraint, float p_2) - { - Generic6DofConstraint constraint = pConstraint as Generic6DofConstraint; - constraint.SetEnabled((p_2 == 0) ? false : true); - } - - - //BulletSimAPI.Create6DofConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr,frame1, frame1rot,frame2, frame2rot,useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); - internal static object Create6DofConstraint2(object pWorld, object pBody1, object pBody2, Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot, bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies) - - { - DiscreteDynamicsWorld world = pWorld as DiscreteDynamicsWorld; - RigidBody body1 = pBody1 as RigidBody; - RigidBody body2 = pBody2 as RigidBody; - IndexedVector3 frame1v = new IndexedVector3(pframe1.X, pframe1.Y, pframe1.Z); - IndexedQuaternion frame1rot = new IndexedQuaternion(pframe1rot.X, pframe1rot.Y, pframe1rot.Z, pframe1rot.W); - IndexedMatrix frame1 = IndexedMatrix.CreateFromQuaternion(frame1rot); - frame1._origin = frame1v; - - IndexedVector3 frame2v = new IndexedVector3(pframe2.X, pframe2.Y, pframe2.Z); - IndexedQuaternion frame2rot = new IndexedQuaternion(pframe2rot.X, pframe2rot.Y, pframe2rot.Z, pframe2rot.W); - IndexedMatrix frame2 = IndexedMatrix.CreateFromQuaternion(frame2rot); - frame2._origin = frame1v; - - Generic6DofConstraint consttr = new Generic6DofConstraint(body1, body2, ref frame1, ref frame2, - puseLinearReferenceFrameA); - consttr.CalculateTransforms(); - world.AddConstraint(consttr,pdisableCollisionsBetweenLinkedBodies); - - return consttr; - } - - - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - internal static object Create6DofConstraintToPoint2(object pWorld, object pBody1, object pBody2, Vector3 pjoinPoint, bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies) - { - DiscreteDynamicsWorld world = pWorld as DiscreteDynamicsWorld; - RigidBody body1 = pBody1 as RigidBody; - RigidBody body2 = pBody2 as RigidBody; - IndexedMatrix frame1 = new IndexedMatrix(IndexedBasisMatrix.Identity, new IndexedVector3(0, 0, 0)); - IndexedMatrix frame2 = new IndexedMatrix(IndexedBasisMatrix.Identity, new IndexedVector3(0, 0, 0)); - - IndexedVector3 joinPoint = new IndexedVector3(pjoinPoint.X, pjoinPoint.Y, pjoinPoint.Z); - IndexedMatrix mat = IndexedMatrix.Identity; - mat._origin = new IndexedVector3(pjoinPoint.X, pjoinPoint.Y, pjoinPoint.Z); - frame1._origin = body1.GetWorldTransform().Inverse()*joinPoint; - frame2._origin = body2.GetWorldTransform().Inverse()*joinPoint; - - Generic6DofConstraint consttr = new Generic6DofConstraint(body1, body2, ref frame1, ref frame2, puseLinearReferenceFrameA); - consttr.CalculateTransforms(); - world.AddConstraint(consttr, pdisableCollisionsBetweenLinkedBodies); - - return consttr; - } - //SetFrames2(m_constraint.ptr, frameA, frameArot, frameB, frameBrot); - internal static void SetFrames2(object pConstraint, Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot) - { - Generic6DofConstraint constraint = pConstraint as Generic6DofConstraint; - IndexedVector3 frame1v = new IndexedVector3(pframe1.X, pframe1.Y, pframe1.Z); - IndexedQuaternion frame1rot = new IndexedQuaternion(pframe1rot.X, pframe1rot.Y, pframe1rot.Z, pframe1rot.W); - IndexedMatrix frame1 = IndexedMatrix.CreateFromQuaternion(frame1rot); - frame1._origin = frame1v; - - IndexedVector3 frame2v = new IndexedVector3(pframe2.X, pframe2.Y, pframe2.Z); - IndexedQuaternion frame2rot = new IndexedQuaternion(pframe2rot.X, pframe2rot.Y, pframe2rot.Z, pframe2rot.W); - IndexedMatrix frame2 = IndexedMatrix.CreateFromQuaternion(frame2rot); - frame2._origin = frame1v; - constraint.SetFrames(ref frame1, ref frame2); - } - - - - - internal static bool IsInWorld2(object pWorld, object pShapeObj) - { - DiscreteDynamicsWorld world = pWorld as DiscreteDynamicsWorld; - CollisionObject shape = pShapeObj as CollisionObject; - return world.IsInWorld(shape); - } - - internal static void SetInterpolationLinearVelocity2(object pBody, Vector3 VehicleVelocity) - { - RigidBody body = pBody as RigidBody; - IndexedVector3 velocity = new IndexedVector3(VehicleVelocity.X, VehicleVelocity.Y, VehicleVelocity.Z); - body.SetInterpolationLinearVelocity(ref velocity); - } - - internal static bool UseFrameOffset2(object pConstraint, float onOff) - { - Generic6DofConstraint constraint = pConstraint as Generic6DofConstraint; - constraint.SetUseFrameOffset((onOff == 0) ? false : true); - return true; - } - //SetBreakingImpulseThreshold2(m_constraint.ptr, threshold); - internal static bool SetBreakingImpulseThreshold2(object pConstraint, float threshold) - { - Generic6DofConstraint constraint = pConstraint as Generic6DofConstraint; - constraint.SetBreakingImpulseThreshold(threshold); - return true; - } - //BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, angularDamping); - internal static void SetAngularDamping2(object pBody, float angularDamping) - { - RigidBody body = pBody as RigidBody; - float lineardamping = body.GetLinearDamping(); - body.SetDamping(lineardamping, angularDamping); - - } - - internal static void UpdateInertiaTensor2(object pBody) - { - RigidBody body = pBody as RigidBody; - body.UpdateInertiaTensor(); - } - - internal static void RecalculateCompoundShapeLocalAabb2( object pCompoundShape) - { - - CompoundShape shape = pCompoundShape as CompoundShape; - shape.RecalculateLocalAabb(); - } - - //BulletSimAPI.GetCollisionFlags2(PhysBody.ptr) - internal static CollisionFlags GetCollisionFlags2(object pBody) - { - RigidBody body = pBody as RigidBody; - uint flags = (uint)body.GetCollisionFlags(); - return (CollisionFlags) flags; - } - - internal static void SetDamping2(object pBody, float pLinear, float pAngular) - { - RigidBody body = pBody as RigidBody; - body.SetDamping(pLinear, pAngular); - } - //PhysBody.ptr, PhysicsScene.Params.deactivationTime); - internal static void SetDeactivationTime2(object pBody, float pDeactivationTime) - { - RigidBody body = pBody as RigidBody; - body.SetDeactivationTime(pDeactivationTime); - } - //SetSleepingThresholds2(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); - internal static void SetSleepingThresholds2(object pBody, float plinearSleepingThreshold, float pangularSleepingThreshold) - { - RigidBody body = pBody as RigidBody; - body.SetSleepingThresholds(plinearSleepingThreshold, pangularSleepingThreshold); - } - - internal static CollisionObjectTypes GetBodyType2(object pBody) - { - RigidBody body = pBody as RigidBody; - return (CollisionObjectTypes)(int) body.GetInternalType(); - } - - //BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum); - internal static void ApplyCentralForce2(object pBody, Vector3 pfSum) - { - RigidBody body = pBody as RigidBody; - IndexedVector3 fSum = new IndexedVector3(pfSum.X, pfSum.Y, pfSum.Z); - body.ApplyCentralForce(ref fSum); - } - internal static void ApplyCentralImpulse2(object pBody, Vector3 pfSum) - { - RigidBody body = pBody as RigidBody; - IndexedVector3 fSum = new IndexedVector3(pfSum.X, pfSum.Y, pfSum.Z); - body.ApplyCentralImpulse(ref fSum); - } - internal static void ApplyTorque2(object pBody, Vector3 pfSum) - { - RigidBody body = pBody as RigidBody; - IndexedVector3 fSum = new IndexedVector3(pfSum.X, pfSum.Y, pfSum.Z); - body.ApplyTorque(ref fSum); - } - internal static void ApplyTorqueImpulse2(object pBody, Vector3 pfSum) - { - RigidBody body = pBody as RigidBody; - IndexedVector3 fSum = new IndexedVector3(pfSum.X, pfSum.Y, pfSum.Z); - body.ApplyTorqueImpulse(ref fSum); - } - - internal static void DumpRigidBody2(object p, object p_2) - { - //TODO: - } - - internal static void DumpCollisionShape2(object p, object p_2) - { - //TODO: - } - - internal static void DestroyObject2(object p, object p_2) - { - //TODO: - } - - internal static void Shutdown2(object pWorld) - { - DiscreteDynamicsWorld world = pWorld as DiscreteDynamicsWorld; - world.Cleanup(); - } - - internal static void DeleteCollisionShape2(object p, object p_2) - { - //TODO: - } - //(sim.ptr, shape.ptr, prim.LocalID, prim.RawPosition, prim.RawOrientation); - - internal static object CreateBodyFromShape2(object pWorld, object pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation) - { - CollisionWorld world = pWorld as CollisionWorld; - IndexedMatrix mat = - IndexedMatrix.CreateFromQuaternion(new IndexedQuaternion(pRawOrientation.X, pRawOrientation.Y, - pRawOrientation.Z, pRawOrientation.W)); - mat._origin = new IndexedVector3(pRawPosition.X, pRawPosition.Y, pRawPosition.Z); - CollisionShape shape = pShape as CollisionShape; - //UpdateSingleAabb2(world, shape); - // TODO: Feed Update array into null - RigidBody body = new RigidBody(0,new SimMotionState(world,pLocalID,mat,null),shape,IndexedVector3.Zero); - - body.SetUserPointer(pLocalID); - return body; - } - - - internal static object CreateBodyWithDefaultMotionState2( object pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation) - { - - IndexedMatrix mat = - IndexedMatrix.CreateFromQuaternion(new IndexedQuaternion(pRawOrientation.X, pRawOrientation.Y, - pRawOrientation.Z, pRawOrientation.W)); - mat._origin = new IndexedVector3(pRawPosition.X, pRawPosition.Y, pRawPosition.Z); - - CollisionShape shape = pShape as CollisionShape; - - // TODO: Feed Update array into null - RigidBody body = new RigidBody(0, new DefaultMotionState( mat, IndexedMatrix.Identity), shape, IndexedVector3.Zero); - body.SetWorldTransform(mat); - body.SetUserPointer(pLocalID); - return body; - } - //(m_mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - internal static void SetCollisionFlags2(object pBody, CollisionFlags collisionFlags) - { - RigidBody body = pBody as RigidBody; - body.SetCollisionFlags((BulletXNA.BulletCollision.CollisionFlags) (uint) collisionFlags); - } - //(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); - internal static void SetHitFraction2(object pBody, float pHitFraction) - { - RigidBody body = pBody as RigidBody; - body.SetHitFraction(pHitFraction); - } - //BuildCapsuleShape2(physicsScene.World.ptr, 1f, 1f, prim.Scale); - internal static object BuildCapsuleShape2(object pWorld, float pRadius, float pHeight, Vector3 pScale) - { - DiscreteDynamicsWorld world = pWorld as DiscreteDynamicsWorld; - IndexedVector3 scale = new IndexedVector3(pScale.X, pScale.Y, pScale.Z); - CapsuleShapeZ capsuleShapeZ = new CapsuleShapeZ(pRadius, pHeight); - capsuleShapeZ.SetMargin(world.WorldSettings.Params.collisionMargin); - capsuleShapeZ.SetLocalScaling(ref scale); - - return capsuleShapeZ; - } - - public static object Initialize2(Vector3 worldExtent, ConfigurationParameters[] o, int mMaxCollisionsPerFrame, ref List collisionArray, int mMaxUpdatesPerFrame, ref List updateArray, object mDebugLogCallbackHandle) - { - CollisionWorld.WorldData.ParamData p = new CollisionWorld.WorldData.ParamData(); - - p.angularDamping = o[0].XangularDamping; - p.defaultFriction = o[0].defaultFriction; - p.defaultFriction = o[0].defaultFriction; - p.defaultDensity = o[0].defaultDensity; - p.defaultRestitution = o[0].defaultRestitution; - p.collisionMargin = o[0].collisionMargin; - p.gravity = o[0].gravity; - - p.linearDamping = o[0].XlinearDamping; - p.angularDamping = o[0].XangularDamping; - p.deactivationTime = o[0].XdeactivationTime; - p.linearSleepingThreshold = o[0].XlinearSleepingThreshold; - p.angularSleepingThreshold = o[0].XangularSleepingThreshold; - p.ccdMotionThreshold = o[0].XccdMotionThreshold; - p.ccdSweptSphereRadius = o[0].XccdSweptSphereRadius; - p.contactProcessingThreshold = o[0].XcontactProcessingThreshold; - - p.terrainImplementation = o[0].XterrainImplementation; - p.terrainFriction = o[0].XterrainFriction; - - p.terrainHitFraction = o[0].XterrainHitFraction; - p.terrainRestitution = o[0].XterrainRestitution; - p.terrainCollisionMargin = o[0].XterrainCollisionMargin; - - p.avatarFriction = o[0].XavatarFriction; - p.avatarStandingFriction = o[0].XavatarStandingFriction; - p.avatarDensity = o[0].XavatarDensity; - p.avatarRestitution = o[0].XavatarRestitution; - p.avatarCapsuleWidth = o[0].XavatarCapsuleWidth; - p.avatarCapsuleDepth = o[0].XavatarCapsuleDepth; - p.avatarCapsuleHeight = o[0].XavatarCapsuleHeight; - p.avatarContactProcessingThreshold = o[0].XavatarContactProcessingThreshold; - - p.vehicleAngularDamping = o[0].XvehicleAngularDamping; - - p.maxPersistantManifoldPoolSize = o[0].maxPersistantManifoldPoolSize; - p.maxCollisionAlgorithmPoolSize = o[0].maxCollisionAlgorithmPoolSize; - p.shouldDisableContactPoolDynamicAllocation = o[0].shouldDisableContactPoolDynamicAllocation; - p.shouldForceUpdateAllAabbs = o[0].shouldForceUpdateAllAabbs; - p.shouldRandomizeSolverOrder = o[0].shouldRandomizeSolverOrder; - p.shouldSplitSimulationIslands = o[0].shouldSplitSimulationIslands; - p.shouldEnableFrictionCaching = o[0].shouldEnableFrictionCaching; - p.numberOfSolverIterations = o[0].numberOfSolverIterations; - - p.linksetImplementation = o[0].XlinksetImplementation; - p.linkConstraintUseFrameOffset = o[0].XlinkConstraintUseFrameOffset; - p.linkConstraintEnableTransMotor = o[0].XlinkConstraintEnableTransMotor; - p.linkConstraintTransMotorMaxVel = o[0].XlinkConstraintTransMotorMaxVel; - p.linkConstraintTransMotorMaxForce = o[0].XlinkConstraintTransMotorMaxForce; - p.linkConstraintERP = o[0].XlinkConstraintERP; - p.linkConstraintCFM = o[0].XlinkConstraintCFM; - p.linkConstraintSolverIterations = o[0].XlinkConstraintSolverIterations; - p.physicsLoggingFrames = o[0].physicsLoggingFrames; - DefaultCollisionConstructionInfo ccci = new DefaultCollisionConstructionInfo(); - - DefaultCollisionConfiguration cci = new DefaultCollisionConfiguration(); - CollisionDispatcher m_dispatcher = new CollisionDispatcher(cci); - - - if (p.maxPersistantManifoldPoolSize > 0) - cci.m_persistentManifoldPoolSize = (int)p.maxPersistantManifoldPoolSize; - if (p.shouldDisableContactPoolDynamicAllocation !=0) - m_dispatcher.SetDispatcherFlags(DispatcherFlags.CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION); - //if (p.maxCollisionAlgorithmPoolSize >0 ) - - DbvtBroadphase m_broadphase = new DbvtBroadphase(); - //IndexedVector3 aabbMin = new IndexedVector3(0, 0, 0); - //IndexedVector3 aabbMax = new IndexedVector3(256, 256, 256); - - //AxisSweep3Internal m_broadphase2 = new AxisSweep3Internal(ref aabbMin, ref aabbMax, Convert.ToInt32(0xfffe), 0xffff, ushort.MaxValue/2, null, true); - m_broadphase.GetOverlappingPairCache().SetInternalGhostPairCallback(new GhostPairCallback()); - - SequentialImpulseConstraintSolver m_solver = new SequentialImpulseConstraintSolver(); - - DiscreteDynamicsWorld world = new DiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, cci); - world.UpdatedObjects = updateArray; - world.UpdatedCollisions = collisionArray; - world.WorldSettings.Params = p; - world.SetForceUpdateAllAabbs(p.shouldForceUpdateAllAabbs != 0); - world.GetSolverInfo().m_solverMode = SolverMode.SOLVER_USE_WARMSTARTING | SolverMode.SOLVER_SIMD; - if (p.shouldRandomizeSolverOrder != 0) - world.GetSolverInfo().m_solverMode |= SolverMode.SOLVER_RANDMIZE_ORDER; - - world.GetSimulationIslandManager().SetSplitIslands(p.shouldSplitSimulationIslands != 0); - //world.GetDispatchInfo().m_enableSatConvex Not implemented in C# port - - if (p.shouldEnableFrictionCaching != 0) - world.GetSolverInfo().m_solverMode |= SolverMode.SOLVER_ENABLE_FRICTION_DIRECTION_CACHING; - - if (p.numberOfSolverIterations > 0) - world.GetSolverInfo().m_numIterations = (int) p.numberOfSolverIterations; - - - world.GetSolverInfo().m_damping = world.WorldSettings.Params.linearDamping; - world.GetSolverInfo().m_restitution = world.WorldSettings.Params.defaultRestitution; - world.GetSolverInfo().m_globalCfm = 0.0f; - world.GetSolverInfo().m_tau = 0.6f; - world.GetSolverInfo().m_friction = 0.3f; - world.GetSolverInfo().m_maxErrorReduction = 20f; - world.GetSolverInfo().m_numIterations = 10; - world.GetSolverInfo().m_erp = 0.2f; - world.GetSolverInfo().m_erp2 = 0.1f; - world.GetSolverInfo().m_sor = 1.0f; - world.GetSolverInfo().m_splitImpulse = false; - world.GetSolverInfo().m_splitImpulsePenetrationThreshold = -0.02f; - world.GetSolverInfo().m_linearSlop = 0.0f; - world.GetSolverInfo().m_warmstartingFactor = 0.85f; - world.GetSolverInfo().m_restingContactRestitutionThreshold = 2; - world.SetForceUpdateAllAabbs(true); - - - world.SetGravity(new IndexedVector3(0,0,p.gravity)); - - return world; - } - //m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL - internal static bool SetConstraintParam2(object pConstraint, ConstraintParams paramIndex, float paramvalue, ConstraintParamAxis axis) - { - Generic6DofConstraint constrain = pConstraint as Generic6DofConstraint; - if (axis == ConstraintParamAxis.AXIS_LINEAR_ALL || axis == ConstraintParamAxis.AXIS_ALL) - { - constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams) (int) paramIndex, paramvalue, 0); - constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams) (int) paramIndex, paramvalue, 1); - constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams) (int) paramIndex, paramvalue, 2); - } - if (axis == ConstraintParamAxis.AXIS_ANGULAR_ALL || axis == ConstraintParamAxis.AXIS_ALL) - { - constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams)(int)paramIndex, paramvalue, 3); - constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams)(int)paramIndex, paramvalue, 4); - constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams)(int)paramIndex, paramvalue, 5); - } - if (axis == ConstraintParamAxis.AXIS_LINEAR_ALL) - { - constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams)(int)paramIndex, paramvalue, (int)axis); - } - return true; - } - - internal static bool PushUpdate2(object pCollisionObject) - { - bool ret = false; - RigidBody rb = pCollisionObject as RigidBody; - if (rb != null) - { - SimMotionState sms = rb.GetMotionState() as SimMotionState; - if (sms != null) - { - IndexedMatrix wt = IndexedMatrix.Identity; - sms.GetWorldTransform(out wt); - sms.SetWorldTransform(ref wt, true); - ret = true; - } - } - return ret; - - } - - internal static bool IsCompound2(object pShape) - { - CollisionShape shape = pShape as CollisionShape; - return shape.IsCompound(); - } - internal static bool IsPloyhedral2(object pShape) - { - CollisionShape shape = pShape as CollisionShape; - return shape.IsPolyhedral(); - } - internal static bool IsConvex2d2(object pShape) - { - CollisionShape shape = pShape as CollisionShape; - return shape.IsConvex2d(); - } - internal static bool IsConvex2(object pShape) - { - CollisionShape shape = pShape as CollisionShape; - return shape.IsConvex(); - } - internal static bool IsNonMoving2(object pShape) - { - CollisionShape shape = pShape as CollisionShape; - return shape.IsNonMoving(); - } - internal static bool IsConcave2(object pShape) - { - CollisionShape shape = pShape as CollisionShape; - return shape.IsConcave(); - } - internal static bool IsInfinite2(object pShape) - { - CollisionShape shape = pShape as CollisionShape; - return shape.IsInfinite(); - } - internal static bool IsNativeShape2(object pShape) - { - CollisionShape shape = pShape as CollisionShape; - bool ret; - switch (shape.GetShapeType()) - { - case BroadphaseNativeTypes.BOX_SHAPE_PROXYTYPE: - case BroadphaseNativeTypes.CONE_SHAPE_PROXYTYPE: - case BroadphaseNativeTypes.SPHERE_SHAPE_PROXYTYPE: - case BroadphaseNativeTypes.CYLINDER_SHAPE_PROXYTYPE: - ret = true; - break; - default: - ret = false; - break; - } - return ret; - } - //sim.ptr, shape.ptr,prim.LocalID, prim.RawPosition, prim.RawOrientation - internal static object CreateGhostFromShape2(object pWorld, object pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation) - { - IndexedMatrix bodyTransform = new IndexedMatrix(); - bodyTransform._origin = new IndexedVector3(pRawPosition.X, pRawPosition.Y, pRawPosition.Z); - bodyTransform.SetRotation(new IndexedQuaternion(pRawOrientation.X,pRawOrientation.Y,pRawOrientation.Z,pRawOrientation.W)); - GhostObject gObj = new PairCachingGhostObject(); - gObj.SetWorldTransform(bodyTransform); - CollisionShape shape = pShape as CollisionShape; - gObj.SetCollisionShape(shape); - gObj.SetUserPointer(pLocalID); - // TODO: Add to Special CollisionObjects! - return gObj; - } - - public static void SetCollisionShape2(object pWorld, object pObj, object pShape) - { - var world = pWorld as DiscreteDynamicsWorld; - var obj = pObj as CollisionObject; - var shape = pShape as CollisionShape; - obj.SetCollisionShape(shape); - - } - //(PhysicsScene.World.ptr, nativeShapeData) - internal static object BuildNativeShape2(object pWorld, ShapeData pShapeData) - { - var world = pWorld as DiscreteDynamicsWorld; - CollisionShape shape = null; - switch (pShapeData.Type) - { - case BSPhysicsShapeType.SHAPE_BOX: - shape = new BoxShape(new IndexedVector3(0.5f,0.5f,0.5f)); - break; - case BSPhysicsShapeType.SHAPE_CONE: - shape = new ConeShapeZ(0.5f, 1.0f); - break; - case BSPhysicsShapeType.SHAPE_CYLINDER: - shape = new CylinderShapeZ(new IndexedVector3(0.5f, 0.5f, 0.5f)); - break; - case BSPhysicsShapeType.SHAPE_SPHERE: - shape = new SphereShape(0.5f); - break; - - } - if (shape != null) - { - IndexedVector3 scaling = new IndexedVector3(pShapeData.Scale.X, pShapeData.Scale.Y, pShapeData.Scale.Z); - shape.SetMargin(world.WorldSettings.Params.collisionMargin); - shape.SetLocalScaling(ref scaling); - - } - return shape; - } - //PhysicsScene.World.ptr, false - internal static object CreateCompoundShape2(object pWorld, bool enableDynamicAabbTree) - { - return new CompoundShape(enableDynamicAabbTree); - } - - internal static int GetNumberOfCompoundChildren2(object pCompoundShape) - { - var compoundshape = pCompoundShape as CompoundShape; - return compoundshape.GetNumChildShapes(); - } - //LinksetRoot.PhysShape.ptr, newShape.ptr, displacementPos, displacementRot - internal static void AddChildShapeToCompoundShape2(object pCShape, object paddShape, Vector3 displacementPos, Quaternion displacementRot) - { - IndexedMatrix relativeTransform = new IndexedMatrix(); - var compoundshape = pCShape as CompoundShape; - var addshape = paddShape as CollisionShape; - - relativeTransform._origin = new IndexedVector3(displacementPos.X, displacementPos.Y, displacementPos.Z); - relativeTransform.SetRotation(new IndexedQuaternion(displacementRot.X,displacementRot.Y,displacementRot.Z,displacementRot.W)); - compoundshape.AddChildShape(ref relativeTransform, addshape); - - } - - internal static object RemoveChildShapeFromCompoundShapeIndex2(object pCShape, int pii) - { - var compoundshape = pCShape as CompoundShape; - CollisionShape ret = null; - ret = compoundshape.GetChildShape(pii); - compoundshape.RemoveChildShapeByIndex(pii); - return ret; - } - - internal static object CreateGroundPlaneShape2(uint pLocalId, float pheight, float pcollisionMargin) - { - StaticPlaneShape m_planeshape = new StaticPlaneShape(new IndexedVector3(0,0,1),(int)pheight ); - m_planeshape.SetMargin(pcollisionMargin); - m_planeshape.SetUserPointer(pLocalId); - return m_planeshape; - } - - internal static object CreateHingeConstraint2(object pWorld, object pBody1, object ppBody2, Vector3 ppivotInA, Vector3 ppivotInB, Vector3 paxisInA, Vector3 paxisInB, bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies) - { - HingeConstraint constrain = null; - var rb1 = pBody1 as RigidBody; - var rb2 = ppBody2 as RigidBody; - if (rb1 != null && rb2 != null) - { - IndexedVector3 pivotInA = new IndexedVector3(ppivotInA.X, ppivotInA.Y, ppivotInA.Z); - IndexedVector3 pivotInB = new IndexedVector3(ppivotInB.X, ppivotInB.Y, ppivotInB.Z); - IndexedVector3 axisInA = new IndexedVector3(paxisInA.X, paxisInA.Y, paxisInA.Z); - IndexedVector3 axisInB = new IndexedVector3(paxisInB.X, paxisInB.Y, paxisInB.Z); - var world = pWorld as DiscreteDynamicsWorld; - world.AddConstraint(constrain, pdisableCollisionsBetweenLinkedBodies); - } - return constrain; - } - - internal static bool ReleaseHeightMapInfo2(object pMapInfo) - { - if (pMapInfo != null) - { - BulletHeightMapInfo mapinfo = pMapInfo as BulletHeightMapInfo; - if (mapinfo.heightMap != null) - mapinfo.heightMap = null; - - - } - return true; - } - - internal static object CreateHullShape2(object pWorld, int pHullCount, float[] pConvHulls) - { - CompoundShape compoundshape = new CompoundShape(false); - var world = pWorld as DiscreteDynamicsWorld; - - - compoundshape.SetMargin(world.WorldSettings.Params.collisionMargin); - int ii = 1; - - for (int i = 0; i < pHullCount; i++) - { - int vertexCount = (int) pConvHulls[ii]; - - IndexedVector3 centroid = new IndexedVector3(pConvHulls[ii + 1], pConvHulls[ii + 2], pConvHulls[ii + 3]); - IndexedMatrix childTrans = IndexedMatrix.Identity; - childTrans._origin = centroid; - - List virts = new List(); - int ender = ((ii + 4) + (vertexCount*3)); - for (int iii = ii + 4; iii < ender; iii+=3) - { - - virts.Add(new IndexedVector3(pConvHulls[iii], pConvHulls[iii + 1], pConvHulls[iii +2])); - } - ConvexHullShape convexShape = new ConvexHullShape(virts, vertexCount); - convexShape.SetMargin(world.WorldSettings.Params.collisionMargin); - compoundshape.AddChildShape(ref childTrans, convexShape); - ii += (vertexCount*3 + 4); - } - - - return compoundshape; - } - - internal static object CreateMeshShape2(object pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats) - { - //DumpRaw(indices,verticesAsFloats,pIndicesCount,pVerticesCount); - - for (int iter = 0; iter < pVerticesCount; iter++) - { - if (verticesAsFloats[iter] > 0 && verticesAsFloats[iter] < 0.0001) verticesAsFloats[iter] = 0; - if (verticesAsFloats[iter] < 0 && verticesAsFloats[iter] > -0.0001) verticesAsFloats[iter] = 0; - } - - ObjectArray indicesarr = new ObjectArray(indices); - ObjectArray vertices = new ObjectArray(verticesAsFloats); - DumpRaw(indicesarr,vertices,pIndicesCount,pVerticesCount); - var world = pWorld as DiscreteDynamicsWorld; - IndexedMesh mesh = new IndexedMesh(); - mesh.m_indexType = PHY_ScalarType.PHY_INTEGER; - mesh.m_numTriangles = pIndicesCount/3; - mesh.m_numVertices = pVerticesCount; - mesh.m_triangleIndexBase = indicesarr; - mesh.m_vertexBase = vertices; - mesh.m_vertexStride = 3; - mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT; - mesh.m_triangleIndexStride = 3; - - TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray(); - tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER); - BvhTriangleMeshShape meshShape = new BvhTriangleMeshShape(tribuilder, true,true); - meshShape.SetMargin(world.WorldSettings.Params.collisionMargin); - // world.UpdateSingleAabb(meshShape); - return meshShape; - - } - public static void DumpRaw(ObjectArrayindices, ObjectArray vertices, int pIndicesCount,int pVerticesCount ) - { - - String fileName = "objTest3.raw"; - String completePath = System.IO.Path.Combine(Util.configDir(), fileName); - StreamWriter sw = new StreamWriter(completePath); - IndexedMesh mesh = new IndexedMesh(); - - mesh.m_indexType = PHY_ScalarType.PHY_INTEGER; - mesh.m_numTriangles = pIndicesCount / 3; - mesh.m_numVertices = pVerticesCount; - mesh.m_triangleIndexBase = indices; - mesh.m_vertexBase = vertices; - mesh.m_vertexStride = 3; - mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT; - mesh.m_triangleIndexStride = 3; - - TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray(); - tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER); - - - - for (int i = 0; i < pVerticesCount; i++) - { - - string s = vertices[indices[i * 3]].ToString("0.0000"); - s += " " + vertices[indices[i * 3 + 1]].ToString("0.0000"); - s += " " + vertices[indices[i * 3 + 2]].ToString("0.0000"); - - sw.Write(s + "\n"); - } - - sw.Close(); - } - public static void DumpRaw(int[] indices, float[] vertices, int pIndicesCount, int pVerticesCount) - { - - String fileName = "objTest6.raw"; - String completePath = System.IO.Path.Combine(Util.configDir(), fileName); - StreamWriter sw = new StreamWriter(completePath); - IndexedMesh mesh = new IndexedMesh(); - - mesh.m_indexType = PHY_ScalarType.PHY_INTEGER; - mesh.m_numTriangles = pIndicesCount / 3; - mesh.m_numVertices = pVerticesCount; - mesh.m_triangleIndexBase = indices; - mesh.m_vertexBase = vertices; - mesh.m_vertexStride = 3; - mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT; - mesh.m_triangleIndexStride = 3; - - TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray(); - tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER); - - - sw.WriteLine("Indices"); - sw.WriteLine(string.Format("int[] indices = new int[{0}];",pIndicesCount)); - for (int iter = 0; iter < indices.Length; iter++) - { - sw.WriteLine(string.Format("indices[{0}]={1};",iter,indices[iter])); - } - sw.WriteLine("VerticesFloats"); - sw.WriteLine(string.Format("float[] vertices = new float[{0}];", pVerticesCount)); - for (int iter = 0; iter < vertices.Length; iter++) - { - sw.WriteLine(string.Format("Vertices[{0}]={1};", iter, vertices[iter].ToString("0.0000"))); - } - - // for (int i = 0; i < pVerticesCount; i++) - // { - // - // string s = vertices[indices[i * 3]].ToString("0.0000"); - // s += " " + vertices[indices[i * 3 + 1]].ToString("0.0000"); - // s += " " + vertices[indices[i * 3 + 2]].ToString("0.0000"); - // - // sw.Write(s + "\n"); - //} - - sw.Close(); - } - //PhysicsScene.World.ptr, m_mapInfo.ID, m_mapInfo.minCoords, m_mapInfo.maxCoords, m_mapInfo.heightMap, PhysicsScene.Params.terrainCollisionMargin - internal static object CreateHeightMapInfo2(object pWorld, uint pId, Vector3 pminCoords, Vector3 pmaxCoords, float[] pheightMap, float pCollisionMargin) - { - BulletHeightMapInfo mapInfo = new BulletHeightMapInfo(pId, pheightMap, null); - mapInfo.heightMap = null; - mapInfo.minCoords = pminCoords; - mapInfo.maxCoords = pmaxCoords; - mapInfo.sizeX = (int) (pmaxCoords.X - pminCoords.X); - mapInfo.sizeY = (int) (pmaxCoords.Y - pminCoords.Y); - mapInfo.ID = pId; - mapInfo.minZ = pminCoords.Z; - mapInfo.maxZ = pmaxCoords.Z; - mapInfo.collisionMargin = pCollisionMargin; - if (mapInfo.minZ == mapInfo.maxZ) - mapInfo.minZ -= 0.2f; - mapInfo.heightMap = pheightMap; - - return mapInfo; - - } - - internal static object CreateTerrainShape2(object pMapInfo) - { - BulletHeightMapInfo mapinfo = pMapInfo as BulletHeightMapInfo; - const int upAxis = 2; - const float scaleFactor = 1.0f; - HeightfieldTerrainShape terrainShape = new HeightfieldTerrainShape((int)mapinfo.sizeX, (int)mapinfo.sizeY, - mapinfo.heightMap, scaleFactor, - mapinfo.minZ, mapinfo.maxZ, upAxis, - false); - terrainShape.SetMargin(mapinfo.collisionMargin + 0.5f); - terrainShape.SetUseDiamondSubdivision(true); - terrainShape.SetUserPointer(mapinfo.ID); - return terrainShape; - } - - internal static bool TranslationalLimitMotor2(object pConstraint, float ponOff, float targetVelocity, float maxMotorForce) - { - TypedConstraint tconstrain = pConstraint as TypedConstraint; - bool onOff = ponOff != 0; - bool ret = false; - - switch (tconstrain.GetConstraintType()) - { - case TypedConstraintType.D6_CONSTRAINT_TYPE: - Generic6DofConstraint constrain = pConstraint as Generic6DofConstraint; - constrain.GetTranslationalLimitMotor().m_enableMotor[0] = onOff; - constrain.GetTranslationalLimitMotor().m_targetVelocity[0] = targetVelocity; - constrain.GetTranslationalLimitMotor().m_maxMotorForce[0] = maxMotorForce; - ret = true; - break; - } - - - return ret; - - } - - internal static int PhysicsStep2(object pWorld, float timeStep, int m_maxSubSteps, float m_fixedTimeStep, out int updatedEntityCount, out List updatedEntities, out int collidersCount, out Listcolliders) - { - int epic = PhysicsStepint2(pWorld, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out updatedEntities, - out collidersCount, out colliders); - return epic; - } - - private static int PhysicsStepint2(object pWorld,float timeStep, int m_maxSubSteps, float m_fixedTimeStep, out int updatedEntityCount, out List updatedEntities, out int collidersCount, out List colliders) - { - int numSimSteps = 0; - - - //if (updatedEntities is null) - // updatedEntities = new List(); - - //if (colliders is null) - // colliders = new List(); - - - if (pWorld is DiscreteDynamicsWorld) - { - DiscreteDynamicsWorld world = pWorld as DiscreteDynamicsWorld; - - numSimSteps = world.StepSimulation(timeStep, m_maxSubSteps, m_fixedTimeStep); - int updates = 0; - - updatedEntityCount = world.UpdatedObjects.Count; - updatedEntities = new List(world.UpdatedObjects); - updatedEntityCount = updatedEntities.Count; - world.UpdatedObjects.Clear(); - - - collidersCount = world.UpdatedCollisions.Count; - colliders = new List(world.UpdatedCollisions); - - world.UpdatedCollisions.Clear(); - m_collisionsThisFrame = 0; - int numManifolds = world.GetDispatcher().GetNumManifolds(); - for (int j = 0; j < numManifolds; j++) - { - PersistentManifold contactManifold = world.GetDispatcher().GetManifoldByIndexInternal(j); - int numContacts = contactManifold.GetNumContacts(); - if (numContacts == 0) - continue; - - CollisionObject objA = contactManifold.GetBody0() as CollisionObject; - CollisionObject objB = contactManifold.GetBody1() as CollisionObject; - - ManifoldPoint manifoldPoint = contactManifold.GetContactPoint(0); - IndexedVector3 contactPoint = manifoldPoint.GetPositionWorldOnB(); - IndexedVector3 contactNormal = -manifoldPoint.m_normalWorldOnB; // make relative to A - - RecordCollision(world, objA, objB, contactPoint, contactNormal); - m_collisionsThisFrame ++; - if (m_collisionsThisFrame >= 9999999) - break; - - - } - - - } - else - { - //if (updatedEntities is null) - updatedEntities = new List(); - updatedEntityCount = 0; - //if (colliders is null) - colliders = new List(); - collidersCount = 0; - } - return numSimSteps; - } - - private static void RecordCollision(CollisionWorld world,CollisionObject objA, CollisionObject objB, IndexedVector3 contact, IndexedVector3 norm) - { - - IndexedVector3 contactNormal = norm; - if ((objA.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0 && - (objB.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0) - { - return; - } - uint idA = (uint)objA.GetUserPointer(); - uint idB = (uint)objB.GetUserPointer(); - if (idA > idB) - { - uint temp = idA; - idA = idB; - idB = temp; - contactNormal = -contactNormal; - } - - ulong collisionID = ((ulong) idA << 32) | idB; - - BulletXNA.CollisionDesc cDesc = new BulletXNA.CollisionDesc() - { - aID = idA, - bID = idB, - point = contact, - normal = contactNormal - }; - world.UpdatedCollisions.Add(cDesc); - m_collisionsThisFrame++; - - - } - private static EntityProperties GetDebugProperties(object pWorld, object pBody) - { - EntityProperties ent = new EntityProperties(); - DiscreteDynamicsWorld world = pWorld as DiscreteDynamicsWorld; - RigidBody body = pBody as RigidBody; - IndexedMatrix transform = body.GetWorldTransform(); - IndexedVector3 LinearVelocity = body.GetInterpolationLinearVelocity(); - IndexedVector3 AngularVelocity = body.GetInterpolationAngularVelocity(); - IndexedQuaternion rotation = transform.GetRotation(); - ent.Acceleration = Vector3.Zero; - ent.ID = (uint)body.GetUserPointer(); - ent.Position = new Vector3(transform._origin.X,transform._origin.Y,transform._origin.Z); - ent.Rotation = new Quaternion(rotation.X,rotation.Y,rotation.Z,rotation.W); - ent.Velocity = new Vector3(LinearVelocity.X, LinearVelocity.Y, LinearVelocity.Z); - ent.RotationalVelocity = new Vector3(AngularVelocity.X, AngularVelocity.Y, AngularVelocity.Z); - return ent; - - - } - - - internal static Vector3 GetLocalScaling2(object pBody) - { - CollisionShape shape = pBody as CollisionShape; - IndexedVector3 scale = shape.GetLocalScaling(); - return new Vector3(scale.X,scale.Y,scale.Z); - } - - internal static bool RayCastGround(object pWorld, Vector3 _RayOrigin, float pRayHeight, object NotMe) - { - DynamicsWorld world = pWorld as DynamicsWorld; - if (world != null) - { - if (NotMe is CollisionObject || NotMe is RigidBody) - { - CollisionObject AvoidBody = NotMe as CollisionObject; - - IndexedVector3 rOrigin = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z); - IndexedVector3 rEnd = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z - pRayHeight); - using ( - ClosestNotMeRayResultCallback rayCallback = new ClosestNotMeRayResultCallback(rOrigin, - rEnd, AvoidBody) - ) - { - world.RayTest(ref rOrigin, ref rEnd, rayCallback); - if (rayCallback.HasHit()) - { - IndexedVector3 hitLocation = rayCallback.m_hitPointWorld; - - } - return rayCallback.HasHit(); - } - } - } - return false; - } -} -} diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BulletSimData.cs b/OpenSim/Region/Physics/BulletSNPlugin/BulletSimData.cs deleted file mode 100644 index f509dc4..0000000 --- a/OpenSim/Region/Physics/BulletSNPlugin/BulletSimData.cs +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using OMV = OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSNPlugin -{ -// Classes to allow some type checking for the API -// These hold pointers to allocated objects in the unmanaged space. - -// The physics engine controller class created at initialization -public struct BulletWorld -{ - public BulletWorld(uint worldId, BSScene bss, object xx) - { - ptr = xx; - worldID = worldId; - physicsScene = bss; - } - public object ptr; - public uint worldID; - // The scene is only in here so very low level routines have a handle to print debug/error messages - public BSScene physicsScene; -} - -// An allocated Bullet btRigidBody -public struct BulletBody -{ - public BulletBody(uint id) : this(id, null) - { - } - public BulletBody(uint id, object xx) - { - ID = id; - ptr = xx; - collisionType = CollisionType.Static; - } - public object ptr; - public uint ID; - public CollisionType collisionType; - - public void Clear() - { - ptr = null; - } - public bool HasPhysicalBody { get { return ptr != null; } } - - // Apply the specificed collision mask into the physical world - public void ApplyCollisionMask() - { - // Should assert the body has been added to the physical world. - // (The collision masks are stored in the collision proxy cache which only exists for - // a collision body that is in the world.) - BulletSimAPI.SetCollisionGroupMask2(ptr, - BulletSimData.CollisionTypeMasks[collisionType].group, - BulletSimData.CollisionTypeMasks[collisionType].mask); - } - - public override string ToString() - { - StringBuilder buff = new StringBuilder(); - buff.Append(""); - return buff.ToString(); - } -} - -public struct BulletShape -{ - public BulletShape(object xx) : this(xx, BSPhysicsShapeType.SHAPE_UNKNOWN) - { - } - public BulletShape(object xx, BSPhysicsShapeType typ) - { - ptr = xx; - type = typ; - shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE; - isNativeShape = false; - } - public object ptr; - public BSPhysicsShapeType type; - public System.UInt64 shapeKey; - public bool isNativeShape; - - public void Clear() - { - ptr = null; - } - public bool HasPhysicalShape { get { return ptr != null; } } - - public override string ToString() - { - StringBuilder buff = new StringBuilder(); - buff.Append(""); - return buff.ToString(); - } -} - -// An allocated Bullet btConstraint -public struct BulletConstraint -{ - public BulletConstraint(object xx) - { - ptr = xx; - } - public object ptr; - - public void Clear() - { - ptr = null; - } - public bool HasPhysicalConstraint { get { return ptr != null; } } -} - -// An allocated HeightMapThing which holds various heightmap info. -// Made a class rather than a struct so there would be only one -// instance of this and C# will pass around pointers rather -// than making copies. -public class BulletHeightMapInfo -{ - public BulletHeightMapInfo(uint id, float[] hm, object xx) { - ID = id; - Ptr = xx; - heightMap = hm; - terrainRegionBase = OMV.Vector3.Zero; - minCoords = new OMV.Vector3(100f, 100f, 25f); - maxCoords = new OMV.Vector3(101f, 101f, 26f); - minZ = maxZ = 0f; - sizeX = sizeY = 256f; - } - public uint ID; - public object Ptr; - public float[] heightMap; - public OMV.Vector3 terrainRegionBase; - public OMV.Vector3 minCoords; - public OMV.Vector3 maxCoords; - public float sizeX, sizeY; - public float minZ, maxZ; - public BulletShape terrainShape; - public BulletBody terrainBody; - - public float collisionMargin { get; set; } -} - -// The general class of collsion object. -public enum CollisionType -{ - Avatar, - Groundplane, - Terrain, - Static, - Dynamic, - VolumeDetect, - // Linkset, // A linkset should be either Static or Dynamic - LinksetChild, - Unknown -}; - -// Hold specification of group and mask collision flags for a CollisionType -public struct CollisionTypeFilterGroup -{ - public CollisionTypeFilterGroup(CollisionType t, uint g, uint m) - { - type = t; - group = g; - mask = m; - } - public CollisionType type; - public uint group; - public uint mask; -}; - - /* NOTE: old definitions kept for reference. Delete when things are working. - // The collsion filters and masked are defined in one place -- don't want them scattered - AvatarGroup = BCharacterGroup, - AvatarMask = BAllGroup, - ObjectGroup = BSolidGroup, - ObjectMask = BAllGroup, - StaticObjectGroup = BStaticGroup, - StaticObjectMask = AvatarGroup | ObjectGroup, // static things don't interact with much - LinksetGroup = BLinksetGroup, - LinksetMask = BAllGroup, - LinksetChildGroup = BLinksetChildGroup, - LinksetChildMask = BNoneGroup, // Linkset children disappear from the world - VolumeDetectGroup = BSensorTrigger, - VolumeDetectMask = ~BSensorTrigger, - TerrainGroup = BTerrainGroup, - TerrainMask = BAllGroup & ~BStaticGroup, // static objects on the ground don't collide - GroundPlaneGroup = BGroundPlaneGroup, - GroundPlaneMask = BAllGroup - */ - -public static class BulletSimData -{ - -// Map of collisionTypes to flags for collision groups and masks. -// As mentioned above, don't use the CollisionFilterGroups definitions directly in the code -// but, instead, use references to this dictionary. Finding and debugging -// collision flag problems will be made easier. -public static Dictionary CollisionTypeMasks - = new Dictionary() -{ - { CollisionType.Avatar, - new CollisionTypeFilterGroup(CollisionType.Avatar, - (uint)CollisionFilterGroups.BCharacterGroup, - (uint)CollisionFilterGroups.BAllGroup) - }, - { CollisionType.Groundplane, - new CollisionTypeFilterGroup(CollisionType.Groundplane, - (uint)CollisionFilterGroups.BGroundPlaneGroup, - (uint)CollisionFilterGroups.BAllGroup) - }, - { CollisionType.Terrain, - new CollisionTypeFilterGroup(CollisionType.Terrain, - (uint)CollisionFilterGroups.BTerrainGroup, - (uint)(CollisionFilterGroups.BAllGroup & ~CollisionFilterGroups.BStaticGroup)) - }, - { CollisionType.Static, - new CollisionTypeFilterGroup(CollisionType.Static, - (uint)CollisionFilterGroups.BStaticGroup, - (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup)) - }, - { CollisionType.Dynamic, - new CollisionTypeFilterGroup(CollisionType.Dynamic, - (uint)CollisionFilterGroups.BSolidGroup, - (uint)(CollisionFilterGroups.BAllGroup)) - }, - { CollisionType.VolumeDetect, - new CollisionTypeFilterGroup(CollisionType.VolumeDetect, - (uint)CollisionFilterGroups.BSensorTrigger, - (uint)(~CollisionFilterGroups.BSensorTrigger)) - }, - { CollisionType.LinksetChild, - new CollisionTypeFilterGroup(CollisionType.LinksetChild, - (uint)CollisionFilterGroups.BTerrainGroup, - (uint)(CollisionFilterGroups.BNoneGroup)) - }, -}; - -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs deleted file mode 100755 index 8c6e7d6..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs +++ /dev/null @@ -1,1839 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Security; -using System.Text; - -using OpenSim.Framework; - -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public sealed class BSAPIUnman : BSAPITemplate -{ - -private sealed class BulletWorldUnman : BulletWorld -{ - public IntPtr ptr; - public BulletWorldUnman(uint id, BSScene physScene, IntPtr xx) - : base(id, physScene) - { - ptr = xx; - } -} - -private sealed class BulletBodyUnman : BulletBody -{ - public IntPtr ptr; - public BulletBodyUnman(uint id, IntPtr xx) - : base(id) - { - ptr = xx; - } - public override bool HasPhysicalBody - { - get { return ptr != IntPtr.Zero; } - } - public override void Clear() - { - ptr = IntPtr.Zero; - } - public override string AddrString - { - get { return ptr.ToString("X"); } - } -} - -private sealed class BulletShapeUnman : BulletShape -{ - public IntPtr ptr; - public BulletShapeUnman(IntPtr xx, BSPhysicsShapeType typ) - : base() - { - ptr = xx; - type = typ; - } - public override bool HasPhysicalShape - { - get { return ptr != IntPtr.Zero; } - } - public override void Clear() - { - ptr = IntPtr.Zero; - } - public override BulletShape Clone() - { - return new BulletShapeUnman(ptr, type); - } - public override bool ReferenceSame(BulletShape other) - { - BulletShapeUnman otheru = other as BulletShapeUnman; - return (otheru != null) && (this.ptr == otheru.ptr); - - } - public override string AddrString - { - get { return ptr.ToString("X"); } - } -} -private sealed class BulletConstraintUnman : BulletConstraint -{ - public BulletConstraintUnman(IntPtr xx) : base() - { - ptr = xx; - } - public IntPtr ptr; - - public override void Clear() - { - ptr = IntPtr.Zero; - } - public override bool HasPhysicalConstraint { get { return ptr != IntPtr.Zero; } } - - // Used for log messages for a unique display of the memory/object allocated to this instance - public override string AddrString - { - get { return ptr.ToString("X"); } - } -} - -// We pin the memory passed between the managed and unmanaged code. -GCHandle m_paramsHandle; -private GCHandle m_collisionArrayPinnedHandle; -private GCHandle m_updateArrayPinnedHandle; - -// Handle to the callback used by the unmanaged code to call into the managed code. -// Used for debug logging. -// Need to store the handle in a persistant variable so it won't be freed. -private BSAPICPP.DebugLogCallback m_DebugLogCallbackHandle; - -private BSScene PhysicsScene { get; set; } - -public override string BulletEngineName { get { return "BulletUnmanaged"; } } -public override string BulletEngineVersion { get; protected set; } - -public BSAPIUnman(string paramName, BSScene physScene) -{ - PhysicsScene = physScene; - - // Do something fancy with the paramName to get the right DLL implementation - // like "Bullet-2.80-OpenCL-Intel" loading the version for Intel based OpenCL implementation, etc. - if (Util.IsWindows()) - Util.LoadArchSpecificWindowsDll("BulletSim.dll"); - // If not Windows, loading is performed by the - // Mono loader as specified in - // "bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config". -} - -// Initialization and simulation -public override BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms, - int maxCollisions, ref CollisionDesc[] collisionArray, - int maxUpdates, ref EntityProperties[] updateArray - ) -{ - // Pin down the memory that will be used to pass object collisions and updates back from unmanaged code - m_paramsHandle = GCHandle.Alloc(parms, GCHandleType.Pinned); - m_collisionArrayPinnedHandle = GCHandle.Alloc(collisionArray, GCHandleType.Pinned); - m_updateArrayPinnedHandle = GCHandle.Alloc(updateArray, GCHandleType.Pinned); - - // If Debug logging level, enable logging from the unmanaged code - m_DebugLogCallbackHandle = null; - if (BSScene.m_log.IsDebugEnabled || PhysicsScene.PhysicsLogging.Enabled) - { - BSScene.m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", BSScene.LogHeader); - if (PhysicsScene.PhysicsLogging.Enabled) - // The handle is saved in a variable to make sure it doesn't get freed after this call - m_DebugLogCallbackHandle = new BSAPICPP.DebugLogCallback(BulletLoggerPhysLog); - else - m_DebugLogCallbackHandle = new BSAPICPP.DebugLogCallback(BulletLogger); - } - - // Get the version of the DLL - // TODO: this doesn't work yet. Something wrong with marshaling the returned string. - // BulletEngineVersion = BulletSimAPI.GetVersion2(); - BulletEngineVersion = ""; - - // Call the unmanaged code with the buffers and other information - return new BulletWorldUnman(0, PhysicsScene, BSAPICPP.Initialize2(maxPosition, m_paramsHandle.AddrOfPinnedObject(), - maxCollisions, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), - maxUpdates, m_updateArrayPinnedHandle.AddrOfPinnedObject(), - m_DebugLogCallbackHandle)); - -} - -// Called directly from unmanaged code so don't do much -private void BulletLogger(string msg) -{ - BSScene.m_log.Debug("[BULLETS UNMANAGED]:" + msg); -} - -// Called directly from unmanaged code so don't do much -private void BulletLoggerPhysLog(string msg) -{ - PhysicsScene.DetailLog("[BULLETS UNMANAGED]:" + msg); -} - -public override int PhysicsStep(BulletWorld world, float timeStep, int maxSubSteps, float fixedTimeStep, - out int updatedEntityCount, out int collidersCount) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - return BSAPICPP.PhysicsStep2(worldu.ptr, timeStep, maxSubSteps, fixedTimeStep, out updatedEntityCount, out collidersCount); -} - -public override void Shutdown(BulletWorld world) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BSAPICPP.Shutdown2(worldu.ptr); -} - -public override bool PushUpdate(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.PushUpdate2(bodyu.ptr); -} - -public override bool UpdateParameter(BulletWorld world, uint localID, String parm, float value) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - return BSAPICPP.UpdateParameter2(worldu.ptr, localID, parm, value); -} - -// ===================================================================================== -// Mesh, hull, shape and body creation helper routines -public override BulletShape CreateMeshShape(BulletWorld world, - int indicesCount, int[] indices, - int verticesCount, float[] vertices) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - return new BulletShapeUnman( - BSAPICPP.CreateMeshShape2(worldu.ptr, indicesCount, indices, verticesCount, vertices), - BSPhysicsShapeType.SHAPE_MESH); -} - -public override BulletShape CreateHullShape(BulletWorld world, int hullCount, float[] hulls) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - return new BulletShapeUnman( - BSAPICPP.CreateHullShape2(worldu.ptr, hullCount, hulls), - BSPhysicsShapeType.SHAPE_HULL); -} - -public override BulletShape BuildHullShapeFromMesh(BulletWorld world, BulletShape meshShape) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BulletShapeUnman shapeu = meshShape as BulletShapeUnman; - return new BulletShapeUnman( - BSAPICPP.BuildHullShapeFromMesh2(worldu.ptr, shapeu.ptr), - BSPhysicsShapeType.SHAPE_HULL); -} - -public override BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - return new BulletShapeUnman(BSAPICPP.BuildNativeShape2(worldu.ptr, shapeData), shapeData.Type); -} - -public override bool IsNativeShape(BulletShape shape) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - if (shapeu != null && shapeu.HasPhysicalShape) - return BSAPICPP.IsNativeShape2(shapeu.ptr); - return false; -} - -public override void SetShapeCollisionMargin(BulletShape shape, float margin) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - if (shapeu != null && shapeu.HasPhysicalShape) - BSAPICPP.SetShapeCollisionMargin2(shapeu.ptr, margin); -} - -public override BulletShape BuildCapsuleShape(BulletWorld world, float radius, float height, Vector3 scale) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - return new BulletShapeUnman( - BSAPICPP.BuildCapsuleShape2(worldu.ptr, radius, height, scale), - BSPhysicsShapeType.SHAPE_CAPSULE); -} - -public override BulletShape CreateCompoundShape(BulletWorld world, bool enableDynamicAabbTree) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - return new BulletShapeUnman( - BSAPICPP.CreateCompoundShape2(worldu.ptr, enableDynamicAabbTree), - BSPhysicsShapeType.SHAPE_COMPOUND); - -} - -public override int GetNumberOfCompoundChildren(BulletShape shape) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - if (shapeu != null && shapeu.HasPhysicalShape) - return BSAPICPP.GetNumberOfCompoundChildren2(shapeu.ptr); - return 0; -} - -public override void AddChildShapeToCompoundShape(BulletShape shape, BulletShape addShape, Vector3 pos, Quaternion rot) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - BulletShapeUnman addShapeu = addShape as BulletShapeUnman; - BSAPICPP.AddChildShapeToCompoundShape2(shapeu.ptr, addShapeu.ptr, pos, rot); -} - -public override BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape shape, int indx) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - return new BulletShapeUnman(BSAPICPP.GetChildShapeFromCompoundShapeIndex2(shapeu.ptr, indx), BSPhysicsShapeType.SHAPE_UNKNOWN); -} - -public override BulletShape RemoveChildShapeFromCompoundShapeIndex(BulletShape shape, int indx) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - return new BulletShapeUnman(BSAPICPP.RemoveChildShapeFromCompoundShapeIndex2(shapeu.ptr, indx), BSPhysicsShapeType.SHAPE_UNKNOWN); -} - -public override void RemoveChildShapeFromCompoundShape(BulletShape shape, BulletShape removeShape) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - BulletShapeUnman removeShapeu = removeShape as BulletShapeUnman; - BSAPICPP.RemoveChildShapeFromCompoundShape2(shapeu.ptr, removeShapeu.ptr); -} - -public override void RecalculateCompoundShapeLocalAabb(BulletShape shape) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - BSAPICPP.RecalculateCompoundShapeLocalAabb2(shapeu.ptr); -} - -public override BulletShape DuplicateCollisionShape(BulletWorld world, BulletShape srcShape, uint id) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BulletShapeUnman srcShapeu = srcShape as BulletShapeUnman; - return new BulletShapeUnman(BSAPICPP.DuplicateCollisionShape2(worldu.ptr, srcShapeu.ptr, id), srcShape.type); -} - -public override bool DeleteCollisionShape(BulletWorld world, BulletShape shape) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BulletShapeUnman shapeu = shape as BulletShapeUnman; - return BSAPICPP.DeleteCollisionShape2(worldu.ptr, shapeu.ptr); -} - -public override CollisionObjectTypes GetBodyType(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return (CollisionObjectTypes)BSAPICPP.GetBodyType2(bodyu.ptr); -} - -public override BulletBody CreateBodyFromShape(BulletWorld world, BulletShape shape, uint id, Vector3 pos, Quaternion rot) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BulletShapeUnman shapeu = shape as BulletShapeUnman; - return new BulletBodyUnman(id, BSAPICPP.CreateBodyFromShape2(worldu.ptr, shapeu.ptr, id, pos, rot)); -} - -public override BulletBody CreateBodyWithDefaultMotionState(BulletShape shape, uint id, Vector3 pos, Quaternion rot) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - return new BulletBodyUnman(id, BSAPICPP.CreateBodyWithDefaultMotionState2(shapeu.ptr, id, pos, rot)); -} - -public override BulletBody CreateGhostFromShape(BulletWorld world, BulletShape shape, uint id, Vector3 pos, Quaternion rot) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BulletShapeUnman shapeu = shape as BulletShapeUnman; - return new BulletBodyUnman(id, BSAPICPP.CreateGhostFromShape2(worldu.ptr, shapeu.ptr, id, pos, rot)); -} - -public override void DestroyObject(BulletWorld world, BulletBody obj) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.DestroyObject2(worldu.ptr, bodyu.ptr); -} - -// ===================================================================================== -// Terrain creation and helper routines -public override BulletShape CreateGroundPlaneShape(uint id, float height, float collisionMargin) -{ - return new BulletShapeUnman(BSAPICPP.CreateGroundPlaneShape2(id, height, collisionMargin), BSPhysicsShapeType.SHAPE_GROUNDPLANE); -} - -public override BulletShape CreateTerrainShape(uint id, Vector3 size, float minHeight, float maxHeight, float[] heightMap, - float scaleFactor, float collisionMargin) -{ - return new BulletShapeUnman(BSAPICPP.CreateTerrainShape2(id, size, minHeight, maxHeight, heightMap, scaleFactor, collisionMargin), - BSPhysicsShapeType.SHAPE_TERRAIN); -} - -// ===================================================================================== -// Constraint creation and helper routines -public override BulletConstraint Create6DofConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2, - Vector3 frame1loc, Quaternion frame1rot, - Vector3 frame2loc, Quaternion frame2rot, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BulletBodyUnman bodyu1 = obj1 as BulletBodyUnman; - BulletBodyUnman bodyu2 = obj2 as BulletBodyUnman; - return new BulletConstraintUnman(BSAPICPP.Create6DofConstraint2(worldu.ptr, bodyu1.ptr, bodyu2.ptr, frame1loc, frame1rot, - frame2loc, frame2rot, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); -} - -public override BulletConstraint Create6DofConstraintToPoint(BulletWorld world, BulletBody obj1, BulletBody obj2, - Vector3 joinPoint, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BulletBodyUnman bodyu1 = obj1 as BulletBodyUnman; - BulletBodyUnman bodyu2 = obj2 as BulletBodyUnman; - return new BulletConstraintUnman(BSAPICPP.Create6DofConstraintToPoint2(worldu.ptr, bodyu1.ptr, bodyu2.ptr, - joinPoint, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); -} - -public override BulletConstraint CreateHingeConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2, - Vector3 pivotinA, Vector3 pivotinB, - Vector3 axisInA, Vector3 axisInB, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BulletBodyUnman bodyu1 = obj1 as BulletBodyUnman; - BulletBodyUnman bodyu2 = obj2 as BulletBodyUnman; - return new BulletConstraintUnman(BSAPICPP.CreateHingeConstraint2(worldu.ptr, bodyu1.ptr, bodyu2.ptr, - pivotinA, pivotinB, axisInA, axisInB, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); -} - -public override void SetConstraintEnable(BulletConstraint constrain, float numericTrueFalse) -{ - BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; - BSAPICPP.SetConstraintEnable2(constrainu.ptr, numericTrueFalse); -} - -public override void SetConstraintNumSolverIterations(BulletConstraint constrain, float iterations) -{ - BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; - BSAPICPP.SetConstraintNumSolverIterations2(constrainu.ptr, iterations); -} - -public override bool SetFrames(BulletConstraint constrain, - Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) -{ - BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; - return BSAPICPP.SetFrames2(constrainu.ptr, frameA, frameArot, frameB, frameBrot); -} - -public override bool SetLinearLimits(BulletConstraint constrain, Vector3 low, Vector3 hi) -{ - BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; - return BSAPICPP.SetLinearLimits2(constrainu.ptr, low, hi); -} - -public override bool SetAngularLimits(BulletConstraint constrain, Vector3 low, Vector3 hi) -{ - BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; - return BSAPICPP.SetAngularLimits2(constrainu.ptr, low, hi); -} - -public override bool UseFrameOffset(BulletConstraint constrain, float enable) -{ - BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; - return BSAPICPP.UseFrameOffset2(constrainu.ptr, enable); -} - -public override bool TranslationalLimitMotor(BulletConstraint constrain, float enable, float targetVel, float maxMotorForce) -{ - BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; - return BSAPICPP.TranslationalLimitMotor2(constrainu.ptr, enable, targetVel, maxMotorForce); -} - -public override bool SetBreakingImpulseThreshold(BulletConstraint constrain, float threshold) -{ - BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; - return BSAPICPP.SetBreakingImpulseThreshold2(constrainu.ptr, threshold); -} - -public override bool CalculateTransforms(BulletConstraint constrain) -{ - BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; - return BSAPICPP.CalculateTransforms2(constrainu.ptr); -} - -public override bool SetConstraintParam(BulletConstraint constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis) -{ - BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; - return BSAPICPP.SetConstraintParam2(constrainu.ptr, paramIndex, value, axis); -} - -public override bool DestroyConstraint(BulletWorld world, BulletConstraint constrain) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; - return BSAPICPP.DestroyConstraint2(worldu.ptr, constrainu.ptr); -} - -// ===================================================================================== -// btCollisionWorld entries -public override void UpdateSingleAabb(BulletWorld world, BulletBody obj) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.UpdateSingleAabb2(worldu.ptr, bodyu.ptr); -} - -public override void UpdateAabbs(BulletWorld world) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BSAPICPP.UpdateAabbs2(worldu.ptr); -} - -public override bool GetForceUpdateAllAabbs(BulletWorld world) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - return BSAPICPP.GetForceUpdateAllAabbs2(worldu.ptr); -} - -public override void SetForceUpdateAllAabbs(BulletWorld world, bool force) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BSAPICPP.SetForceUpdateAllAabbs2(worldu.ptr, force); -} - -// ===================================================================================== -// btDynamicsWorld entries -public override bool AddObjectToWorld(BulletWorld world, BulletBody obj) -{ - // Bullet resets several variables when an object is added to the world. - // Gravity is reset to world default depending on the static/dynamic - // type. Of course, the collision flags in the broadphase proxy are initialized to default. - BulletWorldUnman worldu = world as BulletWorldUnman; - BulletBodyUnman bodyu = obj as BulletBodyUnman; - - Vector3 origGrav = BSAPICPP.GetGravity2(bodyu.ptr); - - bool ret = BSAPICPP.AddObjectToWorld2(worldu.ptr, bodyu.ptr); - - if (ret) - { - BSAPICPP.SetGravity2(bodyu.ptr, origGrav); - obj.ApplyCollisionMask(world.physicsScene); - } - return ret; -} - -public override bool RemoveObjectFromWorld(BulletWorld world, BulletBody obj) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.RemoveObjectFromWorld2(worldu.ptr, bodyu.ptr); -} - -public override bool AddConstraintToWorld(BulletWorld world, BulletConstraint constrain, bool disableCollisionsBetweenLinkedObjects) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; - return BSAPICPP.AddConstraintToWorld2(worldu.ptr, constrainu.ptr, disableCollisionsBetweenLinkedObjects); -} - -public override bool RemoveConstraintFromWorld(BulletWorld world, BulletConstraint constrain) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; - return BSAPICPP.RemoveConstraintFromWorld2(worldu.ptr, constrainu.ptr); -} -// ===================================================================================== -// btCollisionObject entries -public override Vector3 GetAnisotripicFriction(BulletConstraint constrain) -{ - BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; - return BSAPICPP.GetAnisotripicFriction2(constrainu.ptr); -} - -public override Vector3 SetAnisotripicFriction(BulletConstraint constrain, Vector3 frict) -{ - BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; - return BSAPICPP.SetAnisotripicFriction2(constrainu.ptr, frict); -} - -public override bool HasAnisotripicFriction(BulletConstraint constrain) -{ - BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; - return BSAPICPP.HasAnisotripicFriction2(constrainu.ptr); -} - -public override void SetContactProcessingThreshold(BulletBody obj, float val) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetContactProcessingThreshold2(bodyu.ptr, val); -} - -public override float GetContactProcessingThreshold(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetContactProcessingThreshold2(bodyu.ptr); -} - -public override bool IsStaticObject(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.IsStaticObject2(bodyu.ptr); -} - -public override bool IsKinematicObject(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.IsKinematicObject2(bodyu.ptr); -} - -public override bool IsStaticOrKinematicObject(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.IsStaticOrKinematicObject2(bodyu.ptr); -} - -public override bool HasContactResponse(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.HasContactResponse2(bodyu.ptr); -} - -public override void SetCollisionShape(BulletWorld world, BulletBody obj, BulletShape shape) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BulletShapeUnman shapeu = shape as BulletShapeUnman; - if (worldu != null && bodyu != null) - { - // Special case to allow the caller to zero out the reference to any physical shape - if (shapeu != null) - BSAPICPP.SetCollisionShape2(worldu.ptr, bodyu.ptr, shapeu.ptr); - else - BSAPICPP.SetCollisionShape2(worldu.ptr, bodyu.ptr, IntPtr.Zero); - } -} - -public override BulletShape GetCollisionShape(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return new BulletShapeUnman(BSAPICPP.GetCollisionShape2(bodyu.ptr), BSPhysicsShapeType.SHAPE_UNKNOWN); -} - -public override int GetActivationState(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetActivationState2(bodyu.ptr); -} - -public override void SetActivationState(BulletBody obj, int state) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetActivationState2(bodyu.ptr, state); -} - -public override void SetDeactivationTime(BulletBody obj, float dtime) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetDeactivationTime2(bodyu.ptr, dtime); -} - -public override float GetDeactivationTime(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetDeactivationTime2(bodyu.ptr); -} - -public override void ForceActivationState(BulletBody obj, ActivationState state) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.ForceActivationState2(bodyu.ptr, state); -} - -public override void Activate(BulletBody obj, bool forceActivation) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.Activate2(bodyu.ptr, forceActivation); -} - -public override bool IsActive(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.IsActive2(bodyu.ptr); -} - -public override void SetRestitution(BulletBody obj, float val) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetRestitution2(bodyu.ptr, val); -} - -public override float GetRestitution(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetRestitution2(bodyu.ptr); -} - -public override void SetFriction(BulletBody obj, float val) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetFriction2(bodyu.ptr, val); -} - -public override float GetFriction(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetFriction2(bodyu.ptr); -} - -public override Vector3 GetPosition(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetPosition2(bodyu.ptr); -} - -public override Quaternion GetOrientation(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetOrientation2(bodyu.ptr); -} - -public override void SetTranslation(BulletBody obj, Vector3 position, Quaternion rotation) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetTranslation2(bodyu.ptr, position, rotation); -} - - /* -public override IntPtr GetBroadphaseHandle(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetBroadphaseHandle2(bodyu.ptr); -} - -public override void SetBroadphaseHandle(BulletBody obj, IntPtr handle) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetUserPointer2(bodyu.ptr, handle); -} - */ - -public override void SetInterpolationLinearVelocity(BulletBody obj, Vector3 vel) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetInterpolationLinearVelocity2(bodyu.ptr, vel); -} - -public override void SetInterpolationAngularVelocity(BulletBody obj, Vector3 vel) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetInterpolationAngularVelocity2(bodyu.ptr, vel); -} - -public override void SetInterpolationVelocity(BulletBody obj, Vector3 linearVel, Vector3 angularVel) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetInterpolationVelocity2(bodyu.ptr, linearVel, angularVel); -} - -public override float GetHitFraction(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetHitFraction2(bodyu.ptr); -} - -public override void SetHitFraction(BulletBody obj, float val) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetHitFraction2(bodyu.ptr, val); -} - -public override CollisionFlags GetCollisionFlags(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetCollisionFlags2(bodyu.ptr); -} - -public override CollisionFlags SetCollisionFlags(BulletBody obj, CollisionFlags flags) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.SetCollisionFlags2(bodyu.ptr, flags); -} - -public override CollisionFlags AddToCollisionFlags(BulletBody obj, CollisionFlags flags) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.AddToCollisionFlags2(bodyu.ptr, flags); -} - -public override CollisionFlags RemoveFromCollisionFlags(BulletBody obj, CollisionFlags flags) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.RemoveFromCollisionFlags2(bodyu.ptr, flags); -} - -public override float GetCcdMotionThreshold(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetCcdMotionThreshold2(bodyu.ptr); -} - - -public override void SetCcdMotionThreshold(BulletBody obj, float val) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetCcdMotionThreshold2(bodyu.ptr, val); -} - -public override float GetCcdSweptSphereRadius(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetCcdSweptSphereRadius2(bodyu.ptr); -} - -public override void SetCcdSweptSphereRadius(BulletBody obj, float val) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetCcdSweptSphereRadius2(bodyu.ptr, val); -} - -public override IntPtr GetUserPointer(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetUserPointer2(bodyu.ptr); -} - -public override void SetUserPointer(BulletBody obj, IntPtr val) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetUserPointer2(bodyu.ptr, val); -} - -// ===================================================================================== -// btRigidBody entries -public override void ApplyGravity(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.ApplyGravity2(bodyu.ptr); -} - -public override void SetGravity(BulletBody obj, Vector3 val) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetGravity2(bodyu.ptr, val); -} - -public override Vector3 GetGravity(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetGravity2(bodyu.ptr); -} - -public override void SetDamping(BulletBody obj, float lin_damping, float ang_damping) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetDamping2(bodyu.ptr, lin_damping, ang_damping); -} - -public override void SetLinearDamping(BulletBody obj, float lin_damping) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetLinearDamping2(bodyu.ptr, lin_damping); -} - -public override void SetAngularDamping(BulletBody obj, float ang_damping) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetAngularDamping2(bodyu.ptr, ang_damping); -} - -public override float GetLinearDamping(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetLinearDamping2(bodyu.ptr); -} - -public override float GetAngularDamping(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetAngularDamping2(bodyu.ptr); -} - -public override float GetLinearSleepingThreshold(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetLinearSleepingThreshold2(bodyu.ptr); -} - -public override void ApplyDamping(BulletBody obj, float timeStep) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.ApplyDamping2(bodyu.ptr, timeStep); -} - -public override void SetMassProps(BulletBody obj, float mass, Vector3 inertia) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetMassProps2(bodyu.ptr, mass, inertia); -} - -public override Vector3 GetLinearFactor(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetLinearFactor2(bodyu.ptr); -} - -public override void SetLinearFactor(BulletBody obj, Vector3 factor) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetLinearFactor2(bodyu.ptr, factor); -} - -public override void SetCenterOfMassByPosRot(BulletBody obj, Vector3 pos, Quaternion rot) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetCenterOfMassByPosRot2(bodyu.ptr, pos, rot); -} - -// Add a force to the object as if its mass is one. -public override void ApplyCentralForce(BulletBody obj, Vector3 force) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.ApplyCentralForce2(bodyu.ptr, force); -} - -// Set the force being applied to the object as if its mass is one. -public override void SetObjectForce(BulletBody obj, Vector3 force) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetObjectForce2(bodyu.ptr, force); -} - -public override Vector3 GetTotalForce(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetTotalForce2(bodyu.ptr); -} - -public override Vector3 GetTotalTorque(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetTotalTorque2(bodyu.ptr); -} - -public override Vector3 GetInvInertiaDiagLocal(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetInvInertiaDiagLocal2(bodyu.ptr); -} - -public override void SetInvInertiaDiagLocal(BulletBody obj, Vector3 inert) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetInvInertiaDiagLocal2(bodyu.ptr, inert); -} - -public override void SetSleepingThresholds(BulletBody obj, float lin_threshold, float ang_threshold) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetSleepingThresholds2(bodyu.ptr, lin_threshold, ang_threshold); -} - -public override void ApplyTorque(BulletBody obj, Vector3 torque) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.ApplyTorque2(bodyu.ptr, torque); -} - -// Apply force at the given point. Will add torque to the object. -public override void ApplyForce(BulletBody obj, Vector3 force, Vector3 pos) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.ApplyForce2(bodyu.ptr, force, pos); -} - -// Apply impulse to the object. Same as "ApplycentralForce" but force scaled by object's mass. -public override void ApplyCentralImpulse(BulletBody obj, Vector3 imp) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.ApplyCentralImpulse2(bodyu.ptr, imp); -} - -// Apply impulse to the object's torque. Force is scaled by object's mass. -public override void ApplyTorqueImpulse(BulletBody obj, Vector3 imp) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.ApplyTorqueImpulse2(bodyu.ptr, imp); -} - -// Apply impulse at the point given. For is scaled by object's mass and effects both linear and angular forces. -public override void ApplyImpulse(BulletBody obj, Vector3 imp, Vector3 pos) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.ApplyImpulse2(bodyu.ptr, imp, pos); -} - -public override void ClearForces(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.ClearForces2(bodyu.ptr); -} - -public override void ClearAllForces(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.ClearAllForces2(bodyu.ptr); -} - -public override void UpdateInertiaTensor(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.UpdateInertiaTensor2(bodyu.ptr); -} - -public override Vector3 GetLinearVelocity(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetLinearVelocity2(bodyu.ptr); -} - -public override Vector3 GetAngularVelocity(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetAngularVelocity2(bodyu.ptr); -} - -public override void SetLinearVelocity(BulletBody obj, Vector3 vel) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetLinearVelocity2(bodyu.ptr, vel); -} - -public override void SetAngularVelocity(BulletBody obj, Vector3 angularVelocity) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetAngularVelocity2(bodyu.ptr, angularVelocity); -} - -public override Vector3 GetVelocityInLocalPoint(BulletBody obj, Vector3 pos) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetVelocityInLocalPoint2(bodyu.ptr, pos); -} - -public override void Translate(BulletBody obj, Vector3 trans) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.Translate2(bodyu.ptr, trans); -} - -public override void UpdateDeactivation(BulletBody obj, float timeStep) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.UpdateDeactivation2(bodyu.ptr, timeStep); -} - -public override bool WantsSleeping(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.WantsSleeping2(bodyu.ptr); -} - -public override void SetAngularFactor(BulletBody obj, float factor) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetAngularFactor2(bodyu.ptr, factor); -} - -public override void SetAngularFactorV(BulletBody obj, Vector3 factor) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BSAPICPP.SetAngularFactorV2(bodyu.ptr, factor); -} - -public override Vector3 GetAngularFactor(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetAngularFactor2(bodyu.ptr); -} - -public override bool IsInWorld(BulletWorld world, BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.IsInWorld2(bodyu.ptr); -} - -public override void AddConstraintRef(BulletBody obj, BulletConstraint constrain) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; - BSAPICPP.AddConstraintRef2(bodyu.ptr, constrainu.ptr); -} - -public override void RemoveConstraintRef(BulletBody obj, BulletConstraint constrain) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; - BSAPICPP.RemoveConstraintRef2(bodyu.ptr, constrainu.ptr); -} - -public override BulletConstraint GetConstraintRef(BulletBody obj, int index) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return new BulletConstraintUnman(BSAPICPP.GetConstraintRef2(bodyu.ptr, index)); -} - -public override int GetNumConstraintRefs(BulletBody obj) -{ - BulletBodyUnman bodyu = obj as BulletBodyUnman; - return BSAPICPP.GetNumConstraintRefs2(bodyu.ptr); -} - -public override bool SetCollisionGroupMask(BulletBody body, uint filter, uint mask) -{ - BulletBodyUnman bodyu = body as BulletBodyUnman; - return BSAPICPP.SetCollisionGroupMask2(bodyu.ptr, filter, mask); -} - -// ===================================================================================== -// btCollisionShape entries - -public override float GetAngularMotionDisc(BulletShape shape) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - return BSAPICPP.GetAngularMotionDisc2(shapeu.ptr); -} - -public override float GetContactBreakingThreshold(BulletShape shape, float defaultFactor) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - return BSAPICPP.GetContactBreakingThreshold2(shapeu.ptr, defaultFactor); -} - -public override bool IsPolyhedral(BulletShape shape) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - return BSAPICPP.IsPolyhedral2(shapeu.ptr); -} - -public override bool IsConvex2d(BulletShape shape) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - return BSAPICPP.IsConvex2d2(shapeu.ptr); -} - -public override bool IsConvex(BulletShape shape) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - return BSAPICPP.IsConvex2(shapeu.ptr); -} - -public override bool IsNonMoving(BulletShape shape) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - return BSAPICPP.IsNonMoving2(shapeu.ptr); -} - -public override bool IsConcave(BulletShape shape) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - return BSAPICPP.IsConcave2(shapeu.ptr); -} - -public override bool IsCompound(BulletShape shape) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - return BSAPICPP.IsCompound2(shapeu.ptr); -} - -public override bool IsSoftBody(BulletShape shape) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - return BSAPICPP.IsSoftBody2(shapeu.ptr); -} - -public override bool IsInfinite(BulletShape shape) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - return BSAPICPP.IsInfinite2(shapeu.ptr); -} - -public override void SetLocalScaling(BulletShape shape, Vector3 scale) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - BSAPICPP.SetLocalScaling2(shapeu.ptr, scale); -} - -public override Vector3 GetLocalScaling(BulletShape shape) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - return BSAPICPP.GetLocalScaling2(shapeu.ptr); -} - -public override Vector3 CalculateLocalInertia(BulletShape shape, float mass) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - return BSAPICPP.CalculateLocalInertia2(shapeu.ptr, mass); -} - -public override int GetShapeType(BulletShape shape) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - return BSAPICPP.GetShapeType2(shapeu.ptr); -} - -public override void SetMargin(BulletShape shape, float val) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - BSAPICPP.SetMargin2(shapeu.ptr, val); -} - -public override float GetMargin(BulletShape shape) -{ - BulletShapeUnman shapeu = shape as BulletShapeUnman; - return BSAPICPP.GetMargin2(shapeu.ptr); -} - -// ===================================================================================== -// Debugging -public override void DumpRigidBody(BulletWorld world, BulletBody collisionObject) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BulletBodyUnman bodyu = collisionObject as BulletBodyUnman; - BSAPICPP.DumpRigidBody2(worldu.ptr, bodyu.ptr); -} - -public override void DumpCollisionShape(BulletWorld world, BulletShape collisionShape) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BulletShapeUnman shapeu = collisionShape as BulletShapeUnman; - BSAPICPP.DumpCollisionShape2(worldu.ptr, shapeu.ptr); -} - -public override void DumpConstraint(BulletWorld world, BulletConstraint constrain) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; - BSAPICPP.DumpConstraint2(worldu.ptr, constrainu.ptr); -} - -public override void DumpActivationInfo(BulletWorld world) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BSAPICPP.DumpActivationInfo2(worldu.ptr); -} - -public override void DumpAllInfo(BulletWorld world) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BSAPICPP.DumpAllInfo2(worldu.ptr); -} - -public override void DumpPhysicsStatistics(BulletWorld world) -{ - BulletWorldUnman worldu = world as BulletWorldUnman; - BSAPICPP.DumpPhysicsStatistics2(worldu.ptr); -} - -// ===================================================================================== -// ===================================================================================== -// ===================================================================================== -// ===================================================================================== -// ===================================================================================== -// The actual interface to the unmanaged code -static class BSAPICPP -{ -// =============================================================================== -// Link back to the managed code for outputting log messages -[UnmanagedFunctionPointer(CallingConvention.Cdecl)] -public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); - -// =============================================================================== -// Initialization and simulation -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms, - int maxCollisions, IntPtr collisionArray, - int maxUpdates, IntPtr updateArray, - DebugLogCallback logRoutine); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSteps, float fixedTimeStep, - out int updatedEntityCount, out int collidersCount); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void Shutdown2(IntPtr sim); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool PushUpdate2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value); - -// ===================================================================================== -// Mesh, hull, shape and body creation helper routines -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateMeshShape2(IntPtr world, - int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices, - int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices ); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateHullShape2(IntPtr world, - int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr BuildHullShapeFromMesh2(IntPtr world, IntPtr meshShape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsNativeShape2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetShapeCollisionMargin2(IntPtr shape, float margin); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float height, Vector3 scale); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateCompoundShape2(IntPtr sim, bool enableDynamicAabbTree); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern int GetNumberOfCompoundChildren2(IntPtr cShape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void AddChildShapeToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr GetChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr RemoveChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void RecalculateCompoundShapeLocalAabb2(IntPtr cShape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern int GetBodyType2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, uint id, Vector3 pos, Quaternion rot); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateGhostFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void DestroyObject2(IntPtr sim, IntPtr obj); - -// ===================================================================================== -// Terrain creation and helper routines -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateTerrainShape2(uint id, Vector3 size, float minHeight, float maxHeight, - [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, - float scaleFactor, float collisionMargin); - -// ===================================================================================== -// Constraint creation and helper routines -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2, - Vector3 frame1loc, Quaternion frame1rot, - Vector3 frame2loc, Quaternion frame2rot, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr Create6DofConstraintToPoint2(IntPtr world, IntPtr obj1, IntPtr obj2, - Vector3 joinPoint, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateHingeConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2, - Vector3 pivotinA, Vector3 pivotinB, - Vector3 axisInA, Vector3 axisInB, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetConstraintEnable2(IntPtr constrain, float numericTrueFalse); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetFrames2(IntPtr constrain, - Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetAngularLimits2(IntPtr constrain, Vector3 low, Vector3 hi); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool UseFrameOffset2(IntPtr constrain, float enable); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetBreakingImpulseThreshold2(IntPtr constrain, float threshold); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool CalculateTransforms2(IntPtr constrain); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain); - -// ===================================================================================== -// btCollisionWorld entries -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void UpdateSingleAabb2(IntPtr world, IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void UpdateAabbs2(IntPtr world); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool GetForceUpdateAllAabbs2(IntPtr world); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetForceUpdateAllAabbs2(IntPtr world, bool force); - -// ===================================================================================== -// btDynamicsWorld entries -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool AddConstraintToWorld2(IntPtr world, IntPtr constrain, bool disableCollisionsBetweenLinkedObjects); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool RemoveConstraintFromWorld2(IntPtr world, IntPtr constrain); -// ===================================================================================== -// btCollisionObject entries -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetAnisotripicFriction2(IntPtr constrain); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 SetAnisotripicFriction2(IntPtr constrain, Vector3 frict); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool HasAnisotripicFriction2(IntPtr constrain); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetContactProcessingThreshold2(IntPtr obj, float val); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetContactProcessingThreshold2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsStaticObject2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsKinematicObject2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsStaticOrKinematicObject2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool HasContactResponse2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetCollisionShape2(IntPtr sim, IntPtr obj, IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr GetCollisionShape2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern int GetActivationState2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetActivationState2(IntPtr obj, int state); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetDeactivationTime2(IntPtr obj, float dtime); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetDeactivationTime2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ForceActivationState2(IntPtr obj, ActivationState state); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void Activate2(IntPtr obj, bool forceActivation); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsActive2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetRestitution2(IntPtr obj, float val); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetRestitution2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetFriction2(IntPtr obj, float val); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetFriction2(IntPtr obj); - - /* Haven't defined the type 'Transform' -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Transform GetWorldTransform2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void setWorldTransform2(IntPtr obj, Transform trans); - */ - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetPosition2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Quaternion GetOrientation2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr GetBroadphaseHandle2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetBroadphaseHandle2(IntPtr obj, IntPtr handle); - - /* -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Transform GetInterpolationWorldTransform2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetInterpolationWorldTransform2(IntPtr obj, Transform trans); - */ - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetInterpolationLinearVelocity2(IntPtr obj, Vector3 vel); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetInterpolationAngularVelocity2(IntPtr obj, Vector3 vel); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetInterpolationVelocity2(IntPtr obj, Vector3 linearVel, Vector3 angularVel); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetHitFraction2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetHitFraction2(IntPtr obj, float val); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern CollisionFlags GetCollisionFlags2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern CollisionFlags SetCollisionFlags2(IntPtr obj, CollisionFlags flags); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern CollisionFlags AddToCollisionFlags2(IntPtr obj, CollisionFlags flags); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern CollisionFlags RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetCcdMotionThreshold2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetCcdMotionThreshold2(IntPtr obj, float val); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetCcdSweptSphereRadius2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetCcdSweptSphereRadius2(IntPtr obj, float val); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr GetUserPointer2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetUserPointer2(IntPtr obj, IntPtr val); - -// ===================================================================================== -// btRigidBody entries -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyGravity2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetGravity2(IntPtr obj, Vector3 val); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetGravity2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetDamping2(IntPtr obj, float lin_damping, float ang_damping); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetLinearDamping2(IntPtr obj, float lin_damping); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetAngularDamping2(IntPtr obj, float ang_damping); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetLinearDamping2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetAngularDamping2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetLinearSleepingThreshold2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetAngularSleepingThreshold2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyDamping2(IntPtr obj, float timeStep); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetMassProps2(IntPtr obj, float mass, Vector3 inertia); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetLinearFactor2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetLinearFactor2(IntPtr obj, Vector3 factor); - - /* -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetCenterOfMassTransform2(IntPtr obj, Transform trans); - */ - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetCenterOfMassByPosRot2(IntPtr obj, Vector3 pos, Quaternion rot); - -// Add a force to the object as if its mass is one. -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyCentralForce2(IntPtr obj, Vector3 force); - -// Set the force being applied to the object as if its mass is one. -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetObjectForce2(IntPtr obj, Vector3 force); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetTotalForce2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetTotalTorque2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetInvInertiaDiagLocal2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetInvInertiaDiagLocal2(IntPtr obj, Vector3 inert); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyTorque2(IntPtr obj, Vector3 torque); - -// Apply force at the given point. Will add torque to the object. -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyForce2(IntPtr obj, Vector3 force, Vector3 pos); - -// Apply impulse to the object. Same as "ApplycentralForce" but force scaled by object's mass. -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyCentralImpulse2(IntPtr obj, Vector3 imp); - -// Apply impulse to the object's torque. Force is scaled by object's mass. -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyTorqueImpulse2(IntPtr obj, Vector3 imp); - -// Apply impulse at the point given. For is scaled by object's mass and effects both linear and angular forces. -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyImpulse2(IntPtr obj, Vector3 imp, Vector3 pos); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ClearForces2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ClearAllForces2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void UpdateInertiaTensor2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetCenterOfMassPosition2(IntPtr obj); - - /* -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Transform GetCenterOfMassTransform2(IntPtr obj); - */ - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetLinearVelocity2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetAngularVelocity2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetLinearVelocity2(IntPtr obj, Vector3 val); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetVelocityInLocalPoint2(IntPtr obj, Vector3 pos); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void Translate2(IntPtr obj, Vector3 trans); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void UpdateDeactivation2(IntPtr obj, float timeStep); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool WantsSleeping2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetAngularFactor2(IntPtr obj, float factor); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetAngularFactorV2(IntPtr obj, Vector3 factor); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetAngularFactor2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsInWorld2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void AddConstraintRef2(IntPtr obj, IntPtr constrain); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void RemoveConstraintRef2(IntPtr obj, IntPtr constrain); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr GetConstraintRef2(IntPtr obj, int index); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern int GetNumConstraintRefs2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetCollisionGroupMask2(IntPtr body, uint filter, uint mask); - -// ===================================================================================== -// btCollisionShape entries - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetAngularMotionDisc2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetContactBreakingThreshold2(IntPtr shape, float defaultFactor); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsPolyhedral2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsConvex2d2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsConvex2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsNonMoving2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsConcave2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsCompound2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsSoftBody2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsInfinite2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetLocalScaling2(IntPtr shape, Vector3 scale); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetLocalScaling2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 CalculateLocalInertia2(IntPtr shape, float mass); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern int GetShapeType2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetMargin2(IntPtr shape, float val); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetMargin2(IntPtr shape); - -// ===================================================================================== -// Debugging -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void DumpCollisionShape2(IntPtr sim, IntPtr collisionShape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void DumpConstraint2(IntPtr sim, IntPtr constrain); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void DumpActivationInfo2(IntPtr sim); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void DumpAllInfo2(IntPtr sim); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void DumpPhysicsStatistics2(IntPtr sim); - -} - -} - -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs deleted file mode 100755 index 30a7bee..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs +++ /dev/null @@ -1,1622 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; - -using OpenSim.Framework; - -using OpenMetaverse; - -using BulletXNA; -using BulletXNA.LinearMath; -using BulletXNA.BulletCollision; -using BulletXNA.BulletDynamics; -using BulletXNA.BulletCollision.CollisionDispatch; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public sealed class BSAPIXNA : BSAPITemplate -{ -private sealed class BulletWorldXNA : BulletWorld -{ - public DiscreteDynamicsWorld world; - public BulletWorldXNA(uint id, BSScene physScene, DiscreteDynamicsWorld xx) - : base(id, physScene) - { - world = xx; - } -} - -private sealed class BulletBodyXNA : BulletBody -{ - public CollisionObject body; - public RigidBody rigidBody { get { return RigidBody.Upcast(body); } } - - public BulletBodyXNA(uint id, CollisionObject xx) - : base(id) - { - body = xx; - } - public override bool HasPhysicalBody - { - get { return body != null; } - } - public override void Clear() - { - body = null; - } - public override string AddrString - { - get { return "XNARigidBody"; } - } -} - -private sealed class BulletShapeXNA : BulletShape -{ - public CollisionShape shape; - public BulletShapeXNA(CollisionShape xx, BSPhysicsShapeType typ) - : base() - { - shape = xx; - type = typ; - } - public override bool HasPhysicalShape - { - get { return shape != null; } - } - public override void Clear() - { - shape = null; - } - public override BulletShape Clone() - { - return new BulletShapeXNA(shape, type); - } - public override bool ReferenceSame(BulletShape other) - { - BulletShapeXNA otheru = other as BulletShapeXNA; - return (otheru != null) && (this.shape == otheru.shape); - - } - public override string AddrString - { - get { return "XNACollisionShape"; } - } -} -private sealed class BulletConstraintXNA : BulletConstraint -{ - public TypedConstraint constrain; - public BulletConstraintXNA(TypedConstraint xx) : base() - { - constrain = xx; - } - - public override void Clear() - { - constrain = null; - } - public override bool HasPhysicalConstraint { get { return constrain != null; } } - - // Used for log messages for a unique display of the memory/object allocated to this instance - public override string AddrString - { - get { return "XNAConstraint"; } - } -} - - private static int m_collisionsThisFrame; - private BSScene PhysicsScene { get; set; } - - public override string BulletEngineName { get { return "BulletXNA"; } } - public override string BulletEngineVersion { get; protected set; } - - public BSAPIXNA(string paramName, BSScene physScene) - { - PhysicsScene = physScene; - } - - /// - /// - /// - /// - /// - public override bool RemoveObjectFromWorld(BulletWorld pWorld, BulletBody pBody) - { - DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world; - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - world.RemoveRigidBody(body); - return true; - } - - public override bool AddConstraintToWorld(BulletWorld world, BulletConstraint constrain, bool disableCollisionsBetweenLinkedObjects) - { - /* TODO */ - return false; - } - - public override bool RemoveConstraintFromWorld(BulletWorld world, BulletConstraint constrain) - { - /* TODO */ - return false; - } - - public override void SetRestitution(BulletBody pBody, float pRestitution) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - body.SetRestitution(pRestitution); - } - - public override int GetShapeType(BulletShape pShape) - { - CollisionShape shape = ((BulletShapeXNA)pShape).shape; - return (int)shape.GetShapeType(); - } - public override void SetMargin(BulletShape pShape, float pMargin) - { - CollisionShape shape = ((BulletShapeXNA)pShape).shape; - shape.SetMargin(pMargin); - } - - public override float GetMargin(BulletShape pShape) - { - CollisionShape shape = ((BulletShapeXNA)pShape).shape; - return shape.GetMargin(); - } - - public override void SetLocalScaling(BulletShape pShape, Vector3 pScale) - { - CollisionShape shape = ((BulletShapeXNA)pShape).shape; - IndexedVector3 vec = new IndexedVector3(pScale.X, pScale.Y, pScale.Z); - shape.SetLocalScaling(ref vec); - - } - - public override void SetContactProcessingThreshold(BulletBody pBody, float contactprocessingthreshold) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - body.SetContactProcessingThreshold(contactprocessingthreshold); - } - - public override void SetCcdMotionThreshold(BulletBody pBody, float pccdMotionThreashold) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - body.SetCcdMotionThreshold(pccdMotionThreashold); - } - - public override void SetCcdSweptSphereRadius(BulletBody pBody, float pCcdSweptSphereRadius) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - body.SetCcdSweptSphereRadius(pCcdSweptSphereRadius); - } - - public override void SetAngularFactorV(BulletBody pBody, Vector3 pAngularFactor) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - body.SetAngularFactor(new IndexedVector3(pAngularFactor.X, pAngularFactor.Y, pAngularFactor.Z)); - } - - public override CollisionFlags AddToCollisionFlags(BulletBody pBody, CollisionFlags pcollisionFlags) - { - CollisionObject body = ((BulletBodyXNA)pBody).body; - CollisionFlags existingcollisionFlags = (CollisionFlags)(uint)body.GetCollisionFlags(); - existingcollisionFlags |= pcollisionFlags; - body.SetCollisionFlags((BulletXNA.BulletCollision.CollisionFlags)(uint)existingcollisionFlags); - return (CollisionFlags) (uint) existingcollisionFlags; - } - - public override bool AddObjectToWorld(BulletWorld pWorld, BulletBody pBody) - { - // Bullet resets several variables when an object is added to the world. In particular, - // BulletXNA resets position and rotation. Gravity is also reset depending on the static/dynamic - // type. Of course, the collision flags in the broadphase proxy are initialized to default. - DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world; - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - - IndexedMatrix origPos = body.GetWorldTransform(); - IndexedVector3 origGrav = body.GetGravity(); - - //if (!(body.GetCollisionShape().GetShapeType() == BroadphaseNativeTypes.STATIC_PLANE_PROXYTYPE && body.GetCollisionShape().GetShapeType() == BroadphaseNativeTypes.TERRAIN_SHAPE_PROXYTYPE)) - - world.AddRigidBody(body); - - body.SetWorldTransform(origPos); - body.SetGravity(origGrav); - - pBody.ApplyCollisionMask(pWorld.physicsScene); - - //if (body.GetBroadphaseHandle() != null) - // world.UpdateSingleAabb(body); - return true; - } - - public override void ForceActivationState(BulletBody pBody, ActivationState pActivationState) - { - CollisionObject body = ((BulletBodyXNA)pBody).body; - body.ForceActivationState((BulletXNA.BulletCollision.ActivationState)(uint)pActivationState); - } - - public override void UpdateSingleAabb(BulletWorld pWorld, BulletBody pBody) - { - DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world; - CollisionObject body = ((BulletBodyXNA)pBody).body; - world.UpdateSingleAabb(body); - } - - public override void UpdateAabbs(BulletWorld world) { /* TODO */ } - public override bool GetForceUpdateAllAabbs(BulletWorld world) { /* TODO */ return false; } - public override void SetForceUpdateAllAabbs(BulletWorld world, bool force) { /* TODO */ } - - public override bool SetCollisionGroupMask(BulletBody pBody, uint pGroup, uint pMask) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - body.GetBroadphaseHandle().m_collisionFilterGroup = (BulletXNA.BulletCollision.CollisionFilterGroups) pGroup; - body.GetBroadphaseHandle().m_collisionFilterGroup = (BulletXNA.BulletCollision.CollisionFilterGroups) pGroup; - if ((uint) body.GetBroadphaseHandle().m_collisionFilterGroup == 0) - return false; - return true; - } - - public override void ClearAllForces(BulletBody pBody) - { - CollisionObject body = ((BulletBodyXNA)pBody).body; - IndexedVector3 zeroVector = new IndexedVector3(0, 0, 0); - body.SetInterpolationLinearVelocity(ref zeroVector); - body.SetInterpolationAngularVelocity(ref zeroVector); - IndexedMatrix bodytransform = body.GetWorldTransform(); - - body.SetInterpolationWorldTransform(ref bodytransform); - - if (body is RigidBody) - { - RigidBody rigidbody = body as RigidBody; - rigidbody.SetLinearVelocity(zeroVector); - rigidbody.SetAngularVelocity(zeroVector); - rigidbody.ClearForces(); - } - } - - public override void SetInterpolationAngularVelocity(BulletBody pBody, Vector3 pVector3) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 vec = new IndexedVector3(pVector3.X, pVector3.Y, pVector3.Z); - body.SetInterpolationAngularVelocity(ref vec); - } - - public override void SetAngularVelocity(BulletBody pBody, Vector3 pVector3) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 vec = new IndexedVector3(pVector3.X, pVector3.Y, pVector3.Z); - body.SetAngularVelocity(ref vec); - } - public override Vector3 GetTotalForce(BulletBody pBody) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 iv3 = body.GetTotalForce(); - return new Vector3(iv3.X, iv3.Y, iv3.Z); - } - public override Vector3 GetTotalTorque(BulletBody pBody) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 iv3 = body.GetTotalTorque(); - return new Vector3(iv3.X, iv3.Y, iv3.Z); - } - public override Vector3 GetInvInertiaDiagLocal(BulletBody pBody) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 iv3 = body.GetInvInertiaDiagLocal(); - return new Vector3(iv3.X, iv3.Y, iv3.Z); - } - public override void SetInvInertiaDiagLocal(BulletBody pBody, Vector3 inert) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 iv3 = new IndexedVector3(inert.X, inert.Y, inert.Z); - body.SetInvInertiaDiagLocal(ref iv3); - } - public override void ApplyForce(BulletBody pBody, Vector3 force, Vector3 pos) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 forceiv3 = new IndexedVector3(force.X, force.Y, force.Z); - IndexedVector3 posiv3 = new IndexedVector3(pos.X, pos.Y, pos.Z); - body.ApplyForce(ref forceiv3, ref posiv3); - } - public override void ApplyImpulse(BulletBody pBody, Vector3 imp, Vector3 pos) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 impiv3 = new IndexedVector3(imp.X, imp.Y, imp.Z); - IndexedVector3 posiv3 = new IndexedVector3(pos.X, pos.Y, pos.Z); - body.ApplyImpulse(ref impiv3, ref posiv3); - } - - public override void ClearForces(BulletBody pBody) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - body.ClearForces(); - } - - public override void SetTranslation(BulletBody pBody, Vector3 _position, Quaternion _orientation) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 vposition = new IndexedVector3(_position.X, _position.Y, _position.Z); - IndexedQuaternion vquaternion = new IndexedQuaternion(_orientation.X, _orientation.Y, _orientation.Z, - _orientation.W); - IndexedMatrix mat = IndexedMatrix.CreateFromQuaternion(vquaternion); - mat._origin = vposition; - body.SetWorldTransform(mat); - - } - - public override Vector3 GetPosition(BulletBody pBody) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 pos = body.GetInterpolationWorldTransform()._origin; - return new Vector3(pos.X, pos.Y, pos.Z); - } - - public override Vector3 CalculateLocalInertia(BulletShape pShape, float pphysMass) - { - CollisionShape shape = ((BulletShapeXNA)pShape).shape; - IndexedVector3 inertia = IndexedVector3.Zero; - shape.CalculateLocalInertia(pphysMass, out inertia); - return new Vector3(inertia.X, inertia.Y, inertia.Z); - } - - public override void SetMassProps(BulletBody pBody, float pphysMass, Vector3 plocalInertia) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 inertia = new IndexedVector3(plocalInertia.X, plocalInertia.Y, plocalInertia.Z); - body.SetMassProps(pphysMass, inertia); - } - - - public override void SetObjectForce(BulletBody pBody, Vector3 _force) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 force = new IndexedVector3(_force.X, _force.Y, _force.Z); - body.SetTotalForce(ref force); - } - - public override void SetFriction(BulletBody pBody, float _currentFriction) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - body.SetFriction(_currentFriction); - } - - public override void SetLinearVelocity(BulletBody pBody, Vector3 _velocity) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 velocity = new IndexedVector3(_velocity.X, _velocity.Y, _velocity.Z); - body.SetLinearVelocity(velocity); - } - - public override void Activate(BulletBody pBody, bool pforceactivation) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - body.Activate(pforceactivation); - - } - - public override Quaternion GetOrientation(BulletBody pBody) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedQuaternion mat = body.GetInterpolationWorldTransform().GetRotation(); - return new Quaternion(mat.X, mat.Y, mat.Z, mat.W); - } - - public override CollisionFlags RemoveFromCollisionFlags(BulletBody pBody, CollisionFlags pcollisionFlags) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - CollisionFlags existingcollisionFlags = (CollisionFlags)(uint)body.GetCollisionFlags(); - existingcollisionFlags &= ~pcollisionFlags; - body.SetCollisionFlags((BulletXNA.BulletCollision.CollisionFlags)(uint)existingcollisionFlags); - return (CollisionFlags)(uint)existingcollisionFlags; - } - - public override float GetCcdMotionThreshold(BulletBody obj) { /* TODO */ return 0f; } - - public override float GetCcdSweptSphereRadius(BulletBody obj) { /* TODO */ return 0f; } - - public override IntPtr GetUserPointer(BulletBody obj) { /* TODO */ return IntPtr.Zero; } - - public override void SetUserPointer(BulletBody obj, IntPtr val) { /* TODO */ } - - public override void SetGravity(BulletBody pBody, Vector3 pGravity) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 gravity = new IndexedVector3(pGravity.X, pGravity.Y, pGravity.Z); - body.SetGravity(gravity); - } - - public override bool DestroyConstraint(BulletWorld pWorld, BulletConstraint pConstraint) - { - DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world; - TypedConstraint constraint = ((BulletConstraintXNA)pConstraint).constrain; - world.RemoveConstraint(constraint); - return true; - } - - public override bool SetLinearLimits(BulletConstraint pConstraint, Vector3 low, Vector3 high) - { - Generic6DofConstraint constraint = ((BulletConstraintXNA)pConstraint).constrain as Generic6DofConstraint; - IndexedVector3 lowlimit = new IndexedVector3(low.X, low.Y, low.Z); - IndexedVector3 highlimit = new IndexedVector3(high.X, high.Y, high.Z); - constraint.SetLinearLowerLimit(lowlimit); - constraint.SetLinearUpperLimit(highlimit); - return true; - } - - public override bool SetAngularLimits(BulletConstraint pConstraint, Vector3 low, Vector3 high) - { - Generic6DofConstraint constraint = ((BulletConstraintXNA)pConstraint).constrain as Generic6DofConstraint; - IndexedVector3 lowlimit = new IndexedVector3(low.X, low.Y, low.Z); - IndexedVector3 highlimit = new IndexedVector3(high.X, high.Y, high.Z); - constraint.SetAngularLowerLimit(lowlimit); - constraint.SetAngularUpperLimit(highlimit); - return true; - } - - public override void SetConstraintNumSolverIterations(BulletConstraint pConstraint, float cnt) - { - Generic6DofConstraint constraint = ((BulletConstraintXNA)pConstraint).constrain as Generic6DofConstraint; - constraint.SetOverrideNumSolverIterations((int)cnt); - } - - public override bool CalculateTransforms(BulletConstraint pConstraint) - { - Generic6DofConstraint constraint = ((BulletConstraintXNA)pConstraint).constrain as Generic6DofConstraint; - constraint.CalculateTransforms(); - return true; - } - - public override void SetConstraintEnable(BulletConstraint pConstraint, float p_2) - { - Generic6DofConstraint constraint = ((BulletConstraintXNA)pConstraint).constrain as Generic6DofConstraint; - constraint.SetEnabled((p_2 == 0) ? false : true); - } - - - //BulletSimAPI.Create6DofConstraint(m_world.ptr, m_body1.ptr, m_body2.ptr,frame1, frame1rot,frame2, frame2rot,useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); - public override BulletConstraint Create6DofConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2, Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot, bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies) - - { - DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world; - RigidBody body1 = ((BulletBodyXNA)pBody1).rigidBody; - RigidBody body2 = ((BulletBodyXNA)pBody2).rigidBody; - IndexedVector3 frame1v = new IndexedVector3(pframe1.X, pframe1.Y, pframe1.Z); - IndexedQuaternion frame1rot = new IndexedQuaternion(pframe1rot.X, pframe1rot.Y, pframe1rot.Z, pframe1rot.W); - IndexedMatrix frame1 = IndexedMatrix.CreateFromQuaternion(frame1rot); - frame1._origin = frame1v; - - IndexedVector3 frame2v = new IndexedVector3(pframe2.X, pframe2.Y, pframe2.Z); - IndexedQuaternion frame2rot = new IndexedQuaternion(pframe2rot.X, pframe2rot.Y, pframe2rot.Z, pframe2rot.W); - IndexedMatrix frame2 = IndexedMatrix.CreateFromQuaternion(frame2rot); - frame2._origin = frame1v; - - Generic6DofConstraint consttr = new Generic6DofConstraint(body1, body2, ref frame1, ref frame2, - puseLinearReferenceFrameA); - consttr.CalculateTransforms(); - world.AddConstraint(consttr,pdisableCollisionsBetweenLinkedBodies); - - return new BulletConstraintXNA(consttr); - } - - - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public override BulletConstraint Create6DofConstraintToPoint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2, Vector3 pjoinPoint, bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies) - { - DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world; - RigidBody body1 = ((BulletBodyXNA)pBody1).rigidBody; - RigidBody body2 = ((BulletBodyXNA)pBody2).rigidBody; - IndexedMatrix frame1 = new IndexedMatrix(IndexedBasisMatrix.Identity, new IndexedVector3(0, 0, 0)); - IndexedMatrix frame2 = new IndexedMatrix(IndexedBasisMatrix.Identity, new IndexedVector3(0, 0, 0)); - - IndexedVector3 joinPoint = new IndexedVector3(pjoinPoint.X, pjoinPoint.Y, pjoinPoint.Z); - IndexedMatrix mat = IndexedMatrix.Identity; - mat._origin = new IndexedVector3(pjoinPoint.X, pjoinPoint.Y, pjoinPoint.Z); - frame1._origin = body1.GetWorldTransform().Inverse()*joinPoint; - frame2._origin = body2.GetWorldTransform().Inverse()*joinPoint; - - Generic6DofConstraint consttr = new Generic6DofConstraint(body1, body2, ref frame1, ref frame2, puseLinearReferenceFrameA); - consttr.CalculateTransforms(); - world.AddConstraint(consttr, pdisableCollisionsBetweenLinkedBodies); - - return new BulletConstraintXNA(consttr); - } - //SetFrames(m_constraint.ptr, frameA, frameArot, frameB, frameBrot); - public override bool SetFrames(BulletConstraint pConstraint, Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot) - { - Generic6DofConstraint constraint = ((BulletConstraintXNA)pConstraint).constrain as Generic6DofConstraint; - IndexedVector3 frame1v = new IndexedVector3(pframe1.X, pframe1.Y, pframe1.Z); - IndexedQuaternion frame1rot = new IndexedQuaternion(pframe1rot.X, pframe1rot.Y, pframe1rot.Z, pframe1rot.W); - IndexedMatrix frame1 = IndexedMatrix.CreateFromQuaternion(frame1rot); - frame1._origin = frame1v; - - IndexedVector3 frame2v = new IndexedVector3(pframe2.X, pframe2.Y, pframe2.Z); - IndexedQuaternion frame2rot = new IndexedQuaternion(pframe2rot.X, pframe2rot.Y, pframe2rot.Z, pframe2rot.W); - IndexedMatrix frame2 = IndexedMatrix.CreateFromQuaternion(frame2rot); - frame2._origin = frame1v; - constraint.SetFrames(ref frame1, ref frame2); - return true; - } - - public override Vector3 GetLinearVelocity(BulletBody pBody) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 iv3 = body.GetLinearVelocity(); - return new Vector3(iv3.X, iv3.Y, iv3.Z); - } - public override Vector3 GetAngularVelocity(BulletBody pBody) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 iv3 = body.GetAngularVelocity(); - return new Vector3(iv3.X, iv3.Y, iv3.Z); - } - public override Vector3 GetVelocityInLocalPoint(BulletBody pBody, Vector3 pos) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 posiv3 = new IndexedVector3(pos.X, pos.Y, pos.Z); - IndexedVector3 iv3 = body.GetVelocityInLocalPoint(ref posiv3); - return new Vector3(iv3.X, iv3.Y, iv3.Z); - } - public override void Translate(BulletBody pBody, Vector3 trans) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - } - public override void UpdateDeactivation(BulletBody pBody, float timeStep) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - body.UpdateDeactivation(timeStep); - } - - public override bool WantsSleeping(BulletBody pBody) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - return body.WantsSleeping(); - } - - public override void SetAngularFactor(BulletBody pBody, float factor) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - body.SetAngularFactor(factor); - } - - public override Vector3 GetAngularFactor(BulletBody pBody) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 iv3 = body.GetAngularFactor(); - return new Vector3(iv3.X, iv3.Y, iv3.Z); - } - - public override bool IsInWorld(BulletWorld pWorld, BulletBody pBody) - { - DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world; - CollisionObject body = ((BulletBodyXNA)pBody).body; - return world.IsInWorld(body); - } - - public override void AddConstraintRef(BulletBody pBody, BulletConstraint pConstrain) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - TypedConstraint constrain = ((BulletConstraintXNA)pConstrain).constrain; - body.AddConstraintRef(constrain); - } - - public override void RemoveConstraintRef(BulletBody pBody, BulletConstraint pConstrain) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - TypedConstraint constrain = ((BulletConstraintXNA)pConstrain).constrain; - body.RemoveConstraintRef(constrain); - } - - public override BulletConstraint GetConstraintRef(BulletBody pBody, int index) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - return new BulletConstraintXNA(body.GetConstraintRef(index)); - } - - public override int GetNumConstraintRefs(BulletBody pBody) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - return body.GetNumConstraintRefs(); - } - - public override void SetInterpolationLinearVelocity(BulletBody pBody, Vector3 VehicleVelocity) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 velocity = new IndexedVector3(VehicleVelocity.X, VehicleVelocity.Y, VehicleVelocity.Z); - body.SetInterpolationLinearVelocity(ref velocity); - } - - public override bool UseFrameOffset(BulletConstraint pConstraint, float onOff) - { - Generic6DofConstraint constraint = ((BulletConstraintXNA)pConstraint).constrain as Generic6DofConstraint; - constraint.SetUseFrameOffset((onOff == 0) ? false : true); - return true; - } - //SetBreakingImpulseThreshold(m_constraint.ptr, threshold); - public override bool SetBreakingImpulseThreshold(BulletConstraint pConstraint, float threshold) - { - Generic6DofConstraint constraint = ((BulletConstraintXNA)pConstraint).constrain as Generic6DofConstraint; - constraint.SetBreakingImpulseThreshold(threshold); - return true; - } - //BulletSimAPI.SetAngularDamping(Prim.PhysBody.ptr, angularDamping); - public override void SetAngularDamping(BulletBody pBody, float angularDamping) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - float lineardamping = body.GetLinearDamping(); - body.SetDamping(lineardamping, angularDamping); - - } - - public override void UpdateInertiaTensor(BulletBody pBody) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - body.UpdateInertiaTensor(); - } - - public override void RecalculateCompoundShapeLocalAabb(BulletShape pCompoundShape) - { - CompoundShape shape = ((BulletShapeXNA)pCompoundShape).shape as CompoundShape; - shape.RecalculateLocalAabb(); - } - - //BulletSimAPI.GetCollisionFlags(PhysBody.ptr) - public override CollisionFlags GetCollisionFlags(BulletBody pBody) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - uint flags = (uint)body.GetCollisionFlags(); - return (CollisionFlags) flags; - } - - public override void SetDamping(BulletBody pBody, float pLinear, float pAngular) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - body.SetDamping(pLinear, pAngular); - } - //PhysBody.ptr, PhysicsScene.Params.deactivationTime); - public override void SetDeactivationTime(BulletBody pBody, float pDeactivationTime) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - body.SetDeactivationTime(pDeactivationTime); - } - //SetSleepingThresholds(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); - public override void SetSleepingThresholds(BulletBody pBody, float plinearSleepingThreshold, float pangularSleepingThreshold) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - body.SetSleepingThresholds(plinearSleepingThreshold, pangularSleepingThreshold); - } - - public override CollisionObjectTypes GetBodyType(BulletBody pBody) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - return (CollisionObjectTypes)(int) body.GetInternalType(); - } - - public override void ApplyGravity(BulletBody obj) { /* TODO */ } - - public override Vector3 GetGravity(BulletBody obj) { /* TODO */ return Vector3.Zero; } - - public override void SetLinearDamping(BulletBody obj, float lin_damping) { /* TODO */ } - - public override float GetLinearDamping(BulletBody obj) { /* TODO */ return 0f; } - - public override float GetAngularDamping(BulletBody obj) { /* TODO */ return 0f; } - - public override float GetLinearSleepingThreshold(BulletBody obj) { /* TODO */ return 0f; } - - public override void ApplyDamping(BulletBody obj, float timeStep) { /* TODO */ } - - public override Vector3 GetLinearFactor(BulletBody obj) { /* TODO */ return Vector3.Zero; } - - public override void SetLinearFactor(BulletBody obj, Vector3 factor) { /* TODO */ } - - public override void SetCenterOfMassByPosRot(BulletBody obj, Vector3 pos, Quaternion rot) { /* TODO */ } - - //BulletSimAPI.ApplyCentralForce(PhysBody.ptr, fSum); - public override void ApplyCentralForce(BulletBody pBody, Vector3 pfSum) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 fSum = new IndexedVector3(pfSum.X, pfSum.Y, pfSum.Z); - body.ApplyCentralForce(ref fSum); - } - public override void ApplyCentralImpulse(BulletBody pBody, Vector3 pfSum) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 fSum = new IndexedVector3(pfSum.X, pfSum.Y, pfSum.Z); - body.ApplyCentralImpulse(ref fSum); - } - public override void ApplyTorque(BulletBody pBody, Vector3 pfSum) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 fSum = new IndexedVector3(pfSum.X, pfSum.Y, pfSum.Z); - body.ApplyTorque(ref fSum); - } - public override void ApplyTorqueImpulse(BulletBody pBody, Vector3 pfSum) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedVector3 fSum = new IndexedVector3(pfSum.X, pfSum.Y, pfSum.Z); - body.ApplyTorqueImpulse(ref fSum); - } - - public override void DumpRigidBody(BulletWorld p, BulletBody p_2) - { - //TODO: - } - - public override void DumpCollisionShape(BulletWorld p, BulletShape p_2) - { - //TODO: - } - public override void DumpConstraint(BulletWorld world, BulletConstraint constrain) - { - //TODO: - } - - public override void DumpActivationInfo(BulletWorld world) - { - //TODO: - } - - public override void DumpAllInfo(BulletWorld world) - { - //TODO: - } - - public override void DumpPhysicsStatistics(BulletWorld world) - { - //TODO: - } - - public override void DestroyObject(BulletWorld p, BulletBody p_2) - { - //TODO: - } - - public override void Shutdown(BulletWorld pWorld) - { - DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world; - world.Cleanup(); - } - - public override BulletShape DuplicateCollisionShape(BulletWorld sim, BulletShape srcShape, uint id) - { - return null; - } - - public override bool DeleteCollisionShape(BulletWorld p, BulletShape p_2) - { - //TODO: - return false; - } - //(sim.ptr, shape.ptr, prim.LocalID, prim.RawPosition, prim.RawOrientation); - - public override BulletBody CreateBodyFromShape(BulletWorld pWorld, BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation) - { - CollisionWorld world = ((BulletWorldXNA)pWorld).world; - IndexedMatrix mat = - IndexedMatrix.CreateFromQuaternion(new IndexedQuaternion(pRawOrientation.X, pRawOrientation.Y, - pRawOrientation.Z, pRawOrientation.W)); - mat._origin = new IndexedVector3(pRawPosition.X, pRawPosition.Y, pRawPosition.Z); - CollisionShape shape = ((BulletShapeXNA)pShape).shape; - //UpdateSingleAabb(world, shape); - // TODO: Feed Update array into null - RigidBody body = new RigidBody(0,new SimMotionState(world,pLocalID,mat,null),shape,IndexedVector3.Zero); - - body.SetUserPointer(pLocalID); - return new BulletBodyXNA(pLocalID, body); - } - - - public override BulletBody CreateBodyWithDefaultMotionState( BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation) - { - - IndexedMatrix mat = - IndexedMatrix.CreateFromQuaternion(new IndexedQuaternion(pRawOrientation.X, pRawOrientation.Y, - pRawOrientation.Z, pRawOrientation.W)); - mat._origin = new IndexedVector3(pRawPosition.X, pRawPosition.Y, pRawPosition.Z); - - CollisionShape shape = ((BulletShapeXNA)pShape).shape; - - // TODO: Feed Update array into null - RigidBody body = new RigidBody(0, new DefaultMotionState( mat, IndexedMatrix.Identity), shape, IndexedVector3.Zero); - body.SetWorldTransform(mat); - body.SetUserPointer(pLocalID); - return new BulletBodyXNA(pLocalID, body); - } - //(m_mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - public override CollisionFlags SetCollisionFlags(BulletBody pBody, CollisionFlags collisionFlags) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - body.SetCollisionFlags((BulletXNA.BulletCollision.CollisionFlags) (uint) collisionFlags); - return (CollisionFlags)body.GetCollisionFlags(); - } - - public override Vector3 GetAnisotripicFriction(BulletConstraint pconstrain) { /* TODO */ return Vector3.Zero; } - public override Vector3 SetAnisotripicFriction(BulletConstraint pconstrain, Vector3 frict) { /* TODO */ return Vector3.Zero; } - public override bool HasAnisotripicFriction(BulletConstraint pconstrain) { /* TODO */ return false; } - public override float GetContactProcessingThreshold(BulletBody pBody) { /* TODO */ return 0f; } - public override bool IsStaticObject(BulletBody pBody) { /* TODO */ return false; } - public override bool IsKinematicObject(BulletBody pBody) { /* TODO */ return false; } - public override bool IsStaticOrKinematicObject(BulletBody pBody) { /* TODO */ return false; } - public override bool HasContactResponse(BulletBody pBody) { /* TODO */ return false; } - public override int GetActivationState(BulletBody pBody) { /* TODO */ return 0; } - public override void SetActivationState(BulletBody pBody, int state) { /* TODO */ } - public override float GetDeactivationTime(BulletBody pBody) { /* TODO */ return 0f; } - public override bool IsActive(BulletBody pBody) { /* TODO */ return false; } - public override float GetRestitution(BulletBody pBody) { /* TODO */ return 0f; } - public override float GetFriction(BulletBody pBody) { /* TODO */ return 0f; } - public override void SetInterpolationVelocity(BulletBody pBody, Vector3 linearVel, Vector3 angularVel) { /* TODO */ } - public override float GetHitFraction(BulletBody pBody) { /* TODO */ return 0f; } - - //(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); - public override void SetHitFraction(BulletBody pBody, float pHitFraction) - { - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - body.SetHitFraction(pHitFraction); - } - //BuildCapsuleShape(physicsScene.World.ptr, 1f, 1f, prim.Scale); - public override BulletShape BuildCapsuleShape(BulletWorld pWorld, float pRadius, float pHeight, Vector3 pScale) - { - DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world; - IndexedVector3 scale = new IndexedVector3(pScale.X, pScale.Y, pScale.Z); - CapsuleShapeZ capsuleShapeZ = new CapsuleShapeZ(pRadius, pHeight); - capsuleShapeZ.SetMargin(world.WorldSettings.Params.collisionMargin); - capsuleShapeZ.SetLocalScaling(ref scale); - - return new BulletShapeXNA(capsuleShapeZ, BSPhysicsShapeType.SHAPE_CAPSULE); ; - } - - public override BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms, - int maxCollisions, ref CollisionDesc[] collisionArray, - int maxUpdates, ref EntityProperties[] updateArray - ) - { - /* TODO */ - return new BulletWorldXNA(1, null, null); - } - - private static object Initialize2(Vector3 worldExtent, - ConfigurationParameters[] o, - int mMaxCollisionsPerFrame, ref List collisionArray, - int mMaxUpdatesPerFrame, ref List updateArray, - object mDebugLogCallbackHandle) - { - CollisionWorld.WorldData.ParamData p = new CollisionWorld.WorldData.ParamData(); - - p.angularDamping = o[0].XangularDamping; - p.defaultFriction = o[0].defaultFriction; - p.defaultFriction = o[0].defaultFriction; - p.defaultDensity = o[0].defaultDensity; - p.defaultRestitution = o[0].defaultRestitution; - p.collisionMargin = o[0].collisionMargin; - p.gravity = o[0].gravity; - - p.linearDamping = o[0].XlinearDamping; - p.angularDamping = o[0].XangularDamping; - p.deactivationTime = o[0].XdeactivationTime; - p.linearSleepingThreshold = o[0].XlinearSleepingThreshold; - p.angularSleepingThreshold = o[0].XangularSleepingThreshold; - p.ccdMotionThreshold = o[0].XccdMotionThreshold; - p.ccdSweptSphereRadius = o[0].XccdSweptSphereRadius; - p.contactProcessingThreshold = o[0].XcontactProcessingThreshold; - - p.terrainImplementation = o[0].XterrainImplementation; - p.terrainFriction = o[0].XterrainFriction; - - p.terrainHitFraction = o[0].XterrainHitFraction; - p.terrainRestitution = o[0].XterrainRestitution; - p.terrainCollisionMargin = o[0].XterrainCollisionMargin; - - p.avatarFriction = o[0].XavatarFriction; - p.avatarStandingFriction = o[0].XavatarStandingFriction; - p.avatarDensity = o[0].XavatarDensity; - p.avatarRestitution = o[0].XavatarRestitution; - p.avatarCapsuleWidth = o[0].XavatarCapsuleWidth; - p.avatarCapsuleDepth = o[0].XavatarCapsuleDepth; - p.avatarCapsuleHeight = o[0].XavatarCapsuleHeight; - p.avatarContactProcessingThreshold = o[0].XavatarContactProcessingThreshold; - - p.vehicleAngularDamping = o[0].XvehicleAngularDamping; - - p.maxPersistantManifoldPoolSize = o[0].maxPersistantManifoldPoolSize; - p.maxCollisionAlgorithmPoolSize = o[0].maxCollisionAlgorithmPoolSize; - p.shouldDisableContactPoolDynamicAllocation = o[0].shouldDisableContactPoolDynamicAllocation; - p.shouldForceUpdateAllAabbs = o[0].shouldForceUpdateAllAabbs; - p.shouldRandomizeSolverOrder = o[0].shouldRandomizeSolverOrder; - p.shouldSplitSimulationIslands = o[0].shouldSplitSimulationIslands; - p.shouldEnableFrictionCaching = o[0].shouldEnableFrictionCaching; - p.numberOfSolverIterations = o[0].numberOfSolverIterations; - - p.linksetImplementation = o[0].XlinksetImplementation; - p.linkConstraintUseFrameOffset = o[0].XlinkConstraintUseFrameOffset; - p.linkConstraintEnableTransMotor = o[0].XlinkConstraintEnableTransMotor; - p.linkConstraintTransMotorMaxVel = o[0].XlinkConstraintTransMotorMaxVel; - p.linkConstraintTransMotorMaxForce = o[0].XlinkConstraintTransMotorMaxForce; - p.linkConstraintERP = o[0].XlinkConstraintERP; - p.linkConstraintCFM = o[0].XlinkConstraintCFM; - p.linkConstraintSolverIterations = o[0].XlinkConstraintSolverIterations; - p.physicsLoggingFrames = o[0].XphysicsLoggingFrames; - DefaultCollisionConstructionInfo ccci = new DefaultCollisionConstructionInfo(); - - DefaultCollisionConfiguration cci = new DefaultCollisionConfiguration(); - CollisionDispatcher m_dispatcher = new CollisionDispatcher(cci); - - - if (p.maxPersistantManifoldPoolSize > 0) - cci.m_persistentManifoldPoolSize = (int)p.maxPersistantManifoldPoolSize; - if (p.shouldDisableContactPoolDynamicAllocation !=0) - m_dispatcher.SetDispatcherFlags(DispatcherFlags.CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION); - //if (p.maxCollisionAlgorithmPoolSize >0 ) - - DbvtBroadphase m_broadphase = new DbvtBroadphase(); - //IndexedVector3 aabbMin = new IndexedVector3(0, 0, 0); - //IndexedVector3 aabbMax = new IndexedVector3(256, 256, 256); - - //AxisSweep3Internal m_broadphase2 = new AxisSweep3Internal(ref aabbMin, ref aabbMax, Convert.ToInt32(0xfffe), 0xffff, ushort.MaxValue/2, null, true); - m_broadphase.GetOverlappingPairCache().SetInternalGhostPairCallback(new GhostPairCallback()); - - SequentialImpulseConstraintSolver m_solver = new SequentialImpulseConstraintSolver(); - - DiscreteDynamicsWorld world = new DiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, cci); - world.UpdatedObjects = updateArray; - world.UpdatedCollisions = collisionArray; - world.WorldSettings.Params = p; - world.SetForceUpdateAllAabbs(p.shouldForceUpdateAllAabbs != 0); - world.GetSolverInfo().m_solverMode = SolverMode.SOLVER_USE_WARMSTARTING | SolverMode.SOLVER_SIMD; - if (p.shouldRandomizeSolverOrder != 0) - world.GetSolverInfo().m_solverMode |= SolverMode.SOLVER_RANDMIZE_ORDER; - - world.GetSimulationIslandManager().SetSplitIslands(p.shouldSplitSimulationIslands != 0); - //world.GetDispatchInfo().m_enableSatConvex Not implemented in C# port - - if (p.shouldEnableFrictionCaching != 0) - world.GetSolverInfo().m_solverMode |= SolverMode.SOLVER_ENABLE_FRICTION_DIRECTION_CACHING; - - if (p.numberOfSolverIterations > 0) - world.GetSolverInfo().m_numIterations = (int) p.numberOfSolverIterations; - - - world.GetSolverInfo().m_damping = world.WorldSettings.Params.linearDamping; - world.GetSolverInfo().m_restitution = world.WorldSettings.Params.defaultRestitution; - world.GetSolverInfo().m_globalCfm = 0.0f; - world.GetSolverInfo().m_tau = 0.6f; - world.GetSolverInfo().m_friction = 0.3f; - world.GetSolverInfo().m_maxErrorReduction = 20f; - world.GetSolverInfo().m_numIterations = 10; - world.GetSolverInfo().m_erp = 0.2f; - world.GetSolverInfo().m_erp2 = 0.1f; - world.GetSolverInfo().m_sor = 1.0f; - world.GetSolverInfo().m_splitImpulse = false; - world.GetSolverInfo().m_splitImpulsePenetrationThreshold = -0.02f; - world.GetSolverInfo().m_linearSlop = 0.0f; - world.GetSolverInfo().m_warmstartingFactor = 0.85f; - world.GetSolverInfo().m_restingContactRestitutionThreshold = 2; - world.SetForceUpdateAllAabbs(true); - - - world.SetGravity(new IndexedVector3(0,0,p.gravity)); - - return world; - } - //m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL - public override bool SetConstraintParam(BulletConstraint pConstraint, ConstraintParams paramIndex, float paramvalue, ConstraintParamAxis axis) - { - Generic6DofConstraint constrain = ((BulletConstraintXNA)pConstraint).constrain as Generic6DofConstraint; - if (axis == ConstraintParamAxis.AXIS_LINEAR_ALL || axis == ConstraintParamAxis.AXIS_ALL) - { - constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams) (int) paramIndex, paramvalue, 0); - constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams) (int) paramIndex, paramvalue, 1); - constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams) (int) paramIndex, paramvalue, 2); - } - if (axis == ConstraintParamAxis.AXIS_ANGULAR_ALL || axis == ConstraintParamAxis.AXIS_ALL) - { - constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams)(int)paramIndex, paramvalue, 3); - constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams)(int)paramIndex, paramvalue, 4); - constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams)(int)paramIndex, paramvalue, 5); - } - if (axis == ConstraintParamAxis.AXIS_LINEAR_ALL) - { - constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams)(int)paramIndex, paramvalue, (int)axis); - } - return true; - } - - public override bool PushUpdate(BulletBody pCollisionObject) - { - bool ret = false; - RigidBody rb = ((BulletBodyXNA)pCollisionObject).rigidBody; - if (rb != null) - { - SimMotionState sms = rb.GetMotionState() as SimMotionState; - if (sms != null) - { - IndexedMatrix wt = IndexedMatrix.Identity; - sms.GetWorldTransform(out wt); - sms.SetWorldTransform(ref wt, true); - ret = true; - } - } - return ret; - - } - - public override float GetAngularMotionDisc(BulletShape pShape) - { - CollisionShape shape = ((BulletShapeXNA)pShape).shape; - return shape.GetAngularMotionDisc(); - } - public override float GetContactBreakingThreshold(BulletShape pShape, float defaultFactor) - { - CollisionShape shape = ((BulletShapeXNA)pShape).shape; - return shape.GetContactBreakingThreshold(defaultFactor); - } - public override bool IsCompound(BulletShape pShape) - { - CollisionShape shape = ((BulletShapeXNA)pShape).shape; - return shape.IsCompound(); - } - public override bool IsSoftBody(BulletShape pShape) - { - CollisionShape shape = ((BulletShapeXNA)pShape).shape; - return shape.IsSoftBody(); - } - public override bool IsPolyhedral(BulletShape pShape) - { - CollisionShape shape = ((BulletShapeXNA)pShape).shape; - return shape.IsPolyhedral(); - } - public override bool IsConvex2d(BulletShape pShape) - { - CollisionShape shape = ((BulletShapeXNA)pShape).shape; - return shape.IsConvex2d(); - } - public override bool IsConvex(BulletShape pShape) - { - CollisionShape shape = ((BulletShapeXNA)pShape).shape; - return shape.IsConvex(); - } - public override bool IsNonMoving(BulletShape pShape) - { - CollisionShape shape = ((BulletShapeXNA)pShape).shape; - return shape.IsNonMoving(); - } - public override bool IsConcave(BulletShape pShape) - { - CollisionShape shape = ((BulletShapeXNA)pShape).shape; - return shape.IsConcave(); - } - public override bool IsInfinite(BulletShape pShape) - { - CollisionShape shape = ((BulletShapeXNA)pShape).shape; - return shape.IsInfinite(); - } - public override bool IsNativeShape(BulletShape pShape) - { - CollisionShape shape = ((BulletShapeXNA)pShape).shape; - bool ret; - switch (shape.GetShapeType()) - { - case BroadphaseNativeTypes.BOX_SHAPE_PROXYTYPE: - case BroadphaseNativeTypes.CONE_SHAPE_PROXYTYPE: - case BroadphaseNativeTypes.SPHERE_SHAPE_PROXYTYPE: - case BroadphaseNativeTypes.CYLINDER_SHAPE_PROXYTYPE: - ret = true; - break; - default: - ret = false; - break; - } - return ret; - } - - public override void SetShapeCollisionMargin(BulletShape shape, float margin) { /* TODO */ } - - //sim.ptr, shape.ptr,prim.LocalID, prim.RawPosition, prim.RawOrientation - public override BulletBody CreateGhostFromShape(BulletWorld pWorld, BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation) - { - DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world; - IndexedMatrix bodyTransform = new IndexedMatrix(); - bodyTransform._origin = new IndexedVector3(pRawPosition.X, pRawPosition.Y, pRawPosition.Z); - bodyTransform.SetRotation(new IndexedQuaternion(pRawOrientation.X,pRawOrientation.Y,pRawOrientation.Z,pRawOrientation.W)); - GhostObject gObj = new PairCachingGhostObject(); - gObj.SetWorldTransform(bodyTransform); - CollisionShape shape = ((BulletShapeXNA)pShape).shape; - gObj.SetCollisionShape(shape); - gObj.SetUserPointer(pLocalID); - // TODO: Add to Special CollisionObjects! - return new BulletBodyXNA(pLocalID, gObj); - } - - public override void SetCollisionShape(BulletWorld pWorld, BulletBody pObj, BulletShape pShape) - { - DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world; - CollisionObject obj = ((BulletBodyXNA)pObj).body; - CollisionShape shape = ((BulletShapeXNA)pShape).shape; - obj.SetCollisionShape(shape); - - } - public override BulletShape GetCollisionShape(BulletBody obj) { /* TODO */ return null; } - - //(PhysicsScene.World.ptr, nativeShapeData) - public override BulletShape BuildNativeShape(BulletWorld pWorld, ShapeData pShapeData) - { - DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world; - CollisionShape shape = null; - switch (pShapeData.Type) - { - case BSPhysicsShapeType.SHAPE_BOX: - shape = new BoxShape(new IndexedVector3(0.5f,0.5f,0.5f)); - break; - case BSPhysicsShapeType.SHAPE_CONE: - shape = new ConeShapeZ(0.5f, 1.0f); - break; - case BSPhysicsShapeType.SHAPE_CYLINDER: - shape = new CylinderShapeZ(new IndexedVector3(0.5f, 0.5f, 0.5f)); - break; - case BSPhysicsShapeType.SHAPE_SPHERE: - shape = new SphereShape(0.5f); - break; - - } - if (shape != null) - { - IndexedVector3 scaling = new IndexedVector3(pShapeData.Scale.X, pShapeData.Scale.Y, pShapeData.Scale.Z); - shape.SetMargin(world.WorldSettings.Params.collisionMargin); - shape.SetLocalScaling(ref scaling); - - } - return new BulletShapeXNA(shape, pShapeData.Type); - } - //PhysicsScene.World.ptr, false - public override BulletShape CreateCompoundShape(BulletWorld pWorld, bool enableDynamicAabbTree) - { - return new BulletShapeXNA(new CompoundShape(enableDynamicAabbTree), BSPhysicsShapeType.SHAPE_COMPOUND); - } - - public override int GetNumberOfCompoundChildren(BulletShape pCompoundShape) - { - CompoundShape compoundshape = ((BulletShapeXNA)pCompoundShape).shape as CompoundShape; - return compoundshape.GetNumChildShapes(); - } - //LinksetRoot.PhysShape.ptr, newShape.ptr, displacementPos, displacementRot - public override void AddChildShapeToCompoundShape(BulletShape pCShape, BulletShape paddShape, Vector3 displacementPos, Quaternion displacementRot) - { - IndexedMatrix relativeTransform = new IndexedMatrix(); - CompoundShape compoundshape = ((BulletShapeXNA)pCShape).shape as CompoundShape; - CollisionShape addshape = ((BulletShapeXNA)paddShape).shape; - - relativeTransform._origin = new IndexedVector3(displacementPos.X, displacementPos.Y, displacementPos.Z); - relativeTransform.SetRotation(new IndexedQuaternion(displacementRot.X,displacementRot.Y,displacementRot.Z,displacementRot.W)); - compoundshape.AddChildShape(ref relativeTransform, addshape); - - } - - public override BulletShape RemoveChildShapeFromCompoundShapeIndex(BulletShape pCShape, int pii) - { - CompoundShape compoundshape = ((BulletShapeXNA)pCShape).shape as CompoundShape; - CollisionShape ret = null; - ret = compoundshape.GetChildShape(pii); - compoundshape.RemoveChildShapeByIndex(pii); - return new BulletShapeXNA(ret, BSPhysicsShapeType.SHAPE_UNKNOWN); - } - - public override BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx) { /* TODO */ return null; } - public override void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape) { /* TODO */ } - - public override BulletShape CreateGroundPlaneShape(uint pLocalId, float pheight, float pcollisionMargin) - { - StaticPlaneShape m_planeshape = new StaticPlaneShape(new IndexedVector3(0,0,1),(int)pheight ); - m_planeshape.SetMargin(pcollisionMargin); - m_planeshape.SetUserPointer(pLocalId); - return new BulletShapeXNA(m_planeshape, BSPhysicsShapeType.SHAPE_GROUNDPLANE); - } - - public override BulletConstraint CreateHingeConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody ppBody2, Vector3 ppivotInA, Vector3 ppivotInB, Vector3 paxisInA, Vector3 paxisInB, bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies) - { - HingeConstraint constrain = null; - DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world; - RigidBody rb1 = ((BulletBodyXNA)pBody1).rigidBody; - RigidBody rb2 = ((BulletBodyXNA)ppBody2).rigidBody; - if (rb1 != null && rb2 != null) - { - IndexedVector3 pivotInA = new IndexedVector3(ppivotInA.X, ppivotInA.Y, ppivotInA.Z); - IndexedVector3 pivotInB = new IndexedVector3(ppivotInB.X, ppivotInB.Y, ppivotInB.Z); - IndexedVector3 axisInA = new IndexedVector3(paxisInA.X, paxisInA.Y, paxisInA.Z); - IndexedVector3 axisInB = new IndexedVector3(paxisInB.X, paxisInB.Y, paxisInB.Z); - world.AddConstraint(constrain, pdisableCollisionsBetweenLinkedBodies); - } - return new BulletConstraintXNA(constrain); - } - - public override BulletShape CreateHullShape(BulletWorld pWorld, int pHullCount, float[] pConvHulls) - { - DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world; - CompoundShape compoundshape = new CompoundShape(false); - - compoundshape.SetMargin(world.WorldSettings.Params.collisionMargin); - int ii = 1; - - for (int i = 0; i < pHullCount; i++) - { - int vertexCount = (int) pConvHulls[ii]; - - IndexedVector3 centroid = new IndexedVector3(pConvHulls[ii + 1], pConvHulls[ii + 2], pConvHulls[ii + 3]); - IndexedMatrix childTrans = IndexedMatrix.Identity; - childTrans._origin = centroid; - - List virts = new List(); - int ender = ((ii + 4) + (vertexCount*3)); - for (int iii = ii + 4; iii < ender; iii+=3) - { - - virts.Add(new IndexedVector3(pConvHulls[iii], pConvHulls[iii + 1], pConvHulls[iii +2])); - } - ConvexHullShape convexShape = new ConvexHullShape(virts, vertexCount); - convexShape.SetMargin(world.WorldSettings.Params.collisionMargin); - compoundshape.AddChildShape(ref childTrans, convexShape); - ii += (vertexCount*3 + 4); - } - - return new BulletShapeXNA(compoundshape, BSPhysicsShapeType.SHAPE_HULL); - } - - public override BulletShape BuildHullShapeFromMesh(BulletWorld world, BulletShape meshShape) { /* TODO */ return null; } - - public override BulletShape CreateMeshShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats) - { - //DumpRaw(indices,verticesAsFloats,pIndicesCount,pVerticesCount); - - for (int iter = 0; iter < pVerticesCount; iter++) - { - if (verticesAsFloats[iter] > 0 && verticesAsFloats[iter] < 0.0001) verticesAsFloats[iter] = 0; - if (verticesAsFloats[iter] < 0 && verticesAsFloats[iter] > -0.0001) verticesAsFloats[iter] = 0; - } - - ObjectArray indicesarr = new ObjectArray(indices); - ObjectArray vertices = new ObjectArray(verticesAsFloats); - DumpRaw(indicesarr,vertices,pIndicesCount,pVerticesCount); - DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world; - IndexedMesh mesh = new IndexedMesh(); - mesh.m_indexType = PHY_ScalarType.PHY_INTEGER; - mesh.m_numTriangles = pIndicesCount/3; - mesh.m_numVertices = pVerticesCount; - mesh.m_triangleIndexBase = indicesarr; - mesh.m_vertexBase = vertices; - mesh.m_vertexStride = 3; - mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT; - mesh.m_triangleIndexStride = 3; - - TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray(); - tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER); - BvhTriangleMeshShape meshShape = new BvhTriangleMeshShape(tribuilder, true,true); - meshShape.SetMargin(world.WorldSettings.Params.collisionMargin); - // world.UpdateSingleAabb(meshShape); - return new BulletShapeXNA(meshShape, BSPhysicsShapeType.SHAPE_MESH); - - } - public static void DumpRaw(ObjectArrayindices, ObjectArray vertices, int pIndicesCount,int pVerticesCount ) - { - - String fileName = "objTest3.raw"; - String completePath = System.IO.Path.Combine(Util.configDir(), fileName); - StreamWriter sw = new StreamWriter(completePath); - IndexedMesh mesh = new IndexedMesh(); - - mesh.m_indexType = PHY_ScalarType.PHY_INTEGER; - mesh.m_numTriangles = pIndicesCount / 3; - mesh.m_numVertices = pVerticesCount; - mesh.m_triangleIndexBase = indices; - mesh.m_vertexBase = vertices; - mesh.m_vertexStride = 3; - mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT; - mesh.m_triangleIndexStride = 3; - - TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray(); - tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER); - - - - for (int i = 0; i < pVerticesCount; i++) - { - - string s = vertices[indices[i * 3]].ToString("0.0000"); - s += " " + vertices[indices[i * 3 + 1]].ToString("0.0000"); - s += " " + vertices[indices[i * 3 + 2]].ToString("0.0000"); - - sw.Write(s + "\n"); - } - - sw.Close(); - } - public static void DumpRaw(int[] indices, float[] vertices, int pIndicesCount, int pVerticesCount) - { - - String fileName = "objTest6.raw"; - String completePath = System.IO.Path.Combine(Util.configDir(), fileName); - StreamWriter sw = new StreamWriter(completePath); - IndexedMesh mesh = new IndexedMesh(); - - mesh.m_indexType = PHY_ScalarType.PHY_INTEGER; - mesh.m_numTriangles = pIndicesCount / 3; - mesh.m_numVertices = pVerticesCount; - mesh.m_triangleIndexBase = indices; - mesh.m_vertexBase = vertices; - mesh.m_vertexStride = 3; - mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT; - mesh.m_triangleIndexStride = 3; - - TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray(); - tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER); - - - sw.WriteLine("Indices"); - sw.WriteLine(string.Format("int[] indices = new int[{0}];",pIndicesCount)); - for (int iter = 0; iter < indices.Length; iter++) - { - sw.WriteLine(string.Format("indices[{0}]={1};",iter,indices[iter])); - } - sw.WriteLine("VerticesFloats"); - sw.WriteLine(string.Format("float[] vertices = new float[{0}];", pVerticesCount)); - for (int iter = 0; iter < vertices.Length; iter++) - { - sw.WriteLine(string.Format("Vertices[{0}]={1};", iter, vertices[iter].ToString("0.0000"))); - } - - // for (int i = 0; i < pVerticesCount; i++) - // { - // - // string s = vertices[indices[i * 3]].ToString("0.0000"); - // s += " " + vertices[indices[i * 3 + 1]].ToString("0.0000"); - // s += " " + vertices[indices[i * 3 + 2]].ToString("0.0000"); - // - // sw.Write(s + "\n"); - //} - - sw.Close(); - } - - public override BulletShape CreateTerrainShape(uint id, Vector3 size, float minHeight, float maxHeight, float[] heightMap, - float scaleFactor, float collisionMargin) - { - const int upAxis = 2; - HeightfieldTerrainShape terrainShape = new HeightfieldTerrainShape((int)size.X, (int)size.Y, - heightMap, scaleFactor, - minHeight, maxHeight, upAxis, - false); - terrainShape.SetMargin(collisionMargin + 0.5f); - terrainShape.SetUseDiamondSubdivision(true); - terrainShape.SetUserPointer(id); - return new BulletShapeXNA(terrainShape, BSPhysicsShapeType.SHAPE_TERRAIN); - } - - public override bool TranslationalLimitMotor(BulletConstraint pConstraint, float ponOff, float targetVelocity, float maxMotorForce) - { - TypedConstraint tconstrain = ((BulletConstraintXNA)pConstraint).constrain; - bool onOff = ponOff != 0; - bool ret = false; - - switch (tconstrain.GetConstraintType()) - { - case TypedConstraintType.D6_CONSTRAINT_TYPE: - Generic6DofConstraint constrain = tconstrain as Generic6DofConstraint; - constrain.GetTranslationalLimitMotor().m_enableMotor[0] = onOff; - constrain.GetTranslationalLimitMotor().m_targetVelocity[0] = targetVelocity; - constrain.GetTranslationalLimitMotor().m_maxMotorForce[0] = maxMotorForce; - ret = true; - break; - } - - - return ret; - - } - - public override int PhysicsStep(BulletWorld world, float timeStep, int maxSubSteps, float fixedTimeStep, - out int updatedEntityCount, out int collidersCount) - { - /* TODO */ - updatedEntityCount = 0; - collidersCount = 0; - return 1; - } - - private int PhysicsStep2(BulletWorld pWorld, float timeStep, int m_maxSubSteps, float m_fixedTimeStep, - out int updatedEntityCount, out List updatedEntities, - out int collidersCount, out Listcolliders) - { - int epic = PhysicsStepint(pWorld, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out updatedEntities, - out collidersCount, out colliders); - return epic; - } - - private static int PhysicsStepint(BulletWorld pWorld,float timeStep, int m_maxSubSteps, float m_fixedTimeStep, out int updatedEntityCount, out List updatedEntities, out int collidersCount, out List colliders) - { - int numSimSteps = 0; - - - //if (updatedEntities is null) - // updatedEntities = new List(); - - //if (colliders is null) - // colliders = new List(); - - - if (pWorld is BulletWorldXNA) - { - DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world; - - numSimSteps = world.StepSimulation(timeStep, m_maxSubSteps, m_fixedTimeStep); - int updates = 0; - - updatedEntityCount = world.UpdatedObjects.Count; - updatedEntities = new List(world.UpdatedObjects); - updatedEntityCount = updatedEntities.Count; - world.UpdatedObjects.Clear(); - - - collidersCount = world.UpdatedCollisions.Count; - colliders = new List(world.UpdatedCollisions); - - world.UpdatedCollisions.Clear(); - m_collisionsThisFrame = 0; - int numManifolds = world.GetDispatcher().GetNumManifolds(); - for (int j = 0; j < numManifolds; j++) - { - PersistentManifold contactManifold = world.GetDispatcher().GetManifoldByIndexInternal(j); - int numContacts = contactManifold.GetNumContacts(); - if (numContacts == 0) - continue; - - CollisionObject objA = contactManifold.GetBody0() as CollisionObject; - CollisionObject objB = contactManifold.GetBody1() as CollisionObject; - - ManifoldPoint manifoldPoint = contactManifold.GetContactPoint(0); - IndexedVector3 contactPoint = manifoldPoint.GetPositionWorldOnB(); - IndexedVector3 contactNormal = -manifoldPoint.m_normalWorldOnB; // make relative to A - - RecordCollision(world, objA, objB, contactPoint, contactNormal); - m_collisionsThisFrame ++; - if (m_collisionsThisFrame >= 9999999) - break; - - - } - - - } - else - { - //if (updatedEntities is null) - updatedEntities = new List(); - updatedEntityCount = 0; - //if (colliders is null) - colliders = new List(); - collidersCount = 0; - } - return numSimSteps; - } - - private static void RecordCollision(CollisionWorld world, CollisionObject objA, CollisionObject objB, IndexedVector3 contact, IndexedVector3 norm) - { - - IndexedVector3 contactNormal = norm; - if ((objA.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0 && - (objB.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0) - { - return; - } - uint idA = (uint)objA.GetUserPointer(); - uint idB = (uint)objB.GetUserPointer(); - if (idA > idB) - { - uint temp = idA; - idA = idB; - idB = temp; - contactNormal = -contactNormal; - } - - ulong collisionID = ((ulong) idA << 32) | idB; - - BulletXNA.CollisionDesc cDesc = new BulletXNA.CollisionDesc() - { - aID = idA, - bID = idB, - point = contact, - normal = contactNormal - }; - world.UpdatedCollisions.Add(cDesc); - m_collisionsThisFrame++; - - - } - private static EntityProperties GetDebugProperties(BulletWorld pWorld, BulletBody pBody) - { - EntityProperties ent = new EntityProperties(); - DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world; - RigidBody body = ((BulletBodyXNA)pBody).rigidBody; - IndexedMatrix transform = body.GetWorldTransform(); - IndexedVector3 LinearVelocity = body.GetInterpolationLinearVelocity(); - IndexedVector3 AngularVelocity = body.GetInterpolationAngularVelocity(); - IndexedQuaternion rotation = transform.GetRotation(); - ent.Acceleration = Vector3.Zero; - ent.ID = (uint)body.GetUserPointer(); - ent.Position = new Vector3(transform._origin.X,transform._origin.Y,transform._origin.Z); - ent.Rotation = new Quaternion(rotation.X,rotation.Y,rotation.Z,rotation.W); - ent.Velocity = new Vector3(LinearVelocity.X, LinearVelocity.Y, LinearVelocity.Z); - ent.RotationalVelocity = new Vector3(AngularVelocity.X, AngularVelocity.Y, AngularVelocity.Z); - return ent; - } - - public override bool UpdateParameter(BulletWorld world, uint localID, String parm, float value) { /* TODO */ return false; } - - public override Vector3 GetLocalScaling(BulletShape pShape) - { - CollisionShape shape = ((BulletShapeXNA)pShape).shape; - IndexedVector3 scale = shape.GetLocalScaling(); - return new Vector3(scale.X,scale.Y,scale.Z); - } - - public bool RayCastGround(BulletWorld pWorld, Vector3 _RayOrigin, float pRayHeight, BulletBody NotMe) - { - DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world; - if (world != null) - { - if (NotMe is BulletBodyXNA && NotMe.HasPhysicalBody) - { - CollisionObject AvoidBody = ((BulletBodyXNA)NotMe).body; - - IndexedVector3 rOrigin = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z); - IndexedVector3 rEnd = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z - pRayHeight); - using ( - ClosestNotMeRayResultCallback rayCallback = - new ClosestNotMeRayResultCallback(rOrigin, rEnd, AvoidBody) - ) - { - world.RayTest(ref rOrigin, ref rEnd, rayCallback); - if (rayCallback.HasHit()) - { - IndexedVector3 hitLocation = rayCallback.m_hitPointWorld; - } - return rayCallback.HasHit(); - } - } - } - return false; - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs deleted file mode 100644 index 8ad78ca..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs +++ /dev/null @@ -1,662 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Security; -using System.Text; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin { - - // Constraint type values as defined by Bullet -public enum ConstraintType : int -{ - POINT2POINT_CONSTRAINT_TYPE = 3, - HINGE_CONSTRAINT_TYPE, - CONETWIST_CONSTRAINT_TYPE, - D6_CONSTRAINT_TYPE, - SLIDER_CONSTRAINT_TYPE, - CONTACT_CONSTRAINT_TYPE, - D6_SPRING_CONSTRAINT_TYPE, - MAX_CONSTRAINT_TYPE -} - -// =============================================================================== -[StructLayout(LayoutKind.Sequential)] -public struct ConvexHull -{ - Vector3 Offset; - int VertexCount; - Vector3[] Vertices; -} -public enum BSPhysicsShapeType -{ - SHAPE_UNKNOWN = 0, - SHAPE_CAPSULE = 1, - SHAPE_BOX = 2, - SHAPE_CONE = 3, - SHAPE_CYLINDER = 4, - SHAPE_SPHERE = 5, - SHAPE_MESH = 6, - SHAPE_HULL = 7, - // following defined by BulletSim - SHAPE_GROUNDPLANE = 20, - SHAPE_TERRAIN = 21, - SHAPE_COMPOUND = 22, - SHAPE_HEIGHTMAP = 23, - SHAPE_AVATAR = 24, -}; - -// The native shapes have predefined shape hash keys -public enum FixedShapeKey : ulong -{ - KEY_NONE = 0, - KEY_BOX = 1, - KEY_SPHERE = 2, - KEY_CONE = 3, - KEY_CYLINDER = 4, - KEY_CAPSULE = 5, - KEY_AVATAR = 6, -} - -[StructLayout(LayoutKind.Sequential)] -public struct ShapeData -{ - public uint ID; - public BSPhysicsShapeType Type; - public Vector3 Position; - public Quaternion Rotation; - public Vector3 Velocity; - public Vector3 Scale; - public float Mass; - public float Buoyancy; - public System.UInt64 HullKey; - public System.UInt64 MeshKey; - public float Friction; - public float Restitution; - public float Collidable; // true of things bump into this - public float Static; // true if a static object. Otherwise gravity, etc. - public float Solid; // true if object cannot be passed through - public Vector3 Size; - - // note that bools are passed as floats since bool size changes by language and architecture - public const float numericTrue = 1f; - public const float numericFalse = 0f; -} -[StructLayout(LayoutKind.Sequential)] -public struct SweepHit -{ - public uint ID; - public float Fraction; - public Vector3 Normal; - public Vector3 Point; -} -[StructLayout(LayoutKind.Sequential)] -public struct RaycastHit -{ - public uint ID; - public float Fraction; - public Vector3 Normal; -} -[StructLayout(LayoutKind.Sequential)] -public struct CollisionDesc -{ - public uint aID; - public uint bID; - public Vector3 point; - public Vector3 normal; -} -[StructLayout(LayoutKind.Sequential)] -public struct EntityProperties -{ - public uint ID; - public Vector3 Position; - public Quaternion Rotation; - public Vector3 Velocity; - public Vector3 Acceleration; - public Vector3 RotationalVelocity; -} - -// Format of this structure must match the definition in the C++ code -// NOTE: adding the X causes compile breaks if used. These are unused symbols -// that can be removed from both here and the unmanaged definition of this structure. -[StructLayout(LayoutKind.Sequential)] -public struct ConfigurationParameters -{ - public float defaultFriction; - public float defaultDensity; - public float defaultRestitution; - public float collisionMargin; - public float gravity; - - public float XlinearDamping; - public float XangularDamping; - public float XdeactivationTime; - public float XlinearSleepingThreshold; - public float XangularSleepingThreshold; - public float XccdMotionThreshold; - public float XccdSweptSphereRadius; - public float XcontactProcessingThreshold; - - public float XterrainImplementation; - public float XterrainFriction; - public float XterrainHitFraction; - public float XterrainRestitution; - public float XterrainCollisionMargin; - - public float XavatarFriction; - public float XavatarStandingFriction; - public float XavatarDensity; - public float XavatarRestitution; - public float XavatarCapsuleWidth; - public float XavatarCapsuleDepth; - public float XavatarCapsuleHeight; - public float XavatarContactProcessingThreshold; - - public float XvehicleAngularDamping; - - public float maxPersistantManifoldPoolSize; - public float maxCollisionAlgorithmPoolSize; - public float shouldDisableContactPoolDynamicAllocation; - public float shouldForceUpdateAllAabbs; - public float shouldRandomizeSolverOrder; - public float shouldSplitSimulationIslands; - public float shouldEnableFrictionCaching; - public float numberOfSolverIterations; - - public float XlinksetImplementation; - public float XlinkConstraintUseFrameOffset; - public float XlinkConstraintEnableTransMotor; - public float XlinkConstraintTransMotorMaxVel; - public float XlinkConstraintTransMotorMaxForce; - public float XlinkConstraintERP; - public float XlinkConstraintCFM; - public float XlinkConstraintSolverIterations; - - public float XphysicsLoggingFrames; - - public const float numericTrue = 1f; - public const float numericFalse = 0f; -} - - -// The states a bullet collision object can have -public enum ActivationState : uint -{ - ACTIVE_TAG = 1, - ISLAND_SLEEPING, - WANTS_DEACTIVATION, - DISABLE_DEACTIVATION, - DISABLE_SIMULATION, -} - -public enum CollisionObjectTypes : int -{ - CO_COLLISION_OBJECT = 1 << 0, - CO_RIGID_BODY = 1 << 1, - CO_GHOST_OBJECT = 1 << 2, - CO_SOFT_BODY = 1 << 3, - CO_HF_FLUID = 1 << 4, - CO_USER_TYPE = 1 << 5, -} - -// Values used by Bullet and BulletSim to control object properties. -// Bullet's "CollisionFlags" has more to do with operations on the -// object (if collisions happen, if gravity effects it, ...). -public enum CollisionFlags : uint -{ - CF_STATIC_OBJECT = 1 << 0, - CF_KINEMATIC_OBJECT = 1 << 1, - CF_NO_CONTACT_RESPONSE = 1 << 2, - CF_CUSTOM_MATERIAL_CALLBACK = 1 << 3, - CF_CHARACTER_OBJECT = 1 << 4, - CF_DISABLE_VISUALIZE_OBJECT = 1 << 5, - CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6, - // Following used by BulletSim to control collisions and updates - BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, - BS_FLOATS_ON_WATER = 1 << 11, - BS_VEHICLE_COLLISIONS = 1 << 12, - BS_NONE = 0, - BS_ALL = 0xFFFFFFFF -}; - -// Values f collisions groups and masks -public enum CollisionFilterGroups : uint -{ - // Don't use the bit definitions!! Define the use in a - // filter/mask definition below. This way collision interactions - // are more easily found and debugged. - BNoneGroup = 0, - BDefaultGroup = 1 << 0, // 0001 - BStaticGroup = 1 << 1, // 0002 - BKinematicGroup = 1 << 2, // 0004 - BDebrisGroup = 1 << 3, // 0008 - BSensorTrigger = 1 << 4, // 0010 - BCharacterGroup = 1 << 5, // 0020 - BAllGroup = 0x000FFFFF, - // Filter groups defined by BulletSim - BGroundPlaneGroup = 1 << 10, // 0400 - BTerrainGroup = 1 << 11, // 0800 - BRaycastGroup = 1 << 12, // 1000 - BSolidGroup = 1 << 13, // 2000 - // BLinksetGroup = xx // a linkset proper is either static or dynamic - BLinksetChildGroup = 1 << 14, // 4000 -}; - -// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 -// ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2. -public enum ConstraintParams : int -{ - BT_CONSTRAINT_ERP = 1, // this one is not used in Bullet as of 20120730 - BT_CONSTRAINT_STOP_ERP, - BT_CONSTRAINT_CFM, - BT_CONSTRAINT_STOP_CFM, -}; -public enum ConstraintParamAxis : int -{ - AXIS_LINEAR_X = 0, - AXIS_LINEAR_Y, - AXIS_LINEAR_Z, - AXIS_ANGULAR_X, - AXIS_ANGULAR_Y, - AXIS_ANGULAR_Z, - AXIS_LINEAR_ALL = 20, // these last three added by BulletSim so we don't have to do zillions of calls - AXIS_ANGULAR_ALL, - AXIS_ALL -}; - -public abstract class BSAPITemplate -{ -// Returns the name of the underlying Bullet engine -public abstract string BulletEngineName { get; } -public abstract string BulletEngineVersion { get; protected set;} - -// Initialization and simulation -public abstract BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms, - int maxCollisions, ref CollisionDesc[] collisionArray, - int maxUpdates, ref EntityProperties[] updateArray - ); - -public abstract int PhysicsStep(BulletWorld world, float timeStep, int maxSubSteps, float fixedTimeStep, - out int updatedEntityCount, out int collidersCount); - -public abstract bool UpdateParameter(BulletWorld world, uint localID, String parm, float value); - -public abstract void Shutdown(BulletWorld sim); - -public abstract bool PushUpdate(BulletBody obj); - -// ===================================================================================== -// Mesh, hull, shape and body creation helper routines -public abstract BulletShape CreateMeshShape(BulletWorld world, - int indicesCount, int[] indices, - int verticesCount, float[] vertices ); - -public abstract BulletShape CreateHullShape(BulletWorld world, - int hullCount, float[] hulls); - -public abstract BulletShape BuildHullShapeFromMesh(BulletWorld world, BulletShape meshShape); - -public abstract BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData); - -public abstract bool IsNativeShape(BulletShape shape); - -public abstract void SetShapeCollisionMargin(BulletShape shape, float margin); - -public abstract BulletShape BuildCapsuleShape(BulletWorld world, float radius, float height, Vector3 scale); - -public abstract BulletShape CreateCompoundShape(BulletWorld sim, bool enableDynamicAabbTree); - -public abstract int GetNumberOfCompoundChildren(BulletShape cShape); - -public abstract void AddChildShapeToCompoundShape(BulletShape cShape, BulletShape addShape, Vector3 pos, Quaternion rot); - -public abstract BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx); - -public abstract BulletShape RemoveChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx); - -public abstract void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape); - -public abstract void RecalculateCompoundShapeLocalAabb(BulletShape cShape); - -public abstract BulletShape DuplicateCollisionShape(BulletWorld sim, BulletShape srcShape, uint id); - -public abstract bool DeleteCollisionShape(BulletWorld world, BulletShape shape); - -public abstract CollisionObjectTypes GetBodyType(BulletBody obj); - -public abstract BulletBody CreateBodyFromShape(BulletWorld sim, BulletShape shape, uint id, Vector3 pos, Quaternion rot); - -public abstract BulletBody CreateBodyWithDefaultMotionState(BulletShape shape, uint id, Vector3 pos, Quaternion rot); - -public abstract BulletBody CreateGhostFromShape(BulletWorld sim, BulletShape shape, uint id, Vector3 pos, Quaternion rot); - -public abstract void DestroyObject(BulletWorld sim, BulletBody obj); - -// ===================================================================================== -public abstract BulletShape CreateGroundPlaneShape(uint id, float height, float collisionMargin); - -public abstract BulletShape CreateTerrainShape(uint id, Vector3 size, float minHeight, float maxHeight, float[] heightMap, - float scaleFactor, float collisionMargin); - -// ===================================================================================== -// Constraint creation and helper routines -public abstract BulletConstraint Create6DofConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2, - Vector3 frame1loc, Quaternion frame1rot, - Vector3 frame2loc, Quaternion frame2rot, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); - -public abstract BulletConstraint Create6DofConstraintToPoint(BulletWorld world, BulletBody obj1, BulletBody obj2, - Vector3 joinPoint, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); - -public abstract BulletConstraint CreateHingeConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2, - Vector3 pivotinA, Vector3 pivotinB, - Vector3 axisInA, Vector3 axisInB, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); - -public abstract void SetConstraintEnable(BulletConstraint constrain, float numericTrueFalse); - -public abstract void SetConstraintNumSolverIterations(BulletConstraint constrain, float iterations); - -public abstract bool SetFrames(BulletConstraint constrain, - Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot); - -public abstract bool SetLinearLimits(BulletConstraint constrain, Vector3 low, Vector3 hi); - -public abstract bool SetAngularLimits(BulletConstraint constrain, Vector3 low, Vector3 hi); - -public abstract bool UseFrameOffset(BulletConstraint constrain, float enable); - -public abstract bool TranslationalLimitMotor(BulletConstraint constrain, float enable, float targetVel, float maxMotorForce); - -public abstract bool SetBreakingImpulseThreshold(BulletConstraint constrain, float threshold); - -public abstract bool CalculateTransforms(BulletConstraint constrain); - -public abstract bool SetConstraintParam(BulletConstraint constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis); - -public abstract bool DestroyConstraint(BulletWorld world, BulletConstraint constrain); - -// ===================================================================================== -// btCollisionWorld entries -public abstract void UpdateSingleAabb(BulletWorld world, BulletBody obj); - -public abstract void UpdateAabbs(BulletWorld world); - -public abstract bool GetForceUpdateAllAabbs(BulletWorld world); - -public abstract void SetForceUpdateAllAabbs(BulletWorld world, bool force); - -// ===================================================================================== -// btDynamicsWorld entries -// public abstract bool AddObjectToWorld(BulletWorld world, BulletBody obj, Vector3 pos, Quaternion rot); -public abstract bool AddObjectToWorld(BulletWorld world, BulletBody obj); - -public abstract bool RemoveObjectFromWorld(BulletWorld world, BulletBody obj); - -public abstract bool AddConstraintToWorld(BulletWorld world, BulletConstraint constrain, bool disableCollisionsBetweenLinkedObjects); - -public abstract bool RemoveConstraintFromWorld(BulletWorld world, BulletConstraint constrain); -// ===================================================================================== -// btCollisionObject entries -public abstract Vector3 GetAnisotripicFriction(BulletConstraint constrain); - -public abstract Vector3 SetAnisotripicFriction(BulletConstraint constrain, Vector3 frict); - -public abstract bool HasAnisotripicFriction(BulletConstraint constrain); - -public abstract void SetContactProcessingThreshold(BulletBody obj, float val); - -public abstract float GetContactProcessingThreshold(BulletBody obj); - -public abstract bool IsStaticObject(BulletBody obj); - -public abstract bool IsKinematicObject(BulletBody obj); - -public abstract bool IsStaticOrKinematicObject(BulletBody obj); - -public abstract bool HasContactResponse(BulletBody obj); - -public abstract void SetCollisionShape(BulletWorld sim, BulletBody obj, BulletShape shape); - -public abstract BulletShape GetCollisionShape(BulletBody obj); - -public abstract int GetActivationState(BulletBody obj); - -public abstract void SetActivationState(BulletBody obj, int state); - -public abstract void SetDeactivationTime(BulletBody obj, float dtime); - -public abstract float GetDeactivationTime(BulletBody obj); - -public abstract void ForceActivationState(BulletBody obj, ActivationState state); - -public abstract void Activate(BulletBody obj, bool forceActivation); - -public abstract bool IsActive(BulletBody obj); - -public abstract void SetRestitution(BulletBody obj, float val); - -public abstract float GetRestitution(BulletBody obj); - -public abstract void SetFriction(BulletBody obj, float val); - -public abstract float GetFriction(BulletBody obj); - -public abstract Vector3 GetPosition(BulletBody obj); - -public abstract Quaternion GetOrientation(BulletBody obj); - -public abstract void SetTranslation(BulletBody obj, Vector3 position, Quaternion rotation); - -// public abstract IntPtr GetBroadphaseHandle(BulletBody obj); - -// public abstract void SetBroadphaseHandle(BulletBody obj, IntPtr handle); - -public abstract void SetInterpolationLinearVelocity(BulletBody obj, Vector3 vel); - -public abstract void SetInterpolationAngularVelocity(BulletBody obj, Vector3 vel); - -public abstract void SetInterpolationVelocity(BulletBody obj, Vector3 linearVel, Vector3 angularVel); - -public abstract float GetHitFraction(BulletBody obj); - -public abstract void SetHitFraction(BulletBody obj, float val); - -public abstract CollisionFlags GetCollisionFlags(BulletBody obj); - -public abstract CollisionFlags SetCollisionFlags(BulletBody obj, CollisionFlags flags); - -public abstract CollisionFlags AddToCollisionFlags(BulletBody obj, CollisionFlags flags); - -public abstract CollisionFlags RemoveFromCollisionFlags(BulletBody obj, CollisionFlags flags); - -public abstract float GetCcdMotionThreshold(BulletBody obj); - -public abstract void SetCcdMotionThreshold(BulletBody obj, float val); - -public abstract float GetCcdSweptSphereRadius(BulletBody obj); - -public abstract void SetCcdSweptSphereRadius(BulletBody obj, float val); - -public abstract IntPtr GetUserPointer(BulletBody obj); - -public abstract void SetUserPointer(BulletBody obj, IntPtr val); - -// ===================================================================================== -// btRigidBody entries -public abstract void ApplyGravity(BulletBody obj); - -public abstract void SetGravity(BulletBody obj, Vector3 val); - -public abstract Vector3 GetGravity(BulletBody obj); - -public abstract void SetDamping(BulletBody obj, float lin_damping, float ang_damping); - -public abstract void SetLinearDamping(BulletBody obj, float lin_damping); - -public abstract void SetAngularDamping(BulletBody obj, float ang_damping); - -public abstract float GetLinearDamping(BulletBody obj); - -public abstract float GetAngularDamping(BulletBody obj); - -public abstract float GetLinearSleepingThreshold(BulletBody obj); - -public abstract void ApplyDamping(BulletBody obj, float timeStep); - -public abstract void SetMassProps(BulletBody obj, float mass, Vector3 inertia); - -public abstract Vector3 GetLinearFactor(BulletBody obj); - -public abstract void SetLinearFactor(BulletBody obj, Vector3 factor); - -public abstract void SetCenterOfMassByPosRot(BulletBody obj, Vector3 pos, Quaternion rot); - -// Add a force to the object as if its mass is one. -public abstract void ApplyCentralForce(BulletBody obj, Vector3 force); - -// Set the force being applied to the object as if its mass is one. -public abstract void SetObjectForce(BulletBody obj, Vector3 force); - -public abstract Vector3 GetTotalForce(BulletBody obj); - -public abstract Vector3 GetTotalTorque(BulletBody obj); - -public abstract Vector3 GetInvInertiaDiagLocal(BulletBody obj); - -public abstract void SetInvInertiaDiagLocal(BulletBody obj, Vector3 inert); - -public abstract void SetSleepingThresholds(BulletBody obj, float lin_threshold, float ang_threshold); - -public abstract void ApplyTorque(BulletBody obj, Vector3 torque); - -// Apply force at the given point. Will add torque to the object. -public abstract void ApplyForce(BulletBody obj, Vector3 force, Vector3 pos); - -// Apply impulse to the object. Same as "ApplycentralForce" but force scaled by object's mass. -public abstract void ApplyCentralImpulse(BulletBody obj, Vector3 imp); - -// Apply impulse to the object's torque. Force is scaled by object's mass. -public abstract void ApplyTorqueImpulse(BulletBody obj, Vector3 imp); - -// Apply impulse at the point given. For is scaled by object's mass and effects both linear and angular forces. -public abstract void ApplyImpulse(BulletBody obj, Vector3 imp, Vector3 pos); - -public abstract void ClearForces(BulletBody obj); - -public abstract void ClearAllForces(BulletBody obj); - -public abstract void UpdateInertiaTensor(BulletBody obj); - -public abstract Vector3 GetLinearVelocity(BulletBody obj); - -public abstract Vector3 GetAngularVelocity(BulletBody obj); - -public abstract void SetLinearVelocity(BulletBody obj, Vector3 val); - -public abstract void SetAngularVelocity(BulletBody obj, Vector3 angularVelocity); - -public abstract Vector3 GetVelocityInLocalPoint(BulletBody obj, Vector3 pos); - -public abstract void Translate(BulletBody obj, Vector3 trans); - -public abstract void UpdateDeactivation(BulletBody obj, float timeStep); - -public abstract bool WantsSleeping(BulletBody obj); - -public abstract void SetAngularFactor(BulletBody obj, float factor); - -public abstract void SetAngularFactorV(BulletBody obj, Vector3 factor); - -public abstract Vector3 GetAngularFactor(BulletBody obj); - -public abstract bool IsInWorld(BulletWorld world, BulletBody obj); - -public abstract void AddConstraintRef(BulletBody obj, BulletConstraint constrain); - -public abstract void RemoveConstraintRef(BulletBody obj, BulletConstraint constrain); - -public abstract BulletConstraint GetConstraintRef(BulletBody obj, int index); - -public abstract int GetNumConstraintRefs(BulletBody obj); - -public abstract bool SetCollisionGroupMask(BulletBody body, uint filter, uint mask); - -// ===================================================================================== -// btCollisionShape entries - -public abstract float GetAngularMotionDisc(BulletShape shape); - -public abstract float GetContactBreakingThreshold(BulletShape shape, float defaultFactor); - -public abstract bool IsPolyhedral(BulletShape shape); - -public abstract bool IsConvex2d(BulletShape shape); - -public abstract bool IsConvex(BulletShape shape); - -public abstract bool IsNonMoving(BulletShape shape); - -public abstract bool IsConcave(BulletShape shape); - -public abstract bool IsCompound(BulletShape shape); - -public abstract bool IsSoftBody(BulletShape shape); - -public abstract bool IsInfinite(BulletShape shape); - -public abstract void SetLocalScaling(BulletShape shape, Vector3 scale); - -public abstract Vector3 GetLocalScaling(BulletShape shape); - -public abstract Vector3 CalculateLocalInertia(BulletShape shape, float mass); - -public abstract int GetShapeType(BulletShape shape); - -public abstract void SetMargin(BulletShape shape, float val); - -public abstract float GetMargin(BulletShape shape); - -// ===================================================================================== -// Debugging -public abstract void DumpRigidBody(BulletWorld sim, BulletBody collisionObject); - -public abstract void DumpCollisionShape(BulletWorld sim, BulletShape collisionShape); - -public abstract void DumpConstraint(BulletWorld sim, BulletConstraint constrain); - -public abstract void DumpActivationInfo(BulletWorld sim); - -public abstract void DumpAllInfo(BulletWorld sim); - -public abstract void DumpPhysicsStatistics(BulletWorld sim); - -}; -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs deleted file mode 100644 index 103d8fc..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ /dev/null @@ -1,827 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Reflection; -using log4net; -using OMV = OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public sealed class BSCharacter : BSPhysObject -{ - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private static readonly string LogHeader = "[BULLETS CHAR]"; - - // private bool _stopped; - private OMV.Vector3 _size; - private bool _grabbed; - private bool _selected; - private OMV.Vector3 _position; - private float _mass; - private float _avatarDensity; - private float _avatarVolume; - private OMV.Vector3 _force; - private OMV.Vector3 _velocity; - private OMV.Vector3 _torque; - private float _collisionScore; - private OMV.Vector3 _acceleration; - private OMV.Quaternion _orientation; - private int _physicsActorType; - private bool _isPhysical; - private bool _flying; - private bool _setAlwaysRun; - private bool _throttleUpdates; - private bool _isColliding; - private bool _collidingObj; - private bool _floatOnWater; - private OMV.Vector3 _rotationalVelocity; - private bool _kinematic; - private float _buoyancy; - - // The friction and velocity of the avatar is modified depending on whether walking or not. - private float _currentFriction; // the friction currently being used (changed by setVelocity). - - private BSVMotor _velocityMotor; - - private OMV.Vector3 _PIDTarget; - private bool _usePID; - private float _PIDTau; - private bool _useHoverPID; - private float _PIDHoverHeight; - private PIDHoverType _PIDHoverType; - private float _PIDHoverTao; - - public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) - : base(parent_scene, localID, avName, "BSCharacter") - { - _physicsActorType = (int)ActorTypes.Agent; - _position = pos; - - _flying = isFlying; - _orientation = OMV.Quaternion.Identity; - _velocity = OMV.Vector3.Zero; - _buoyancy = ComputeBuoyancyFromFlying(isFlying); - _currentFriction = BSParam.AvatarStandingFriction; - _avatarDensity = BSParam.AvatarDensity; - - // Old versions of ScenePresence passed only the height. If width and/or depth are zero, - // replace with the default values. - _size = size; - if (_size.X == 0f) _size.X = BSParam.AvatarCapsuleDepth; - if (_size.Y == 0f) _size.Y = BSParam.AvatarCapsuleWidth; - - // The dimensions of the physical capsule are kept in the scale. - // Physics creates a unit capsule which is scaled by the physics engine. - Scale = ComputeAvatarScale(_size); - // set _avatarVolume and _mass based on capsule size, _density and Scale - ComputeAvatarVolumeAndMass(); - - SetupMovementMotor(); - - DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", - LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass); - - // do actual creation in taint time - PhysicsScene.TaintedObject("BSCharacter.create", delegate() - { - DetailLog("{0},BSCharacter.create,taint", LocalID); - // New body and shape into PhysBody and PhysShape - PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this); - - SetPhysicalProperties(); - }); - return; - } - - // called when this character is being destroyed and the resources should be released - public override void Destroy() - { - base.Destroy(); - - DetailLog("{0},BSCharacter.Destroy", LocalID); - PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() - { - PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); - PhysBody.Clear(); - PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); - PhysShape.Clear(); - }); - } - - private void SetPhysicalProperties() - { - PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); - - ZeroMotion(true); - ForcePosition = _position; - - // Set the velocity and compute the proper friction - _velocityMotor.Reset(); - _velocityMotor.SetTarget(_velocity); - _velocityMotor.SetCurrent(_velocity); - ForceVelocity = _velocity; - - // This will enable or disable the flying buoyancy of the avatar. - // Needs to be reset especially when an avatar is recreated after crossing a region boundry. - Flying = _flying; - - PhysicsScene.PE.SetRestitution(PhysBody, BSParam.AvatarRestitution); - PhysicsScene.PE.SetMargin(PhysShape, PhysicsScene.Params.collisionMargin); - PhysicsScene.PE.SetLocalScaling(PhysShape, Scale); - PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); - if (BSParam.CcdMotionThreshold > 0f) - { - PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); - PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); - } - - UpdatePhysicalMassProperties(RawMass, false); - - // Make so capsule does not fall over - PhysicsScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero); - - PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT); - - PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody); - - // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG); - PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_DEACTIVATION); - PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody); - - // Do this after the object has been added to the world - PhysBody.collisionType = CollisionType.Avatar; - PhysBody.ApplyCollisionMask(PhysicsScene); - } - - // The avatar's movement is controlled by this motor that speeds up and slows down - // the avatar seeking to reach the motor's target speed. - // This motor runs as a prestep action for the avatar so it will keep the avatar - // standing as well as moving. Destruction of the avatar will destroy the pre-step action. - private void SetupMovementMotor() - { - - // Someday, use a PID motor for asymmetric speed up and slow down - // _velocityMotor = new BSPIDVMotor("BSCharacter.Velocity", 3f, 5f, BSMotor.InfiniteVector, 1f); - - // Infinite decay and timescale values so motor only changes current to target values. - _velocityMotor = new BSVMotor("BSCharacter.Velocity", - 0.2f, // time scale - BSMotor.Infinite, // decay time scale - BSMotor.InfiniteVector, // friction timescale - 1f // efficiency - ); - // _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages. - - RegisterPreStepAction("BSCharactor.Movement", LocalID, delegate(float timeStep) - { - // TODO: Decide if the step parameters should be changed depending on the avatar's - // state (flying, colliding, ...). There is code in ODE to do this. - - OMV.Vector3 stepVelocity = _velocityMotor.Step(timeStep); - - // If falling, we keep the world's downward vector no matter what the other axis specify. - if (!Flying && !IsColliding) - { - stepVelocity.Z = _velocity.Z; - // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity); - } - - // 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force. - OMV.Vector3 moveForce = (stepVelocity - _velocity) * Mass / PhysicsScene.LastTimeStep; - - /* - // If moveForce is very small, zero things so we don't keep sending microscopic updates to the user - float moveForceMagnitudeSquared = moveForce.LengthSquared(); - if (moveForceMagnitudeSquared < 0.0001) - { - DetailLog("{0},BSCharacter.MoveMotor,zeroMovement,stepVel={1},vel={2},mass={3},magSq={4},moveForce={5}", - LocalID, stepVelocity, _velocity, Mass, moveForceMagnitudeSquared, moveForce); - ForceVelocity = OMV.Vector3.Zero; - } - else - { - AddForce(moveForce, false, true); - } - */ - // DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", LocalID, stepVelocity, _velocity, Mass, moveForce); - AddForce(moveForce, false, true); - }); - } - - public override void RequestPhysicsterseUpdate() - { - base.RequestPhysicsterseUpdate(); - } - // No one calls this method so I don't know what it could possibly mean - public override bool Stopped { get { return false; } } - - public override OMV.Vector3 Size { - get - { - // Avatar capsule size is kept in the scale parameter. - return _size; - } - - set { - _size = value; - // Old versions of ScenePresence passed only the height. If width and/or depth are zero, - // replace with the default values. - if (_size.X == 0f) _size.X = BSParam.AvatarCapsuleDepth; - if (_size.Y == 0f) _size.Y = BSParam.AvatarCapsuleWidth; - - Scale = ComputeAvatarScale(_size); - ComputeAvatarVolumeAndMass(); - DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}", - LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass); - - PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() - { - if (PhysBody.HasPhysicalBody && PhysShape.HasPhysicalShape) - { - PhysicsScene.PE.SetLocalScaling(PhysShape, Scale); - UpdatePhysicalMassProperties(RawMass, true); - // Make sure this change appears as a property update event - PhysicsScene.PE.PushUpdate(PhysBody); - } - }); - - } - } - - public override PrimitiveBaseShape Shape - { - set { BaseShape = value; } - } - // I want the physics engine to make an avatar capsule - public override BSPhysicsShapeType PreferredPhysicalShape - { - get {return BSPhysicsShapeType.SHAPE_CAPSULE; } - } - - 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; } - - // Set motion values to zero. - // Do it to the properties so the values get set in the physics engine. - // Push the setting of the values to the viewer. - // Called at taint time! - public override void ZeroMotion(bool inTaintTime) - { - _velocity = OMV.Vector3.Zero; - _acceleration = OMV.Vector3.Zero; - _rotationalVelocity = OMV.Vector3.Zero; - - // Zero some other properties directly into the physics engine - PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() - { - if (PhysBody.HasPhysicalBody) - PhysicsScene.PE.ClearAllForces(PhysBody); - }); - } - public override void ZeroAngularMotion(bool inTaintTime) - { - _rotationalVelocity = OMV.Vector3.Zero; - - PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() - { - if (PhysBody.HasPhysicalBody) - { - PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, OMV.Vector3.Zero); - PhysicsScene.PE.SetAngularVelocity(PhysBody, OMV.Vector3.Zero); - // The next also get rid of applied linear force but the linear velocity is untouched. - PhysicsScene.PE.ClearForces(PhysBody); - } - }); - } - - - public override void LockAngularMotion(OMV.Vector3 axis) { return; } - - public override OMV.Vector3 RawPosition - { - get { return _position; } - set { _position = value; } - } - public override OMV.Vector3 Position { - get { - // Don't refetch the position because this function is called a zillion times - // _position = PhysicsScene.PE.GetObjectPosition(Scene.World, LocalID); - return _position; - } - set { - _position = value; - PositionSanityCheck(); - - PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() - { - DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); - if (PhysBody.HasPhysicalBody) - PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); - }); - } - } - public override OMV.Vector3 ForcePosition { - get { - _position = PhysicsScene.PE.GetPosition(PhysBody); - return _position; - } - set { - _position = value; - PositionSanityCheck(); - PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); - } - } - - - // Check that the current position is sane and, if not, modify the position to make it so. - // Check for being below terrain or on water. - // Returns 'true' of the position was made sane by some action. - private bool PositionSanityCheck() - { - bool ret = false; - - // TODO: check for out of bounds - if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(_position)) - { - // The character is out of the known/simulated area. - // Upper levels of code will handle the transition to other areas so, for - // the time, we just ignore the position. - return ret; - } - - // If below the ground, move the avatar up - float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); - if (Position.Z < terrainHeight) - { - DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); - _position.Z = terrainHeight + 2.0f; - ret = true; - } - if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) - { - float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position); - if (Position.Z < waterHeight) - { - _position.Z = waterHeight; - ret = true; - } - } - - return ret; - } - - // A version of the sanity check that also makes sure a new position value is - // pushed back to the physics engine. This routine would be used by anyone - // who is not already pushing the value. - private bool PositionSanityCheck(bool inTaintTime) - { - bool ret = false; - if (PositionSanityCheck()) - { - // The new position value must be pushed into the physics engine but we can't - // just assign to "Position" because of potential call loops. - PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() - { - DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); - if (PhysBody.HasPhysicalBody) - PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); - }); - ret = true; - } - return ret; - } - - public override float Mass { get { return _mass; } } - - // used when we only want this prim's mass and not the linkset thing - public override float RawMass { - get {return _mass; } - } - public override void UpdatePhysicalMassProperties(float physMass, bool inWorld) - { - OMV.Vector3 localInertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass); - PhysicsScene.PE.SetMassProps(PhysBody, physMass, localInertia); - } - - public override OMV.Vector3 Force { - get { return _force; } - set { - _force = value; - // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); - PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() - { - DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); - if (PhysBody.HasPhysicalBody) - PhysicsScene.PE.SetObjectForce(PhysBody, _force); - }); - } - } - - // Avatars don't do vehicles - public override int VehicleType { get { return (int)Vehicle.TYPE_NONE; } set { return; } } - public override void VehicleFloatParam(int param, float value) { } - public override void VehicleVectorParam(int param, OMV.Vector3 value) {} - public override void VehicleRotationParam(int param, OMV.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 OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } } - public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } } - - // Sets the target in the motor. This starts the changing of the avatar's velocity. - public override OMV.Vector3 TargetVelocity - { - get - { - return _velocityMotor.TargetValue; - } - set - { - DetailLog("{0},BSCharacter.setTargetVelocity,call,vel={1}", LocalID, value); - OMV.Vector3 targetVel = value; - if (_setAlwaysRun) - targetVel *= BSParam.AvatarAlwaysRunFactor; - - PhysicsScene.TaintedObject("BSCharacter.setTargetVelocity", delegate() - { - _velocityMotor.Reset(); - _velocityMotor.SetTarget(targetVel); - _velocityMotor.SetCurrent(_velocity); - _velocityMotor.Enabled = true; - }); - } - } - // Directly setting velocity means this is what the user really wants now. - public override OMV.Vector3 Velocity { - get { return _velocity; } - set { - _velocity = value; - // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); - PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() - { - _velocityMotor.Reset(); - _velocityMotor.SetCurrent(_velocity); - _velocityMotor.SetTarget(_velocity); - // Even though the motor is initialized, it's not used and the velocity goes straight into the avatar. - _velocityMotor.Enabled = false; - - DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); - ForceVelocity = _velocity; - }); - } - } - public override OMV.Vector3 ForceVelocity { - get { return _velocity; } - set { - PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity"); - - _velocity = value; - // Depending on whether the avatar is moving or not, change the friction - // to keep the avatar from slipping around - if (_velocity.Length() == 0) - { - if (_currentFriction != BSParam.AvatarStandingFriction) - { - _currentFriction = BSParam.AvatarStandingFriction; - if (PhysBody.HasPhysicalBody) - PhysicsScene.PE.SetFriction(PhysBody, _currentFriction); - } - } - else - { - if (_currentFriction != BSParam.AvatarFriction) - { - _currentFriction = BSParam.AvatarFriction; - if (PhysBody.HasPhysicalBody) - PhysicsScene.PE.SetFriction(PhysBody, _currentFriction); - } - } - - PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity); - PhysicsScene.PE.Activate(PhysBody, true); - } - } - public override OMV.Vector3 Torque { - get { return _torque; } - set { _torque = value; - } - } - public override float CollisionScore { - get { return _collisionScore; } - set { _collisionScore = value; - } - } - public override OMV.Vector3 Acceleration { - get { return _acceleration; } - set { _acceleration = value; } - } - public override OMV.Quaternion RawOrientation - { - get { return _orientation; } - set { _orientation = value; } - } - public override OMV.Quaternion Orientation { - get { return _orientation; } - set { - // Orientation is set zillions of times when an avatar is walking. It's like - // the viewer doesn't trust us. - if (_orientation != value) - { - _orientation = value; - PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() - { - ForceOrientation = _orientation; - }); - } - } - } - // Go directly to Bullet to get/set the value. - public override OMV.Quaternion ForceOrientation - { - get - { - _orientation = PhysicsScene.PE.GetOrientation(PhysBody); - return _orientation; - } - set - { - _orientation = value; - if (PhysBody.HasPhysicalBody) - { - // _position = PhysicsScene.PE.GetPosition(BSBody); - PhysicsScene.PE.SetTranslation(PhysBody, _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 IsSolid { - get { return true; } - } - public override bool IsStatic { - get { return false; } - } - public override bool Flying { - get { return _flying; } - set { - _flying = value; - - // simulate flying by changing the effect of gravity - Buoyancy = ComputeBuoyancyFromFlying(_flying); - } - } - // Flying is implimented by changing the avatar's buoyancy. - // Would this be done better with a vehicle type? - private float ComputeBuoyancyFromFlying(bool ifFlying) { - return ifFlying ? 1f : 0f; - } - public override bool - SetAlwaysRun { - get { return _setAlwaysRun; } - set { _setAlwaysRun = value; } - } - public override bool ThrottleUpdates { - get { return _throttleUpdates; } - set { _throttleUpdates = value; } - } - public override bool FloatOnWater { - set { - _floatOnWater = value; - PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() - { - if (PhysBody.HasPhysicalBody) - { - if (_floatOnWater) - CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); - else - CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); - } - }); - } - } - public override OMV.Vector3 RotationalVelocity { - get { return _rotationalVelocity; } - set { _rotationalVelocity = value; } - } - public override OMV.Vector3 ForceRotationalVelocity { - get { return _rotationalVelocity; } - set { _rotationalVelocity = value; } - } - public override bool Kinematic { - get { return _kinematic; } - set { _kinematic = value; } - } - // neg=fall quickly, 0=1g, 1=0g, pos=float up - public override float Buoyancy { - get { return _buoyancy; } - set { _buoyancy = value; - PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate() - { - DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - ForceBuoyancy = _buoyancy; - }); - } - } - public override float ForceBuoyancy { - get { return _buoyancy; } - set { - PhysicsScene.AssertInTaintTime("BSCharacter.ForceBuoyancy"); - - _buoyancy = value; - DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - // Buoyancy is faked by changing the gravity applied to the object - float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); - if (PhysBody.HasPhysicalBody) - PhysicsScene.PE.SetGravity(PhysBody, new OMV.Vector3(0f, 0f, grav)); - } - } - - // Used for MoveTo - public override OMV.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 OMV.Quaternion APIDTarget { set { return; } } - public override bool APIDActive { set { return; } } - public override float APIDStrength { set { return; } } - public override float APIDDamping { set { return; } } - - public override void AddForce(OMV.Vector3 force, bool pushforce) - { - // Since this force is being applied in only one step, make this a force per second. - OMV.Vector3 addForce = force / PhysicsScene.LastTimeStep; - AddForce(addForce, pushforce, false); - } - private void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { - if (force.IsFinite()) - { - float magnitude = force.Length(); - if (magnitude > BSParam.MaxAddForceMagnitude) - { - // Force has a limit - force = force / magnitude * BSParam.MaxAddForceMagnitude; - } - - OMV.Vector3 addForce = force; - // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce); - - PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.AddForce", delegate() - { - // Bullet adds this central force to the total force for this tick - // DetailLog("{0},BSCharacter.addForce,taint,force={1}", LocalID, addForce); - if (PhysBody.HasPhysicalBody) - { - PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce); - } - }); - } - else - { - m_log.WarnFormat("{0}: Got a NaN force applied to a character. LocalID={1}", LogHeader, LocalID); - return; - } - } - - public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { - } - public override void SetMomentum(OMV.Vector3 momentum) { - } - - private OMV.Vector3 ComputeAvatarScale(OMV.Vector3 size) - { - OMV.Vector3 newScale; - - // Bullet's capsule total height is the "passed height + radius * 2"; - // The base capsule is 1 diameter and 2 height (passed radius=0.5, passed height = 1) - // The number we pass in for 'scaling' is the multiplier to get that base - // shape to be the size desired. - // So, when creating the scale for the avatar height, we take the passed height - // (size.Z) and remove the caps. - // Another oddity of the Bullet capsule implementation is that it presumes the Y - // dimension is the radius of the capsule. Even though some of the code allows - // for a asymmetrical capsule, other parts of the code presume it is cylindrical. - - // Scale is multiplier of radius with one of "0.5" - newScale.X = size.X / 2f; - newScale.Y = size.Y / 2f; - - // The total scale height is the central cylindar plus the caps on the two ends. - newScale.Z = (size.Z + (Math.Min(size.X, size.Y) * 2)) / 2f; - // If smaller than the endcaps, just fake like we're almost that small - if (newScale.Z < 0) - newScale.Z = 0.1f; - - return newScale; - } - - // set _avatarVolume and _mass based on capsule size, _density and Scale - private void ComputeAvatarVolumeAndMass() - { - _avatarVolume = (float)( - Math.PI - * Size.X / 2f - * Size.Y / 2f // the area of capsule cylinder - * Size.Z // times height of capsule cylinder - + 1.33333333f - * Math.PI - * Size.X / 2f - * Math.Min(Size.X, Size.Y) / 2 - * Size.Y / 2f // plus the volume of the capsule end caps - ); - _mass = _avatarDensity * _avatarVolume; - } - - // The physics engine says that properties have updated. Update same and inform - // the world that things have changed. - public override void UpdateProperties(EntityProperties entprop) - { - _position = entprop.Position; - _orientation = entprop.Rotation; - _velocity = entprop.Velocity; - _acceleration = entprop.Acceleration; - _rotationalVelocity = entprop.RotationalVelocity; - - // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. - PositionSanityCheck(true); - - // remember the current and last set values - LastEntityProperties = CurrentEntityProperties; - CurrentEntityProperties = entprop; - - // Tell the linkset about value changes - Linkset.UpdateProperties(this, true); - - // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. - // base.RequestPhysicsterseUpdate(); - - DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", - LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs deleted file mode 100755 index b813974..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ - -public abstract class BSConstraint : IDisposable -{ - private static string LogHeader = "[BULLETSIM CONSTRAINT]"; - - protected BulletWorld m_world; - protected BSScene PhysicsScene; - protected BulletBody m_body1; - protected BulletBody m_body2; - protected BulletConstraint m_constraint; - protected bool m_enabled = false; - - public BulletBody Body1 { get { return m_body1; } } - public BulletBody Body2 { get { return m_body2; } } - public BulletConstraint Constraint { get { return m_constraint; } } - public abstract ConstraintType Type { get; } - public bool IsEnabled { get { return m_enabled; } } - - public BSConstraint(BulletWorld world) - { - m_world = world; - PhysicsScene = m_world.physicsScene; - } - - public virtual void Dispose() - { - if (m_enabled) - { - m_enabled = false; - if (m_constraint.HasPhysicalConstraint) - { - bool success = PhysicsScene.PE.DestroyConstraint(m_world, m_constraint); - m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}", - BSScene.DetailLogZero, - m_body1.ID, m_body1.AddrString, - m_body2.ID, m_body2.AddrString, - success); - m_constraint.Clear(); - } - } - } - - public virtual bool SetLinearLimits(Vector3 low, Vector3 high) - { - bool ret = false; - if (m_enabled) - ret = PhysicsScene.PE.SetLinearLimits(m_constraint, low, high); - return ret; - } - - public virtual bool SetAngularLimits(Vector3 low, Vector3 high) - { - bool ret = false; - if (m_enabled) - ret = PhysicsScene.PE.SetAngularLimits(m_constraint, low, high); - return ret; - } - - public virtual bool SetSolverIterations(float cnt) - { - bool ret = false; - if (m_enabled) - { - PhysicsScene.PE.SetConstraintNumSolverIterations(m_constraint, cnt); - ret = true; - } - return ret; - } - - public virtual bool CalculateTransforms() - { - bool ret = false; - if (m_enabled) - { - // Recompute the internal transforms - PhysicsScene.PE.CalculateTransforms(m_constraint); - ret = true; - } - return ret; - } - - // Reset this constraint making sure it has all its internal structures - // recomputed and is enabled and ready to go. - public virtual bool RecomputeConstraintVariables(float mass) - { - bool ret = false; - if (m_enabled) - { - ret = CalculateTransforms(); - if (ret) - { - // Setting an object's mass to zero (making it static like when it's selected) - // automatically disables the constraints. - // If the link is enabled, be sure to set the constraint itself to enabled. - PhysicsScene.PE.SetConstraintEnable(m_constraint, BSParam.NumericBool(true)); - } - else - { - m_world.physicsScene.Logger.ErrorFormat("{0} CalculateTransforms failed. A={1}, B={2}", LogHeader, Body1.ID, Body2.ID); - } - } - return ret; - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs deleted file mode 100755 index ecb1b32..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ - -public sealed class BSConstraint6Dof : BSConstraint -{ - private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]"; - - public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } } - - // Create a btGeneric6DofConstraint - public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2, - Vector3 frame1, Quaternion frame1rot, - Vector3 frame2, Quaternion frame2rot, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) - : base(world) - { - m_body1 = obj1; - m_body2 = obj2; - m_constraint = PhysicsScene.PE.Create6DofConstraint(m_world, m_body1, m_body2, - frame1, frame1rot, - frame2, frame2rot, - useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies); - m_enabled = true; - world.physicsScene.DetailLog("{0},BS6DofConstraint,createFrame,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", - BSScene.DetailLogZero, world.worldID, - obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString); - } - - public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2, - Vector3 joinPoint, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) - : base(world) - { - m_body1 = obj1; - m_body2 = obj2; - if (!obj1.HasPhysicalBody || !obj2.HasPhysicalBody) - { - world.physicsScene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", - BSScene.DetailLogZero, world.worldID, - obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString); - world.physicsScene.Logger.ErrorFormat("{0} Attempt to build 6DOF constraint with missing bodies: wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", - LogHeader, world.worldID, obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString); - m_enabled = false; - } - else - { - m_constraint = PhysicsScene.PE.Create6DofConstraintToPoint(m_world, m_body1, m_body2, - joinPoint, - useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies); - PhysicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}", - BSScene.DetailLogZero, world.worldID, m_constraint.AddrString, - obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString); - if (!m_constraint.HasPhysicalConstraint) - { - world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}", - LogHeader, obj1.ID, obj2.ID); - m_enabled = false; - } - else - { - m_enabled = true; - } - } - } - - public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) - { - bool ret = false; - if (m_enabled) - { - PhysicsScene.PE.SetFrames(m_constraint, frameA, frameArot, frameB, frameBrot); - ret = true; - } - return ret; - } - - public bool SetCFMAndERP(float cfm, float erp) - { - bool ret = false; - if (m_enabled) - { - PhysicsScene.PE.SetConstraintParam(m_constraint, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); - PhysicsScene.PE.SetConstraintParam(m_constraint, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); - PhysicsScene.PE.SetConstraintParam(m_constraint, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); - ret = true; - } - return ret; - } - - public bool UseFrameOffset(bool useOffset) - { - bool ret = false; - float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; - if (m_enabled) - ret = PhysicsScene.PE.UseFrameOffset(m_constraint, onOff); - return ret; - } - - public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce) - { - bool ret = false; - float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; - if (m_enabled) - { - ret = PhysicsScene.PE.TranslationalLimitMotor(m_constraint, onOff, targetVelocity, maxMotorForce); - m_world.physicsScene.DetailLog("{0},BS6DOFConstraint,TransLimitMotor,enable={1},vel={2},maxForce={3}", - BSScene.DetailLogZero, enable, targetVelocity, maxMotorForce); - } - return ret; - } - - public bool SetBreakingImpulseThreshold(float threshold) - { - bool ret = false; - if (m_enabled) - ret = PhysicsScene.PE.SetBreakingImpulseThreshold(m_constraint, threshold); - return ret; - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs deleted file mode 100755 index 2aeff25..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using log4net; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ - -public sealed class BSConstraintCollection : IDisposable -{ - // private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - // private static readonly string LogHeader = "[CONSTRAINT COLLECTION]"; - - delegate bool ConstraintAction(BSConstraint constrain); - - private List m_constraints; - private BulletWorld m_world; - - public BSConstraintCollection(BulletWorld world) - { - m_world = world; - m_constraints = new List(); - } - - public void Dispose() - { - this.Clear(); - } - - public void Clear() - { - lock (m_constraints) - { - foreach (BSConstraint cons in m_constraints) - { - cons.Dispose(); - } - m_constraints.Clear(); - } - } - - public bool AddConstraint(BSConstraint cons) - { - lock (m_constraints) - { - // There is only one constraint between any bodies. Remove any old just to make sure. - RemoveAndDestroyConstraint(cons.Body1, cons.Body2); - - m_constraints.Add(cons); - } - - return true; - } - - // Get the constraint between two bodies. There can be only one. - // Return 'true' if a constraint was found. - public bool TryGetConstraint(BulletBody body1, BulletBody body2, out BSConstraint returnConstraint) - { - bool found = false; - BSConstraint foundConstraint = null; - - uint lookingID1 = body1.ID; - uint lookingID2 = body2.ID; - lock (m_constraints) - { - foreach (BSConstraint constrain in m_constraints) - { - if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2) - || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1)) - { - foundConstraint = constrain; - found = true; - break; - } - } - } - returnConstraint = foundConstraint; - return found; - } - - // Remove any constraint between the passed bodies. - // Presumed there is only one such constraint possible. - // Return 'true' if a constraint was found and destroyed. - public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2) - { - bool ret = false; - lock (m_constraints) - { - BSConstraint constrain; - if (this.TryGetConstraint(body1, body2, out constrain)) - { - // remove the constraint from our collection - RemoveAndDestroyConstraint(constrain); - ret = true; - } - } - - return ret; - } - - // The constraint MUST exist in the collection - public bool RemoveAndDestroyConstraint(BSConstraint constrain) - { - lock (m_constraints) - { - // remove the constraint from our collection - m_constraints.Remove(constrain); - } - // tell the engine that all its structures need to be freed - constrain.Dispose(); - // we destroyed something - return true; - } - - // Remove all constraints that reference the passed body. - // Return 'true' if any constraints were destroyed. - public bool RemoveAndDestroyConstraint(BulletBody body1) - { - List toRemove = new List(); - uint lookingID = body1.ID; - lock (m_constraints) - { - foreach (BSConstraint constrain in m_constraints) - { - if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID) - { - toRemove.Add(constrain); - } - } - foreach (BSConstraint constrain in toRemove) - { - m_constraints.Remove(constrain); - constrain.Dispose(); - } - } - return (toRemove.Count > 0); - } - - public bool RecalculateAllConstraints() - { - bool ret = false; - lock (m_constraints) - { - foreach (BSConstraint constrain in m_constraints) - { - constrain.CalculateTransforms(); - ret = true; - } - } - return ret; - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs deleted file mode 100755 index 7714a03..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ - -public sealed class BSConstraintHinge : BSConstraint -{ - public override ConstraintType Type { get { return ConstraintType.HINGE_CONSTRAINT_TYPE; } } - - public BSConstraintHinge(BulletWorld world, BulletBody obj1, BulletBody obj2, - Vector3 pivotInA, Vector3 pivotInB, - Vector3 axisInA, Vector3 axisInB, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) - : base(world) - { - m_body1 = obj1; - m_body2 = obj2; - m_constraint = PhysicsScene.PE.CreateHingeConstraint(world, obj1, obj2, - pivotInA, pivotInB, axisInA, axisInB, - useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies); - m_enabled = true; - } - -} - -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs deleted file mode 100644 index 13c2539..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ /dev/null @@ -1,1383 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The quotations from http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial - * are Copyright (c) 2009 Linden Research, Inc and are used under their license - * of Creative Commons Attribution-Share Alike 3.0 - * (http://creativecommons.org/licenses/by-sa/3.0/). - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Runtime.InteropServices; -using OpenMetaverse; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ - public sealed class BSDynamics - { - private static string LogHeader = "[BULLETSIM VEHICLE]"; - - private BSScene PhysicsScene { get; set; } - // the prim this dynamic controller belongs to - private BSPrim Prim { get; set; } - - // mass of the vehicle fetched each time we're calles - private float m_vehicleMass; - - // Vehicle properties - public Vehicle Type { get; set; } - - // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier - private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings: - // HOVER_TERRAIN_ONLY - // HOVER_GLOBAL_HEIGHT - // NO_DEFLECTION_UP - // HOVER_WATER_ONLY - // HOVER_UP_ONLY - // LIMIT_MOTOR_UP - // LIMIT_ROLL_ONLY - private Vector3 m_BlockingEndPoint = Vector3.Zero; - private Quaternion m_RollreferenceFrame = Quaternion.Identity; - private Quaternion m_referenceFrame = Quaternion.Identity; - - // Linear properties - private BSVMotor m_linearMotor = new BSVMotor("LinearMotor"); - private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time - private Vector3 m_linearMotorOffset = Vector3.Zero; // the point of force can be offset from the center - private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL - private Vector3 m_linearFrictionTimescale = Vector3.Zero; - private float m_linearMotorDecayTimescale = 0; - private float m_linearMotorTimescale = 0; - private Vector3 m_lastLinearVelocityVector = Vector3.Zero; - private Vector3 m_lastPositionVector = Vector3.Zero; - // private bool m_LinearMotorSetLastFrame = false; - // private Vector3 m_linearMotorOffset = Vector3.Zero; - - //Angular properties - private BSVMotor m_angularMotor = new BSVMotor("AngularMotor"); - private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor - // private int m_angularMotorApply = 0; // application frame counter - private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity - private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate - private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate - private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate - private Vector3 m_lastAngularVelocity = Vector3.Zero; - private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body - - //Deflection properties - private BSVMotor m_angularDeflectionMotor = new BSVMotor("AngularDeflection"); - private float m_angularDeflectionEfficiency = 0; - private float m_angularDeflectionTimescale = 0; - private float m_linearDeflectionEfficiency = 0; - private float m_linearDeflectionTimescale = 0; - - //Banking properties - private float m_bankingEfficiency = 0; - private float m_bankingMix = 0; - private float m_bankingTimescale = 0; - - //Hover and Buoyancy properties - private BSVMotor m_hoverMotor = new BSVMotor("Hover"); - private float m_VhoverHeight = 0f; - private float m_VhoverEfficiency = 0f; - private float m_VhoverTimescale = 0f; - private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height - private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. - // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity) - // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity. - // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity. - - //Attractor properties - private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction"); - private float m_verticalAttractionEfficiency = 1.0f; // damped - private float m_verticalAttractionCutoff = 500f; // per the documentation - // Timescale > cutoff means no vert attractor. - private float m_verticalAttractionTimescale = 510f; - - // Just some recomputed constants: - static readonly float PIOverFour = ((float)Math.PI) / 4f; - static readonly float PIOverTwo = ((float)Math.PI) / 2f; - - public BSDynamics(BSScene myScene, BSPrim myPrim) - { - PhysicsScene = myScene; - Prim = myPrim; - Type = Vehicle.TYPE_NONE; - } - - // Return 'true' if this vehicle is doing vehicle things - public bool IsActive - { - get { return Type != Vehicle.TYPE_NONE && Prim.IsPhysical; } - } - - internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) - { - VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); - switch (pParam) - { - case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: - m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f); - break; - case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: - m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); - break; - case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: - m_angularMotorDecayTimescale = ClampInRange(0.01f, pValue, 120); - m_angularMotor.TargetValueDecayTimeScale = m_angularMotorDecayTimescale; - break; - case Vehicle.ANGULAR_MOTOR_TIMESCALE: - m_angularMotorTimescale = Math.Max(pValue, 0.01f); - m_angularMotor.TimeScale = m_angularMotorTimescale; - break; - case Vehicle.BANKING_EFFICIENCY: - m_bankingEfficiency = ClampInRange(-1f, pValue, 1f); - break; - case Vehicle.BANKING_MIX: - m_bankingMix = Math.Max(pValue, 0.01f); - break; - case Vehicle.BANKING_TIMESCALE: - m_bankingTimescale = Math.Max(pValue, 0.01f); - break; - case Vehicle.BUOYANCY: - m_VehicleBuoyancy = ClampInRange(-1f, pValue, 1f); - break; - case Vehicle.HOVER_EFFICIENCY: - m_VhoverEfficiency = ClampInRange(0f, pValue, 1f); - break; - case Vehicle.HOVER_HEIGHT: - m_VhoverHeight = pValue; - break; - case Vehicle.HOVER_TIMESCALE: - m_VhoverTimescale = Math.Max(pValue, 0.01f); - break; - case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: - m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f); - break; - case Vehicle.LINEAR_DEFLECTION_TIMESCALE: - m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); - break; - case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: - m_linearMotorDecayTimescale = ClampInRange(0.01f, pValue, 120); - m_linearMotor.TargetValueDecayTimeScale = m_linearMotorDecayTimescale; - break; - case Vehicle.LINEAR_MOTOR_TIMESCALE: - m_linearMotorTimescale = Math.Max(pValue, 0.01f); - m_linearMotor.TimeScale = m_linearMotorTimescale; - break; - case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: - m_verticalAttractionEfficiency = ClampInRange(0.1f, pValue, 1f); - m_verticalAttractionMotor.Efficiency = m_verticalAttractionEfficiency; - break; - case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: - m_verticalAttractionTimescale = Math.Max(pValue, 0.01f); - m_verticalAttractionMotor.TimeScale = m_verticalAttractionTimescale; - break; - - // These are vector properties but the engine lets you use a single float value to - // set all of the components to the same value - case Vehicle.ANGULAR_FRICTION_TIMESCALE: - m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); - m_angularMotor.FrictionTimescale = m_angularFrictionTimescale; - break; - case Vehicle.ANGULAR_MOTOR_DIRECTION: - m_angularMotorDirection = new Vector3(pValue, pValue, pValue); - m_angularMotor.SetTarget(m_angularMotorDirection); - break; - case Vehicle.LINEAR_FRICTION_TIMESCALE: - m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); - m_linearMotor.FrictionTimescale = m_linearFrictionTimescale; - break; - case Vehicle.LINEAR_MOTOR_DIRECTION: - m_linearMotorDirection = new Vector3(pValue, pValue, pValue); - m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); - m_linearMotor.SetTarget(m_linearMotorDirection); - break; - case Vehicle.LINEAR_MOTOR_OFFSET: - m_linearMotorOffset = new Vector3(pValue, pValue, pValue); - break; - - } - }//end ProcessFloatVehicleParam - - internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) - { - VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); - switch (pParam) - { - case Vehicle.ANGULAR_FRICTION_TIMESCALE: - m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); - m_angularMotor.FrictionTimescale = m_angularFrictionTimescale; - break; - case Vehicle.ANGULAR_MOTOR_DIRECTION: - // Limit requested angular speed to 2 rps= 4 pi rads/sec - pValue.X = ClampInRange(-12.56f, pValue.X, 12.56f); - pValue.Y = ClampInRange(-12.56f, pValue.Y, 12.56f); - pValue.Z = ClampInRange(-12.56f, pValue.Z, 12.56f); - m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); - m_angularMotor.SetTarget(m_angularMotorDirection); - break; - case Vehicle.LINEAR_FRICTION_TIMESCALE: - m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); - m_linearMotor.FrictionTimescale = m_linearFrictionTimescale; - break; - case Vehicle.LINEAR_MOTOR_DIRECTION: - m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); - m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); - m_linearMotor.SetTarget(m_linearMotorDirection); - break; - case Vehicle.LINEAR_MOTOR_OFFSET: - m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); - break; - case Vehicle.BLOCK_EXIT: - m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z); - break; - } - }//end ProcessVectorVehicleParam - - internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) - { - VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); - switch (pParam) - { - case Vehicle.REFERENCE_FRAME: - m_referenceFrame = pValue; - break; - case Vehicle.ROLL_FRAME: - m_RollreferenceFrame = pValue; - break; - } - }//end ProcessRotationVehicleParam - - internal void ProcessVehicleFlags(int pParam, bool remove) - { - VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", Prim.LocalID, pParam, remove); - VehicleFlag parm = (VehicleFlag)pParam; - if (pParam == -1) - m_flags = (VehicleFlag)0; - else - { - if (remove) - m_flags &= ~parm; - else - m_flags |= parm; - } - } - - internal void ProcessTypeChange(Vehicle pType) - { - VDetailLog("{0},ProcessTypeChange,type={1}", Prim.LocalID, pType); - // Set Defaults For Type - Type = pType; - switch (pType) - { - case Vehicle.TYPE_NONE: - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 0; - m_linearMotorDecayTimescale = 0; - m_linearFrictionTimescale = new Vector3(0, 0, 0); - - m_angularMotorDirection = Vector3.Zero; - m_angularMotorDecayTimescale = 0; - m_angularMotorTimescale = 0; - m_angularFrictionTimescale = new Vector3(0, 0, 0); - - m_VhoverHeight = 0; - m_VhoverEfficiency = 0; - m_VhoverTimescale = 0; - m_VehicleBuoyancy = 0; - - m_linearDeflectionEfficiency = 1; - m_linearDeflectionTimescale = 1; - - m_angularDeflectionEfficiency = 0; - m_angularDeflectionTimescale = 1000; - - m_verticalAttractionEfficiency = 0; - m_verticalAttractionTimescale = 0; - - m_bankingEfficiency = 0; - m_bankingTimescale = 1000; - m_bankingMix = 1; - - m_referenceFrame = Quaternion.Identity; - m_flags = (VehicleFlag)0; - - break; - - case Vehicle.TYPE_SLED: - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 1000; - m_linearMotorDecayTimescale = 120; - m_linearFrictionTimescale = new Vector3(30, 1, 1000); - - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 1000; - m_angularMotorDecayTimescale = 120; - m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); - - m_VhoverHeight = 0; - m_VhoverEfficiency = 10; // TODO: this looks wrong!! - m_VhoverTimescale = 10; - m_VehicleBuoyancy = 0; - - m_linearDeflectionEfficiency = 1; - m_linearDeflectionTimescale = 1; - - m_angularDeflectionEfficiency = 1; - m_angularDeflectionTimescale = 1000; - - m_verticalAttractionEfficiency = 0; - m_verticalAttractionTimescale = 0; - - m_bankingEfficiency = 0; - m_bankingTimescale = 10; - m_bankingMix = 1; - - m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY - | VehicleFlag.HOVER_TERRAIN_ONLY - | VehicleFlag.HOVER_GLOBAL_HEIGHT - | VehicleFlag.HOVER_UP_ONLY); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP - | VehicleFlag.LIMIT_ROLL_ONLY - | VehicleFlag.LIMIT_MOTOR_UP); - - break; - case Vehicle.TYPE_CAR: - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 1; - m_linearMotorDecayTimescale = 60; - m_linearFrictionTimescale = new Vector3(100, 2, 1000); - - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 1; - m_angularMotorDecayTimescale = 0.8f; - m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); - - m_VhoverHeight = 0; - m_VhoverEfficiency = 0; - m_VhoverTimescale = 1000; - m_VehicleBuoyancy = 0; - - m_linearDeflectionEfficiency = 1; - m_linearDeflectionTimescale = 2; - - m_angularDeflectionEfficiency = 0; - m_angularDeflectionTimescale = 10; - - m_verticalAttractionEfficiency = 1f; - m_verticalAttractionTimescale = 10f; - - m_bankingEfficiency = -0.2f; - m_bankingMix = 1; - m_bankingTimescale = 1; - - m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY - | VehicleFlag.HOVER_TERRAIN_ONLY - | VehicleFlag.HOVER_GLOBAL_HEIGHT); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP - | VehicleFlag.LIMIT_ROLL_ONLY - | VehicleFlag.LIMIT_MOTOR_UP - | VehicleFlag.HOVER_UP_ONLY); - break; - case Vehicle.TYPE_BOAT: - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 5; - m_linearMotorDecayTimescale = 60; - m_linearFrictionTimescale = new Vector3(10, 3, 2); - - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 4; - m_angularMotorDecayTimescale = 4; - m_angularFrictionTimescale = new Vector3(10,10,10); - - m_VhoverHeight = 0; - m_VhoverEfficiency = 0.5f; - m_VhoverTimescale = 2; - m_VehicleBuoyancy = 1; - - m_linearDeflectionEfficiency = 0.5f; - m_linearDeflectionTimescale = 3; - - m_angularDeflectionEfficiency = 0.5f; - m_angularDeflectionTimescale = 5; - - m_verticalAttractionEfficiency = 0.5f; - m_verticalAttractionTimescale = 5f; - - m_bankingEfficiency = -0.3f; - m_bankingMix = 0.8f; - m_bankingTimescale = 1; - - m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY - | VehicleFlag.HOVER_GLOBAL_HEIGHT - | VehicleFlag.LIMIT_ROLL_ONLY - | VehicleFlag.HOVER_UP_ONLY); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP - | VehicleFlag.LIMIT_MOTOR_UP - | VehicleFlag.HOVER_WATER_ONLY); - break; - case Vehicle.TYPE_AIRPLANE: - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 2; - m_linearMotorDecayTimescale = 60; - m_linearFrictionTimescale = new Vector3(200, 10, 5); - - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 4; - m_angularMotorDecayTimescale = 4; - m_angularFrictionTimescale = new Vector3(20, 20, 20); - - m_VhoverHeight = 0; - m_VhoverEfficiency = 0.5f; - m_VhoverTimescale = 1000; - m_VehicleBuoyancy = 0; - - m_linearDeflectionEfficiency = 0.5f; - m_linearDeflectionTimescale = 3; - - m_angularDeflectionEfficiency = 1; - m_angularDeflectionTimescale = 2; - - m_verticalAttractionEfficiency = 0.9f; - m_verticalAttractionTimescale = 2f; - - m_bankingEfficiency = 1; - m_bankingMix = 0.7f; - m_bankingTimescale = 2; - - m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY - | VehicleFlag.HOVER_TERRAIN_ONLY - | VehicleFlag.HOVER_GLOBAL_HEIGHT - | VehicleFlag.HOVER_UP_ONLY - | VehicleFlag.NO_DEFLECTION_UP - | VehicleFlag.LIMIT_MOTOR_UP); - m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); - break; - case Vehicle.TYPE_BALLOON: - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 5; - m_linearFrictionTimescale = new Vector3(5, 5, 5); - m_linearMotorDecayTimescale = 60; - - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 6; - m_angularFrictionTimescale = new Vector3(10, 10, 10); - m_angularMotorDecayTimescale = 10; - - m_VhoverHeight = 5; - m_VhoverEfficiency = 0.8f; - m_VhoverTimescale = 10; - m_VehicleBuoyancy = 1; - - m_linearDeflectionEfficiency = 0; - m_linearDeflectionTimescale = 5; - - m_angularDeflectionEfficiency = 0; - m_angularDeflectionTimescale = 5; - - m_verticalAttractionEfficiency = 1f; - m_verticalAttractionTimescale = 100f; - - m_bankingEfficiency = 0; - m_bankingMix = 0.7f; - m_bankingTimescale = 5; - - m_referenceFrame = Quaternion.Identity; - - m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY - | VehicleFlag.HOVER_TERRAIN_ONLY - | VehicleFlag.HOVER_UP_ONLY - | VehicleFlag.NO_DEFLECTION_UP - | VehicleFlag.LIMIT_MOTOR_UP); - m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY - | VehicleFlag.HOVER_GLOBAL_HEIGHT); - break; - } - - // Update any physical parameters based on this type. - Refresh(); - - m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, - m_linearMotorDecayTimescale, m_linearFrictionTimescale, - 1f); - m_linearMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) - - m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, - m_angularMotorDecayTimescale, m_angularFrictionTimescale, - 1f); - m_angularMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) - - m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale, - BSMotor.Infinite, BSMotor.InfiniteVector, - m_verticalAttractionEfficiency); - // Z goes away and we keep X and Y - m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f); - m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) - } - - // Some of the properties of this prim may have changed. - // Do any updating needed for a vehicle - public void Refresh() - { - if (IsActive) - { - // Remember the mass so we don't have to fetch it every step - m_vehicleMass = Prim.Linkset.LinksetMass; - - // Friction affects are handled by this vehicle code - float friction = 0f; - PhysicsScene.PE.SetFriction(Prim.PhysBody, friction); - - // Moderate angular movement introduced by Bullet. - // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle. - // Maybe compute linear and angular factor and damping from params. - float angularDamping = BSParam.VehicleAngularDamping; - PhysicsScene.PE.SetAngularDamping(Prim.PhysBody, angularDamping); - - // Vehicles report collision events so we know when it's on the ground - PhysicsScene.PE.AddToCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); - - Vector3 localInertia = PhysicsScene.PE.CalculateLocalInertia(Prim.PhysShape, m_vehicleMass); - PhysicsScene.PE.SetMassProps(Prim.PhysBody, m_vehicleMass, localInertia); - PhysicsScene.PE.UpdateInertiaTensor(Prim.PhysBody); - - Vector3 grav = PhysicsScene.DefaultGravity * (1f - Prim.Buoyancy); - PhysicsScene.PE.SetGravity(Prim.PhysBody, grav); - - VDetailLog("{0},BSDynamics.Refresh,mass={1},frict={2},inert={3},aDamp={4}", - Prim.LocalID, m_vehicleMass, friction, localInertia, angularDamping); - } - else - { - PhysicsScene.PE.RemoveFromCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); - } - } - - public bool RemoveBodyDependencies(BSPhysObject prim) - { - // If active, we need to add our properties back when the body is rebuilt. - return IsActive; - } - - public void RestoreBodyDependencies(BSPhysObject prim) - { - if (Prim.LocalID != prim.LocalID) - { - // The call should be on us by our prim. Error if not. - PhysicsScene.Logger.ErrorFormat("{0} RestoreBodyDependencies: called by not my prim. passedLocalID={1}, vehiclePrimLocalID={2}", - LogHeader, prim.LocalID, Prim.LocalID); - return; - } - Refresh(); - } - - #region Known vehicle value functions - // Vehicle physical parameters that we buffer from constant getting and setting. - // The "m_known*" values are unknown until they are fetched and the m_knownHas flag is set. - // Changing is remembered and the parameter is stored back into the physics engine only if updated. - // This does two things: 1) saves continuious calls into unmanaged code, and - // 2) signals when a physics property update must happen back to the simulator - // to update values modified for the vehicle. - private int m_knownChanged; - private int m_knownHas; - private float m_knownTerrainHeight; - private float m_knownWaterLevel; - private Vector3 m_knownPosition; - private Vector3 m_knownVelocity; - private Vector3 m_knownForce; - private Quaternion m_knownOrientation; - private Vector3 m_knownRotationalVelocity; - private Vector3 m_knownRotationalForce; - private Vector3 m_knownForwardVelocity; // vehicle relative forward speed - - private const int m_knownChangedPosition = 1 << 0; - private const int m_knownChangedVelocity = 1 << 1; - private const int m_knownChangedForce = 1 << 2; - private const int m_knownChangedOrientation = 1 << 3; - private const int m_knownChangedRotationalVelocity = 1 << 4; - private const int m_knownChangedRotationalForce = 1 << 5; - private const int m_knownChangedTerrainHeight = 1 << 6; - private const int m_knownChangedWaterLevel = 1 << 7; - private const int m_knownChangedForwardVelocity = 1 << 8; - - private void ForgetKnownVehicleProperties() - { - m_knownHas = 0; - m_knownChanged = 0; - } - // Push all the changed values back into the physics engine - private void PushKnownChanged() - { - if (m_knownChanged != 0) - { - if ((m_knownChanged & m_knownChangedPosition) != 0) - Prim.ForcePosition = m_knownPosition; - - if ((m_knownChanged & m_knownChangedOrientation) != 0) - Prim.ForceOrientation = m_knownOrientation; - - if ((m_knownChanged & m_knownChangedVelocity) != 0) - { - Prim.ForceVelocity = m_knownVelocity; - PhysicsScene.PE.SetInterpolationLinearVelocity(Prim.PhysBody, VehicleVelocity); - } - - if ((m_knownChanged & m_knownChangedForce) != 0) - Prim.AddForce((Vector3)m_knownForce, false, true); - - if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0) - { - Prim.ForceRotationalVelocity = m_knownRotationalVelocity; - // Fake out Bullet by making it think the velocity is the same as last time. - PhysicsScene.PE.SetInterpolationAngularVelocity(Prim.PhysBody, m_knownRotationalVelocity); - } - - if ((m_knownChanged & m_knownChangedRotationalForce) != 0) - Prim.AddAngularForce((Vector3)m_knownRotationalForce, false, true); - - // If we set one of the values (ie, the physics engine didn't do it) we must force - // an UpdateProperties event to send the changes up to the simulator. - PhysicsScene.PE.PushUpdate(Prim.PhysBody); - } - m_knownChanged = 0; - } - - // Since the computation of terrain height can be a little involved, this routine - // is used to fetch the height only once for each vehicle simulation step. - private float GetTerrainHeight(Vector3 pos) - { - if ((m_knownHas & m_knownChangedTerrainHeight) == 0) - { - m_knownTerrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); - m_knownHas |= m_knownChangedTerrainHeight; - } - return m_knownTerrainHeight; - } - - // Since the computation of water level can be a little involved, this routine - // is used ot fetch the level only once for each vehicle simulation step. - private float GetWaterLevel(Vector3 pos) - { - if ((m_knownHas & m_knownChangedWaterLevel) == 0) - { - m_knownWaterLevel = Prim.PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(pos); - m_knownHas |= m_knownChangedWaterLevel; - } - return (float)m_knownWaterLevel; - } - - private Vector3 VehiclePosition - { - get - { - if ((m_knownHas & m_knownChangedPosition) == 0) - { - m_knownPosition = Prim.ForcePosition; - m_knownHas |= m_knownChangedPosition; - } - return m_knownPosition; - } - set - { - m_knownPosition = value; - m_knownChanged |= m_knownChangedPosition; - m_knownHas |= m_knownChangedPosition; - } - } - - private Quaternion VehicleOrientation - { - get - { - if ((m_knownHas & m_knownChangedOrientation) == 0) - { - m_knownOrientation = Prim.ForceOrientation; - m_knownHas |= m_knownChangedOrientation; - } - return m_knownOrientation; - } - set - { - m_knownOrientation = value; - m_knownChanged |= m_knownChangedOrientation; - m_knownHas |= m_knownChangedOrientation; - } - } - - private Vector3 VehicleVelocity - { - get - { - if ((m_knownHas & m_knownChangedVelocity) == 0) - { - m_knownVelocity = Prim.ForceVelocity; - m_knownHas |= m_knownChangedVelocity; - } - return (Vector3)m_knownVelocity; - } - set - { - m_knownVelocity = value; - m_knownChanged |= m_knownChangedVelocity; - m_knownHas |= m_knownChangedVelocity; - } - } - - private void VehicleAddForce(Vector3 aForce) - { - if ((m_knownHas & m_knownChangedForce) == 0) - { - m_knownForce = Vector3.Zero; - } - m_knownForce += aForce; - m_knownChanged |= m_knownChangedForce; - m_knownHas |= m_knownChangedForce; - } - - private Vector3 VehicleRotationalVelocity - { - get - { - if ((m_knownHas & m_knownChangedRotationalVelocity) == 0) - { - m_knownRotationalVelocity = Prim.ForceRotationalVelocity; - m_knownHas |= m_knownChangedRotationalVelocity; - } - return (Vector3)m_knownRotationalVelocity; - } - set - { - m_knownRotationalVelocity = value; - m_knownChanged |= m_knownChangedRotationalVelocity; - m_knownHas |= m_knownChangedRotationalVelocity; - } - } - private void VehicleAddAngularForce(Vector3 aForce) - { - if ((m_knownHas & m_knownChangedRotationalForce) == 0) - { - m_knownRotationalForce = Vector3.Zero; - } - m_knownRotationalForce += aForce; - m_knownChanged |= m_knownChangedRotationalForce; - m_knownHas |= m_knownChangedRotationalForce; - } - // Vehicle relative forward velocity - private Vector3 VehicleForwardVelocity - { - get - { - if ((m_knownHas & m_knownChangedForwardVelocity) == 0) - { - m_knownForwardVelocity = VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation)); - m_knownHas |= m_knownChangedForwardVelocity; - } - return m_knownForwardVelocity; - } - } - private float VehicleForwardSpeed - { - get - { - return VehicleForwardVelocity.X; - } - } - - #endregion // Known vehicle value functions - - // One step of the vehicle properties for the next 'pTimestep' seconds. - internal void Step(float pTimestep) - { - if (!IsActive) return; - - if (PhysicsScene.VehiclePhysicalLoggingEnabled) - PhysicsScene.PE.DumpRigidBody(PhysicsScene.World, Prim.PhysBody); - - ForgetKnownVehicleProperties(); - - MoveLinear(pTimestep); - MoveAngular(pTimestep); - - LimitRotation(pTimestep); - - // remember the position so next step we can limit absolute movement effects - m_lastPositionVector = VehiclePosition; - - // If we forced the changing of some vehicle parameters, update the values and - // for the physics engine to note the changes so an UpdateProperties event will happen. - PushKnownChanged(); - - if (PhysicsScene.VehiclePhysicalLoggingEnabled) - PhysicsScene.PE.DumpRigidBody(PhysicsScene.World, Prim.PhysBody); - - VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", - Prim.LocalID, VehiclePosition, Prim.Force, VehicleVelocity, VehicleRotationalVelocity); - } - - // Apply the effect of the linear motor and other linear motions (like hover and float). - private void MoveLinear(float pTimestep) - { - Vector3 linearMotorContribution = m_linearMotor.Step(pTimestep); - - // The movement computed in the linear motor is relative to the vehicle - // coordinates. Rotate the movement to world coordinates. - linearMotorContribution *= VehicleOrientation; - - // ================================================================== - // Buoyancy: force to overcome gravity. - // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; - // So, if zero, don't change anything (let gravity happen). If one, negate the effect of gravity. - Vector3 buoyancyContribution = Prim.PhysicsScene.DefaultGravity * m_VehicleBuoyancy; - - Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep); - - Vector3 hoverContribution = ComputeLinearHover(pTimestep); - - ComputeLinearBlockingEndPoint(pTimestep); - - Vector3 limitMotorUpContribution = ComputeLinearMotorUp(pTimestep); - - // ================================================================== - Vector3 newVelocity = linearMotorContribution - + terrainHeightContribution - + hoverContribution - + limitMotorUpContribution; - - Vector3 newForce = buoyancyContribution; - - // If not changing some axis, reduce out velocity - if ((m_flags & (VehicleFlag.NO_X)) != 0) - newVelocity.X = 0; - if ((m_flags & (VehicleFlag.NO_Y)) != 0) - newVelocity.Y = 0; - if ((m_flags & (VehicleFlag.NO_Z)) != 0) - newVelocity.Z = 0; - - // ================================================================== - // Clamp high or low velocities - float newVelocityLengthSq = newVelocity.LengthSquared(); - if (newVelocityLengthSq > 1000f) - { - newVelocity /= newVelocity.Length(); - newVelocity *= 1000f; - } - else if (newVelocityLengthSq < 0.001f) - newVelocity = Vector3.Zero; - - // ================================================================== - // Stuff new linear velocity into the vehicle. - // Since the velocity is just being set, it is not scaled by pTimeStep. Bullet will do that for us. - VehicleVelocity = newVelocity; - - // Other linear forces are applied as forces. - Vector3 totalDownForce = newForce * m_vehicleMass; - if (!totalDownForce.ApproxEquals(Vector3.Zero, 0.01f)) - { - VehicleAddForce(totalDownForce); - } - - VDetailLog("{0}, MoveLinear,done,newVel={1},totDown={2},IsColliding={3}", - Prim.LocalID, newVelocity, totalDownForce, Prim.IsColliding); - VDetailLog("{0}, MoveLinear,done,linContrib={1},terrContrib={2},hoverContrib={3},limitContrib={4},buoyContrib={5}", - Prim.LocalID, - linearMotorContribution, terrainHeightContribution, hoverContribution, - limitMotorUpContribution, buoyancyContribution - ); - - } // end MoveLinear() - - public Vector3 ComputeLinearTerrainHeightCorrection(float pTimestep) - { - Vector3 ret = Vector3.Zero; - // If below the terrain, move us above the ground a little. - // TODO: Consider taking the rotated size of the object or possibly casting a ray. - if (VehiclePosition.Z < GetTerrainHeight(VehiclePosition)) - { - // TODO: correct position by applying force rather than forcing position. - Vector3 newPosition = VehiclePosition; - newPosition.Z = GetTerrainHeight(VehiclePosition) + 1f; - VehiclePosition = newPosition; - VDetailLog("{0}, MoveLinear,terrainHeight,terrainHeight={1},pos={2}", - Prim.LocalID, GetTerrainHeight(VehiclePosition), VehiclePosition); - } - return ret; - } - - public Vector3 ComputeLinearHover(float pTimestep) - { - Vector3 ret = Vector3.Zero; - - // m_VhoverEfficiency: 0=bouncy, 1=totally damped - // m_VhoverTimescale: time to achieve height - if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) - { - // We should hover, get the target height - if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0) - { - m_VhoverTargetHeight = GetWaterLevel(VehiclePosition) + m_VhoverHeight; - } - if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) - { - m_VhoverTargetHeight = GetTerrainHeight(VehiclePosition) + m_VhoverHeight; - } - if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) - { - m_VhoverTargetHeight = m_VhoverHeight; - } - - if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) - { - // If body is already heigher, use its height as target height - if (VehiclePosition.Z > m_VhoverTargetHeight) - m_VhoverTargetHeight = VehiclePosition.Z; - } - - if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) - { - if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f) - { - Vector3 pos = VehiclePosition; - pos.Z = m_VhoverTargetHeight; - VehiclePosition = pos; - } - } - else - { - // Error is positive if below the target and negative if above. - float verticalError = m_VhoverTargetHeight - VehiclePosition.Z; - float verticalCorrectionVelocity = verticalError / m_VhoverTimescale; - - // TODO: implement m_VhoverEfficiency correctly - if (Math.Abs(verticalError) > m_VhoverEfficiency) - { - ret = new Vector3(0f, 0f, verticalCorrectionVelocity); - } - } - - VDetailLog("{0}, MoveLinear,hover,pos={1},ret={2},hoverTS={3},height={4},target={5}", - Prim.LocalID, VehiclePosition, ret, m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight); - } - - return ret; - } - - public bool ComputeLinearBlockingEndPoint(float pTimestep) - { - bool changed = false; - - Vector3 pos = VehiclePosition; - Vector3 posChange = pos - m_lastPositionVector; - if (m_BlockingEndPoint != Vector3.Zero) - { - if (pos.X >= (m_BlockingEndPoint.X - (float)1)) - { - pos.X -= posChange.X + 1; - changed = true; - } - if (pos.Y >= (m_BlockingEndPoint.Y - (float)1)) - { - pos.Y -= posChange.Y + 1; - changed = true; - } - if (pos.Z >= (m_BlockingEndPoint.Z - (float)1)) - { - pos.Z -= posChange.Z + 1; - changed = true; - } - if (pos.X <= 0) - { - pos.X += posChange.X + 1; - changed = true; - } - if (pos.Y <= 0) - { - pos.Y += posChange.Y + 1; - changed = true; - } - if (changed) - { - VehiclePosition = pos; - VDetailLog("{0}, MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", - Prim.LocalID, m_BlockingEndPoint, posChange, pos); - } - } - return changed; - } - - // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : - // Prevent ground vehicles from motoring into the sky. This flag has a subtle effect when - // used with conjunction with banking: the strength of the banking will decay when the - // vehicle no longer experiences collisions. The decay timescale is the same as - // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering - // when they are in mid jump. - // TODO: this code is wrong. Also, what should it do for boats (height from water)? - // This is just using the ground and a general collision check. Should really be using - // a downward raycast to find what is below. - public Vector3 ComputeLinearMotorUp(float pTimestep) - { - Vector3 ret = Vector3.Zero; - float distanceAboveGround = 0f; - - if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) - { - float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition); - distanceAboveGround = VehiclePosition.Z - targetHeight; - // Not colliding if the vehicle is off the ground - if (!Prim.IsColliding) - { - // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); - ret = new Vector3(0, 0, -distanceAboveGround); - } - // TODO: this calculation is wrong. From the description at - // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce - // has a decay factor. This says this force should - // be computed with a motor. - // TODO: add interaction with banking. - } - VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}", - Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret); - return ret; - } - - // ======================================================================= - // ======================================================================= - // Apply the effect of the angular motor. - // The 'contribution' is how much angular correction velocity each function wants. - // All the contributions are added together and the resulting velocity is - // set directly on the vehicle. - private void MoveAngular(float pTimestep) - { - // The user wants this many radians per second angular change? - Vector3 angularMotorContribution = m_angularMotor.Step(pTimestep); - - // ================================================================== - // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : - // This flag prevents linear deflection parallel to world z-axis. This is useful - // for preventing ground vehicles with large linear deflection, like bumper cars, - // from climbing their linear deflection into the sky. - // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement - if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) - { - angularMotorContribution.X = 0f; - angularMotorContribution.Y = 0f; - VDetailLog("{0}, MoveAngular,noDeflectionUp,angularMotorContrib={1}", Prim.LocalID, angularMotorContribution); - } - - Vector3 verticalAttractionContribution = ComputeAngularVerticalAttraction(); - - Vector3 deflectionContribution = ComputeAngularDeflection(); - - Vector3 bankingContribution = ComputeAngularBanking(); - - // ================================================================== - m_lastVertAttractor = verticalAttractionContribution; - - m_lastAngularVelocity = angularMotorContribution - + verticalAttractionContribution - + deflectionContribution - + bankingContribution; - - // ================================================================== - // Apply the correction velocity. - // TODO: Should this be applied as an angular force (torque)? - if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) - { - VehicleRotationalVelocity = m_lastAngularVelocity; - - VDetailLog("{0}, MoveAngular,done,nonZero,angMotorContrib={1},vertAttrContrib={2},bankContrib={3},deflectContrib={4},totalContrib={5}", - Prim.LocalID, - angularMotorContribution, verticalAttractionContribution, - bankingContribution, deflectionContribution, - m_lastAngularVelocity - ); - } - else - { - // The vehicle is not adding anything angular wise. - VehicleRotationalVelocity = Vector3.Zero; - VDetailLog("{0}, MoveAngular,done,zero", Prim.LocalID); - } - - // ================================================================== - //Offset section - if (m_linearMotorOffset != Vector3.Zero) - { - //Offset of linear velocity doesn't change the linear velocity, - // but causes a torque to be applied, for example... - // - // IIIII >>> IIIII - // IIIII >>> IIIII - // IIIII >>> IIIII - // ^ - // | Applying a force at the arrow will cause the object to move forward, but also rotate - // - // - // The torque created is the linear velocity crossed with the offset - - // TODO: this computation should be in the linear section - // because that is where we know the impulse being applied. - Vector3 torqueFromOffset = Vector3.Zero; - // torqueFromOffset = Vector3.Cross(m_linearMotorOffset, appliedImpulse); - if (float.IsNaN(torqueFromOffset.X)) - torqueFromOffset.X = 0; - if (float.IsNaN(torqueFromOffset.Y)) - torqueFromOffset.Y = 0; - if (float.IsNaN(torqueFromOffset.Z)) - torqueFromOffset.Z = 0; - - VehicleAddAngularForce(torqueFromOffset * m_vehicleMass); - VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset); - } - - } - // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: - // Some vehicles, like boats, should always keep their up-side up. This can be done by - // enabling the "vertical attractor" behavior that springs the vehicle's local z-axis to - // the world z-axis (a.k.a. "up"). To take advantage of this feature you would set the - // VEHICLE_VERTICAL_ATTRACTION_TIMESCALE to control the period of the spring frequency, - // and then set the VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY to control the damping. An - // efficiency of 0.0 will cause the spring to wobble around its equilibrium, while an - // efficiency of 1.0 will cause the spring to reach its equilibrium with exponential decay. - public Vector3 ComputeAngularVerticalAttraction() - { - Vector3 ret = Vector3.Zero; - - // If vertical attaction timescale is reasonable - if (m_verticalAttractionTimescale < m_verticalAttractionCutoff) - { - // Take a vector pointing up and convert it from world to vehicle relative coords. - Vector3 verticalError = Vector3.UnitZ * VehicleOrientation; - - // If vertical attraction correction is needed, the vector that was pointing up (UnitZ) - // is now: - // leaning to one side: rotated around the X axis with the Y value going - // from zero (nearly straight up) to one (completely to the side)) or - // leaning front-to-back: rotated around the Y axis with the value of X being between - // zero and one. - // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees. - - // Y error means needed rotation around X axis and visa versa. - // Since the error goes from zero to one, the asin is the corresponding angle. - ret.X = (float)Math.Asin(verticalError.Y); - // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.) - ret.Y = -(float)Math.Asin(verticalError.X); - - // If verticalError.Z is negative, the vehicle is upside down. Add additional push. - if (verticalError.Z < 0f) - { - ret.X += PIOverFour; - ret.Y += PIOverFour; - } - - // 'ret' is now the necessary velocity to correct tilt in one second. - // Correction happens over a number of seconds. - Vector3 unscaledContrib = ret; - ret /= m_verticalAttractionTimescale; - - VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},eff={3},ts={4},vertAttr={5}", - Prim.LocalID, verticalError, unscaledContrib, m_verticalAttractionEfficiency, m_verticalAttractionTimescale, ret); - } - return ret; - } - - // Return the angular correction to correct the direction the vehicle is pointing to be - // the direction is should want to be pointing. - // The vehicle is moving in some direction and correct its orientation to it is pointing - // in that direction. - // TODO: implement reference frame. - public Vector3 ComputeAngularDeflection() - { - Vector3 ret = Vector3.Zero; - return ret; // DEBUG DEBUG DEBUG - // Disable angular deflection for the moment. - // Since angularMotorUp and angularDeflection are computed independently, they will calculate - // approximately the same X or Y correction. When added together (when contributions are combined) - // this creates an over-correction and then wabbling as the target is overshot. - // TODO: rethink how the different correction computations inter-relate. - - if (m_angularDeflectionEfficiency != 0) - { - // The direction the vehicle is moving - Vector3 movingDirection = VehicleVelocity; - movingDirection.Normalize(); - - // The direction the vehicle is pointing - Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation; - pointingDirection.Normalize(); - - // The difference between what is and what should be. - Vector3 deflectionError = movingDirection - pointingDirection; - - // Don't try to correct very large errors (not our job) - if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = 0f; - if (Math.Abs(deflectionError.Y) > PIOverFour) deflectionError.Y = 0f; - if (Math.Abs(deflectionError.Z) > PIOverFour) deflectionError.Z = 0f; - - // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError); - - // Scale the correction by recovery timescale and efficiency - ret = (-deflectionError) * m_angularDeflectionEfficiency; - ret /= m_angularDeflectionTimescale; - - VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}", - Prim.LocalID, movingDirection, pointingDirection, deflectionError, ret); - VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3}", - Prim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale); - } - return ret; - } - - // Return an angular change to rotate the vehicle around the Z axis when the vehicle - // is tipped around the X axis. - // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: - // The vertical attractor feature must be enabled in order for the banking behavior to - // function. The way banking works is this: a rotation around the vehicle's roll-axis will - // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude - // of the yaw effect will be proportional to the - // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's - // velocity along its preferred axis of motion. - // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any - // positive rotation (by the right-hand rule) about the roll-axis will effect a - // (negative) torque around the yaw-axis, making it turn to the right--that is the - // vehicle will lean into the turn, which is how real airplanes and motorcycle's work. - // Negating the banking coefficient will make it so that the vehicle leans to the - // outside of the turn (not very "physical" but might allow interesting vehicles so why not?). - // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making - // banking vehicles do what you want rather than what the laws of physics allow. - // For example, consider a real motorcycle...it must be moving forward in order for - // it to turn while banking, however video-game motorcycles are often configured - // to turn in place when at a dead stop--because they are often easier to control - // that way using the limited interface of the keyboard or game controller. The - // VEHICLE_BANKING_MIX enables combinations of both realistic and non-realistic - // banking by functioning as a slider between a banking that is correspondingly - // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the - // banking effect depends only on the vehicle's rotation about its roll-axis compared - // to "dynamic" where the banking is also proportional to its velocity along its - // roll-axis. Finding the best value of the "mixture" will probably require trial and error. - // The time it takes for the banking behavior to defeat a preexisting angular velocity about the - // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to - // bank quickly then give it a banking timescale of about a second or less, otherwise you can - // make a sluggish vehicle by giving it a timescale of several seconds. - public Vector3 ComputeAngularBanking() - { - Vector3 ret = Vector3.Zero; - - if (m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff) - { - // This works by rotating a unit vector to the orientation of the vehicle. The - // roll (tilt) will be Y component of a tilting Z vector (zero for no tilt - // up to one for full over). - Vector3 rollComponents = Vector3.UnitZ * VehicleOrientation; - - // Figure out the yaw value for this much roll. - float turnComponent = rollComponents.Y * rollComponents.Y * m_bankingEfficiency; - // Keep the sign - if (rollComponents.Y < 0f) - turnComponent = -turnComponent; - - // TODO: there must be a better computation of the banking force. - float bankingTurnForce = turnComponent; - - // actual error = static turn error + dynamic turn error - float mixedBankingError = bankingTurnForce * (1f - m_bankingMix) + bankingTurnForce * m_bankingMix * VehicleForwardSpeed; - // TODO: the banking effect should not go to infinity but what to limit it to? - mixedBankingError = ClampInRange(-20f, mixedBankingError, 20f); - - // Build the force vector to change rotation from what it is to what it should be - ret.Z = -mixedBankingError; - - // Don't do it all at once. - ret /= m_bankingTimescale; - - VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},turnComp={3},bankErr={4},mixedBankErr={5},ret={6}", - Prim.LocalID, rollComponents, VehicleForwardSpeed, turnComponent, bankingTurnForce, mixedBankingError, ret); - } - return ret; - } - - // This is from previous instantiations of XXXDynamics.cs. - // Applies roll reference frame. - // TODO: is this the right way to separate the code to do this operation? - // Should this be in MoveAngular()? - internal void LimitRotation(float timestep) - { - Quaternion rotq = VehicleOrientation; - Quaternion m_rot = rotq; - if (m_RollreferenceFrame != Quaternion.Identity) - { - if (rotq.X >= m_RollreferenceFrame.X) - { - m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2); - } - if (rotq.Y >= m_RollreferenceFrame.Y) - { - m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2); - } - if (rotq.X <= -m_RollreferenceFrame.X) - { - m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2); - } - if (rotq.Y <= -m_RollreferenceFrame.Y) - { - m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2); - } - } - if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0) - { - m_rot.X = 0; - m_rot.Y = 0; - } - if (rotq != m_rot) - { - VehicleOrientation = m_rot; - VDetailLog("{0}, LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot); - } - - } - - private float ClampInRange(float low, float val, float high) - { - return Math.Max(low, Math.Min(val, high)); - // return Utils.Clamp(val, low, high); - } - - // Invoke the detailed logger and output something if it's enabled. - private void VDetailLog(string msg, params Object[] args) - { - if (Prim.PhysicsScene.VehicleLoggingEnabled) - Prim.PhysicsScene.DetailLog(msg, args); - } - } -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs deleted file mode 100755 index 756faed..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OMV = OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ - -// A BSPrim can get individual information about its linkedness attached -// to it through an instance of a subclass of LinksetInfo. -// Each type of linkset will define the information needed for its type. -public abstract class BSLinksetInfo -{ - public virtual void Clear() { } -} - -public abstract class BSLinkset -{ - // private static string LogHeader = "[BULLETSIM LINKSET]"; - - public enum LinksetImplementation - { - Constraint = 0, // linkset tied together with constraints - Compound = 1, // linkset tied together as a compound object - Manual = 2 // linkset tied together manually (code moves all the pieces) - } - // Create the correct type of linkset for this child - public static BSLinkset Factory(BSScene physScene, BSPhysObject parent) - { - BSLinkset ret = null; - - switch ((int)BSParam.LinksetImplementation) - { - case (int)LinksetImplementation.Constraint: - ret = new BSLinksetConstraints(physScene, parent); - break; - case (int)LinksetImplementation.Compound: - ret = new BSLinksetCompound(physScene, parent); - break; - case (int)LinksetImplementation.Manual: - // ret = new BSLinksetManual(physScene, parent); - break; - default: - ret = new BSLinksetCompound(physScene, parent); - break; - } - return ret; - } - - public BSPhysObject LinksetRoot { get; protected set; } - - public BSScene PhysicsScene { get; private set; } - - static int m_nextLinksetID = 1; - public int LinksetID { get; private set; } - - // The children under the root in this linkset. - protected HashSet m_children; - - // We lock the diddling of linkset classes to prevent any badness. - // This locks the modification of the instances of this class. Changes - // to the physical representation is done via the tainting mechenism. - protected object m_linksetActivityLock = new Object(); - - // Some linksets have a preferred physical shape. - // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected. - public virtual BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) - { - return BSPhysicsShapeType.SHAPE_UNKNOWN; - } - - // We keep the prim's mass in the linkset structure since it could be dependent on other prims - public float LinksetMass { get; protected set; } - - public virtual bool LinksetIsColliding { get { return false; } } - - public OMV.Vector3 CenterOfMass - { - get { return ComputeLinksetCenterOfMass(); } - } - - public OMV.Vector3 GeometricCenter - { - get { return ComputeLinksetGeometricCenter(); } - } - - protected BSLinkset(BSScene scene, BSPhysObject parent) - { - // A simple linkset of one (no children) - LinksetID = m_nextLinksetID++; - // We create LOTS of linksets. - if (m_nextLinksetID <= 0) - m_nextLinksetID = 1; - PhysicsScene = scene; - LinksetRoot = parent; - m_children = new HashSet(); - LinksetMass = parent.RawMass; - Rebuilding = false; - } - - // Link to a linkset where the child knows the parent. - // Parent changing should not happen so do some sanity checking. - // We return the parent's linkset so the child can track its membership. - // Called at runtime. - public BSLinkset AddMeToLinkset(BSPhysObject child) - { - lock (m_linksetActivityLock) - { - // Don't add the root to its own linkset - if (!IsRoot(child)) - AddChildToLinkset(child); - LinksetMass = ComputeLinksetMass(); - } - return this; - } - - // Remove a child from a linkset. - // Returns a new linkset for the child which is a linkset of one (just the - // orphened child). - // Called at runtime. - public BSLinkset RemoveMeFromLinkset(BSPhysObject child) - { - lock (m_linksetActivityLock) - { - if (IsRoot(child)) - { - // Cannot remove the root from a linkset. - return this; - } - RemoveChildFromLinkset(child); - LinksetMass = ComputeLinksetMass(); - } - - // The child is down to a linkset of just itself - return BSLinkset.Factory(PhysicsScene, child); - } - - // Return 'true' if the passed object is the root object of this linkset - public bool IsRoot(BSPhysObject requestor) - { - return (requestor.LocalID == LinksetRoot.LocalID); - } - - public int NumberOfChildren { get { return m_children.Count; } } - - // Return 'true' if this linkset has any children (more than the root member) - public bool HasAnyChildren { get { return (m_children.Count > 0); } } - - // Return 'true' if this child is in this linkset - public bool HasChild(BSPhysObject child) - { - bool ret = false; - lock (m_linksetActivityLock) - { - ret = m_children.Contains(child); - /* Safer version but the above should work - foreach (BSPhysObject bp in m_children) - { - if (child.LocalID == bp.LocalID) - { - ret = true; - break; - } - } - */ - } - return ret; - } - - // Perform an action on each member of the linkset including root prim. - // Depends on the action on whether this should be done at taint time. - public delegate bool ForEachMemberAction(BSPhysObject obj); - public virtual bool ForEachMember(ForEachMemberAction action) - { - bool ret = false; - lock (m_linksetActivityLock) - { - action(LinksetRoot); - foreach (BSPhysObject po in m_children) - { - if (action(po)) - break; - } - } - return ret; - } - - // I am the root of a linkset and a new child is being added - // Called while LinkActivity is locked. - protected abstract void AddChildToLinkset(BSPhysObject child); - - // I am the root of a linkset and one of my children is being removed. - // Safe to call even if the child is not really in my linkset. - protected abstract void RemoveChildFromLinkset(BSPhysObject child); - - // When physical properties are changed the linkset needs to recalculate - // its internal properties. - // May be called at runtime or taint-time. - public virtual void Refresh(BSPhysObject requestor) - { - LinksetMass = ComputeLinksetMass(); - } - - // Flag denoting the linkset is in the process of being rebuilt. - // Used to know not the schedule a rebuild in the middle of a rebuild. - protected bool Rebuilding { get; set; } - - // The object is going dynamic (physical). Do any setup necessary - // for a dynamic linkset. - // Only the state of the passed object can be modified. The rest of the linkset - // has not yet been fully constructed. - // Return 'true' if any properties updated on the passed object. - // Called at taint-time! - public abstract bool MakeDynamic(BSPhysObject child); - - // The object is going static (non-physical). Do any setup necessary - // for a static linkset. - // Return 'true' if any properties updated on the passed object. - // Called at taint-time! - public abstract bool MakeStatic(BSPhysObject child); - - // Called when a parameter update comes from the physics engine for any object - // of the linkset is received. - // Passed flag is update came from physics engine (true) or the user (false). - // Called at taint-time!! - public abstract void UpdateProperties(BSPhysObject physObject, bool physicalUpdate); - - // Routine used when rebuilding the body of the root of the linkset - // Destroy all the constraints have have been made to root. - // This is called when the root body is changing. - // Returns 'true' of something was actually removed and would need restoring - // Called at taint-time!! - public abstract bool RemoveBodyDependencies(BSPrim child); - - // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', - // this routine will restore the removed constraints. - // Called at taint-time!! - public abstract void RestoreBodyDependencies(BSPrim child); - - // ================================================================ - protected virtual float ComputeLinksetMass() - { - float mass = LinksetRoot.RawMass; - if (HasAnyChildren) - { - lock (m_linksetActivityLock) - { - foreach (BSPhysObject bp in m_children) - { - mass += bp.RawMass; - } - } - } - return mass; - } - - protected virtual OMV.Vector3 ComputeLinksetCenterOfMass() - { - OMV.Vector3 com; - lock (m_linksetActivityLock) - { - com = LinksetRoot.Position * LinksetRoot.RawMass; - float totalMass = LinksetRoot.RawMass; - - foreach (BSPhysObject bp in m_children) - { - com += bp.Position * bp.RawMass; - totalMass += bp.RawMass; - } - if (totalMass != 0f) - com /= totalMass; - } - - return com; - } - - protected virtual OMV.Vector3 ComputeLinksetGeometricCenter() - { - OMV.Vector3 com; - lock (m_linksetActivityLock) - { - com = LinksetRoot.Position; - - foreach (BSPhysObject bp in m_children) - { - com += bp.Position * bp.RawMass; - } - com /= (m_children.Count + 1); - } - - return com; - } - - // Invoke the detailed logger and output something if it's enabled. - protected void DetailLog(string msg, params Object[] args) - { - if (PhysicsScene.PhysicsLogging.Enabled) - PhysicsScene.DetailLog(msg, args); - } - -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs deleted file mode 100755 index bd03d31..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OpenSim.Framework; - -using OMV = OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ - -// When a child is linked, the relationship position of the child to the parent -// is remembered so the child's world position can be recomputed when it is -// removed from the linkset. -sealed class BSLinksetCompoundInfo : BSLinksetInfo -{ - public OMV.Vector3 OffsetPos; - public OMV.Quaternion OffsetRot; - public BSLinksetCompoundInfo(OMV.Vector3 p, OMV.Quaternion r) - { - OffsetPos = p; - OffsetRot = r; - } - public override void Clear() - { - OffsetPos = OMV.Vector3.Zero; - OffsetRot = OMV.Quaternion.Identity; - } - public override string ToString() - { - StringBuilder buff = new StringBuilder(); - buff.Append(""); - return buff.ToString(); - } -}; - -public sealed class BSLinksetCompound : BSLinkset -{ - private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]"; - - public BSLinksetCompound(BSScene scene, BSPhysObject parent) : base(scene, parent) - { - } - - // For compound implimented linksets, if there are children, use compound shape for the root. - public override BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) - { - // Returning 'unknown' means we don't have a preference. - BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN; - if (IsRoot(requestor) && HasAnyChildren) - { - ret = BSPhysicsShapeType.SHAPE_COMPOUND; - } - // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret); - return ret; - } - - // When physical properties are changed the linkset needs to recalculate - // its internal properties. - public override void Refresh(BSPhysObject requestor) - { - base.Refresh(requestor); - - // Something changed so do the rebuilding thing - // ScheduleRebuild(); - } - - // Schedule a refresh to happen after all the other taint processing. - private void ScheduleRebuild(BSPhysObject requestor) - { - DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1},hasChildren={2}", - requestor.LocalID, Rebuilding, HasAnyChildren); - // When rebuilding, it is possible to set properties that would normally require a rebuild. - // If already rebuilding, don't request another rebuild. - // If a linkset with just a root prim (simple non-linked prim) don't bother rebuilding. - if (!Rebuilding && HasAnyChildren) - { - PhysicsScene.PostTaintObject("BSLinksetCompound.ScheduleRebuild", LinksetRoot.LocalID, delegate() - { - if (HasAnyChildren) - RecomputeLinksetCompound(); - }); - } - } - - // The object is going dynamic (physical). Do any setup necessary for a dynamic linkset. - // Only the state of the passed object can be modified. The rest of the linkset - // has not yet been fully constructed. - // Return 'true' if any properties updated on the passed object. - // Called at taint-time! - public override bool MakeDynamic(BSPhysObject child) - { - bool ret = false; - DetailLog("{0},BSLinksetCompound.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child)); - if (IsRoot(child)) - { - // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly. - ScheduleRebuild(LinksetRoot); - } - else - { - // The origional prims are removed from the world as the shape of the root compound - // shape takes over. - PhysicsScene.PE.AddToCollisionFlags(child.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); - PhysicsScene.PE.ForceActivationState(child.PhysBody, ActivationState.DISABLE_SIMULATION); - // We don't want collisions from the old linkset children. - PhysicsScene.PE.RemoveFromCollisionFlags(child.PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - - child.PhysBody.collisionType = CollisionType.LinksetChild; - - ret = true; - } - return ret; - } - - // The object is going static (non-physical). Do any setup necessary for a static linkset. - // Return 'true' if any properties updated on the passed object. - // This doesn't normally happen -- OpenSim removes the objects from the physical - // world if it is a static linkset. - // Called at taint-time! - public override bool MakeStatic(BSPhysObject child) - { - bool ret = false; - DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child)); - if (IsRoot(child)) - { - ScheduleRebuild(LinksetRoot); - } - else - { - // The non-physical children can come back to life. - PhysicsScene.PE.RemoveFromCollisionFlags(child.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); - - child.PhysBody.collisionType = CollisionType.LinksetChild; - - // Don't force activation so setting of DISABLE_SIMULATION can stay if used. - PhysicsScene.PE.Activate(child.PhysBody, false); - ret = true; - } - return ret; - } - - public override void UpdateProperties(BSPhysObject updated, bool physicalUpdate) - { - // The user moving a child around requires the rebuilding of the linkset compound shape - // One problem is this happens when a border is crossed -- the simulator implementation - // is to store the position into the group which causes the move of the object - // but it also means all the child positions get updated. - // What would cause an unnecessary rebuild so we make sure the linkset is in a - // region before bothering to do a rebuild. - if (!IsRoot(updated) - && !physicalUpdate - && PhysicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition)) - { - updated.LinksetInfo = null; - ScheduleRebuild(updated); - } - } - - // Routine called when rebuilding the body of some member of the linkset. - // Since we don't keep in world relationships, do nothing unless it's a child changing. - // Returns 'true' of something was actually removed and would need restoring - // Called at taint-time!! - public override bool RemoveBodyDependencies(BSPrim child) - { - bool ret = false; - - DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString, IsRoot(child)); - - if (!IsRoot(child)) - { - // Because it is a convenient time, recompute child world position and rotation based on - // its position in the linkset. - RecomputeChildWorldPosition(child, true); - } - - // Cannot schedule a refresh/rebuild here because this routine is called when - // the linkset is being rebuilt. - // InternalRefresh(LinksetRoot); - - return ret; - } - - // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', - // this routine will restore the removed constraints. - // Called at taint-time!! - public override void RestoreBodyDependencies(BSPrim child) - { - } - - // When the linkset is built, the child shape is added to the compound shape relative to the - // root shape. The linkset then moves around but this does not move the actual child - // prim. The child prim's location must be recomputed based on the location of the root shape. - private void RecomputeChildWorldPosition(BSPhysObject child, bool inTaintTime) - { - BSLinksetCompoundInfo lci = child.LinksetInfo as BSLinksetCompoundInfo; - if (lci != null) - { - if (inTaintTime) - { - OMV.Vector3 oldPos = child.RawPosition; - child.ForcePosition = LinksetRoot.RawPosition + lci.OffsetPos; - child.ForceOrientation = LinksetRoot.RawOrientation * lci.OffsetRot; - DetailLog("{0},BSLinksetCompound.RecomputeChildWorldPosition,oldPos={1},lci={2},newPos={3}", - child.LocalID, oldPos, lci, child.RawPosition); - } - else - { - // TaintedObject is not used here so the raw position is set now and not at taint-time. - child.Position = LinksetRoot.RawPosition + lci.OffsetPos; - child.Orientation = LinksetRoot.RawOrientation * lci.OffsetRot; - } - } - else - { - // This happens when children have been added to the linkset but the linkset - // has not been constructed yet. So like, at taint time, adding children to a linkset - // and then changing properties of the children (makePhysical, for instance) - // but the post-print action of actually rebuilding the linkset has not yet happened. - // PhysicsScene.Logger.WarnFormat("{0} Restoring linkset child position failed because of no relative position computed. ID={1}", - // LogHeader, child.LocalID); - DetailLog("{0},BSLinksetCompound.recomputeChildWorldPosition,noRelativePositonInfo", child.LocalID); - } - } - - // ================================================================ - - // Add a new child to the linkset. - // Called while LinkActivity is locked. - protected override void AddChildToLinkset(BSPhysObject child) - { - if (!HasChild(child)) - { - m_children.Add(child); - - DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); - - // Rebuild the compound shape with the new child shape included - ScheduleRebuild(child); - } - return; - } - - // Remove the specified child from the linkset. - // Safe to call even if the child is not really in the linkset. - protected override void RemoveChildFromLinkset(BSPhysObject child) - { - if (m_children.Remove(child)) - { - DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", - child.LocalID, - LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString, - child.LocalID, child.PhysBody.AddrString); - - // Cause the child's body to be rebuilt and thus restored to normal operation - RecomputeChildWorldPosition(child, false); - child.ForceBodyShapeRebuild(false); - - if (!HasAnyChildren) - { - // The linkset is now empty. The root needs rebuilding. - LinksetRoot.ForceBodyShapeRebuild(false); - } - else - { - // Rebuild the compound shape with the child removed - ScheduleRebuild(child); - } - } - return; - } - - // Called before the simulation step to make sure the compound based linkset - // is all initialized. - // Constraint linksets are rebuilt every time. - // Note that this works for rebuilding just the root after a linkset is taken apart. - // Called at taint time!! - private void RecomputeLinksetCompound() - { - try - { - // Suppress rebuilding while rebuilding - Rebuilding = true; - - // Cause the root shape to be rebuilt as a compound object with just the root in it - LinksetRoot.ForceBodyShapeRebuild(true); - - DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", - LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); - - // Add a shape for each of the other children in the linkset - ForEachMember(delegate(BSPhysObject cPrim) - { - if (!IsRoot(cPrim)) - { - // Compute the displacement of the child from the root of the linkset. - // This info is saved in the child prim so the relationship does not - // change over time and the new child position can be computed - // when the linkset is being disassembled (the linkset may have moved). - BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo; - if (lci == null) - { - // Each child position and rotation is given relative to the root. - OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); - OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation; - OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; - - // Save relative position for recomputing child's world position after moving linkset. - lci = new BSLinksetCompoundInfo(displacementPos, displacementRot); - cPrim.LinksetInfo = lci; - DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci); - } - - DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", - LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot); - - if (cPrim.PhysShape.isNativeShape) - { - // A native shape is turning into a hull collision shape because native - // shapes are not shared so we have to hullify it so it will be tracked - // and freed at the correct time. This also solves the scaling problem - // (native shapes scaled but hull/meshes are assumed to not be). - // TODO: decide of the native shape can just be used in the compound shape. - // Use call to CreateGeomNonSpecial(). - BulletShape saveShape = cPrim.PhysShape; - cPrim.PhysShape.Clear(); // Don't let the create free the child's shape - // PhysicsScene.Shapes.CreateGeomNonSpecial(true, cPrim, null); - PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); - BulletShape newShape = cPrim.PhysShape; - cPrim.PhysShape = saveShape; - PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, lci.OffsetPos, lci.OffsetRot); - } - else - { - // For the shared shapes (meshes and hulls), just use the shape in the child. - // The reference count added here will be decremented when the compound shape - // is destroyed in BSShapeCollection (the child shapes are looped over and dereferenced). - if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape)) - { - PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", - LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); - } - PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot); - } - } - return false; // 'false' says to move onto the next child in the list - }); - - // With all of the linkset packed into the root prim, it has the mass of everyone. - LinksetMass = ComputeLinksetMass(); - LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true); - } - finally - { - Rebuilding = false; - } - - PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape); - } -} -} \ No newline at end of file diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs deleted file mode 100755 index d0b2a56..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OMV = OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public sealed class BSLinksetConstraints : BSLinkset -{ - // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; - - public BSLinksetConstraints(BSScene scene, BSPhysObject parent) : base(scene, parent) - { - } - - // When physical properties are changed the linkset needs to recalculate - // its internal properties. - // This is queued in the 'post taint' queue so the - // refresh will happen once after all the other taints are applied. - public override void Refresh(BSPhysObject requestor) - { - base.Refresh(requestor); - - if (HasAnyChildren && IsRoot(requestor)) - { - // Queue to happen after all the other taint processing - PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() - { - if (HasAnyChildren && IsRoot(requestor)) - RecomputeLinksetConstraints(); - }); - } - } - - // The object is going dynamic (physical). Do any setup necessary - // for a dynamic linkset. - // Only the state of the passed object can be modified. The rest of the linkset - // has not yet been fully constructed. - // Return 'true' if any properties updated on the passed object. - // Called at taint-time! - public override bool MakeDynamic(BSPhysObject child) - { - // What is done for each object in BSPrim is what we want. - return false; - } - - // The object is going static (non-physical). Do any setup necessary for a static linkset. - // Return 'true' if any properties updated on the passed object. - // This doesn't normally happen -- OpenSim removes the objects from the physical - // world if it is a static linkset. - // Called at taint-time! - public override bool MakeStatic(BSPhysObject child) - { - // What is done for each object in BSPrim is what we want. - return false; - } - - // Called at taint-time!! - public override void UpdateProperties(BSPhysObject updated, bool inTaintTime) - { - // Nothing to do for constraints on property updates - } - - // Routine called when rebuilding the body of some member of the linkset. - // Destroy all the constraints have have been made to root and set - // up to rebuild the constraints before the next simulation step. - // Returns 'true' of something was actually removed and would need restoring - // Called at taint-time!! - public override bool RemoveBodyDependencies(BSPrim child) - { - bool ret = false; - - DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString); - - lock (m_linksetActivityLock) - { - // Just undo all the constraints for this linkset. Rebuild at the end of the step. - ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); - // Cause the constraints, et al to be rebuilt before the next simulation step. - Refresh(LinksetRoot); - } - return ret; - } - - // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', - // this routine will restore the removed constraints. - // Called at taint-time!! - public override void RestoreBodyDependencies(BSPrim child) - { - // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints. - } - - // ================================================================ - - // Add a new child to the linkset. - // Called while LinkActivity is locked. - protected override void AddChildToLinkset(BSPhysObject child) - { - if (!HasChild(child)) - { - m_children.Add(child); - - DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); - - // Cause constraints and assorted properties to be recomputed before the next simulation step. - Refresh(LinksetRoot); - } - return; - } - - // Remove the specified child from the linkset. - // Safe to call even if the child is not really in my linkset. - protected override void RemoveChildFromLinkset(BSPhysObject child) - { - if (m_children.Remove(child)) - { - BSPhysObject rootx = LinksetRoot; // capture the root and body as of now - BSPhysObject childx = child; - - DetailLog("{0},BSLinksetConstraints.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", - childx.LocalID, - rootx.LocalID, rootx.PhysBody.AddrString, - childx.LocalID, childx.PhysBody.AddrString); - - PhysicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate() - { - PhysicallyUnlinkAChildFromRoot(rootx, childx); - }); - // See that the linkset parameters are recomputed at the end of the taint time. - Refresh(LinksetRoot); - } - else - { - // Non-fatal occurance. - // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); - } - return; - } - - // Create a constraint between me (root of linkset) and the passed prim (the child). - // Called at taint time! - private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim) - { - // Don't build the constraint when asked. Put it off until just before the simulation step. - Refresh(rootPrim); - } - - private BSConstraint BuildConstraint(BSPhysObject rootPrim, BSPhysObject childPrim) - { - // Zero motion for children so they don't interpolate - childPrim.ZeroMotion(true); - - // Relative position normalized to the root prim - // Essentually a vector pointing from center of rootPrim to center of childPrim - OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position; - - // real world coordinate of midpoint between the two objects - OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); - - DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", - rootPrim.LocalID, - rootPrim.LocalID, rootPrim.PhysBody.AddrString, - childPrim.LocalID, childPrim.PhysBody.AddrString, - rootPrim.Position, childPrim.Position, midPoint); - - // create a constraint that allows no freedom of movement between the two objects - // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - - BSConstraint6Dof constrain = new BSConstraint6Dof( - PhysicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true ); - // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true ); - - /* NOTE: below is an attempt to build constraint with full frame computation, etc. - * Using the midpoint is easier since it lets the Bullet code manipulate the transforms - * of the objects. - * Code left for future programmers. - // ================================================================================== - // relative position normalized to the root prim - OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); - OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation; - - // relative rotation of the child to the parent - OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; - OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation); - - DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); - BS6DofConstraint constrain = new BS6DofConstraint( - PhysicsScene.World, rootPrim.Body, childPrim.Body, - OMV.Vector3.Zero, - OMV.Quaternion.Inverse(rootPrim.Orientation), - OMV.Vector3.Zero, - OMV.Quaternion.Inverse(childPrim.Orientation), - true, - true - ); - // ================================================================================== - */ - - PhysicsScene.Constraints.AddConstraint(constrain); - - // zero linear and angular limits makes the objects unable to move in relation to each other - constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); - constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); - - // tweek the constraint to increase stability - constrain.UseFrameOffset(BSParam.BoolNumeric(BSParam.LinkConstraintUseFrameOffset)); - constrain.TranslationalLimitMotor(BSParam.BoolNumeric(BSParam.LinkConstraintEnableTransMotor), - BSParam.LinkConstraintTransMotorMaxVel, - BSParam.LinkConstraintTransMotorMaxForce); - constrain.SetCFMAndERP(BSParam.LinkConstraintCFM, BSParam.LinkConstraintERP); - if (BSParam.LinkConstraintSolverIterations != 0f) - { - constrain.SetSolverIterations(BSParam.LinkConstraintSolverIterations); - } - return constrain; - } - - // Remove linkage between the linkset root and a particular child - // The root and child bodies are passed in because we need to remove the constraint between - // the bodies that were present at unlink time. - // Called at taint time! - private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim) - { - bool ret = false; - DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", - rootPrim.LocalID, - rootPrim.LocalID, rootPrim.PhysBody.AddrString, - childPrim.LocalID, childPrim.PhysBody.AddrString); - - // Find the constraint for this link and get rid of it from the overall collection and from my list - if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody)) - { - // Make the child refresh its location - PhysicsScene.PE.PushUpdate(childPrim.PhysBody); - ret = true; - } - - return ret; - } - - // Remove linkage between myself and any possible children I might have. - // Returns 'true' of any constraints were destroyed. - // Called at taint time! - private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) - { - DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); - - return PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody); - } - - // Call each of the constraints that make up this linkset and recompute the - // various transforms and variables. Create constraints of not created yet. - // Called before the simulation step to make sure the constraint based linkset - // is all initialized. - // Called at taint time!! - private void RecomputeLinksetConstraints() - { - float linksetMass = LinksetMass; - LinksetRoot.UpdatePhysicalMassProperties(linksetMass, true); - - DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}", - LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString, linksetMass); - - foreach (BSPhysObject child in m_children) - { - // A child in the linkset physically shows the mass of the whole linkset. - // This allows Bullet to apply enough force on the child to move the whole linkset. - // (Also do the mass stuff before recomputing the constraint so mass is not zero.) - child.UpdatePhysicalMassProperties(linksetMass, true); - - BSConstraint constrain; - if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain)) - { - // If constraint doesn't exist yet, create it. - constrain = BuildConstraint(LinksetRoot, child); - } - constrain.RecomputeConstraintVariables(linksetMass); - - // PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG - } - - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs deleted file mode 100755 index 92d62ff..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using System.Reflection; -using Nini.Config; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ - -public struct MaterialAttributes -{ - // Material type values that correspond with definitions for LSL - public enum Material : int - { - Stone = 0, - Metal, - Glass, - Wood, - Flesh, - Plastic, - Rubber, - Light, - // Hereafter are BulletSim additions - Avatar, - NumberOfTypes // the count of types in the enum. - } - - // Names must be in the order of the above enum. - // These names must coorespond to the lower case field names in the MaterialAttributes - // structure as reflection is used to select the field to put the value in. - public static readonly string[] MaterialAttribs = { "Density", "Friction", "Restitution"}; - - public MaterialAttributes(string t, float d, float f, float r) - { - type = t; - density = d; - friction = f; - restitution = r; - } - public string type; - public float density; - public float friction; - public float restitution; -} - -public static class BSMaterials -{ - // Attributes for each material type - private static readonly MaterialAttributes[] Attributes; - - // Map of material name to material type code - public static readonly Dictionary MaterialMap; - - static BSMaterials() - { - // Attribute sets for both the non-physical and physical instances of materials. - Attributes = new MaterialAttributes[(int)MaterialAttributes.Material.NumberOfTypes * 2]; - - // Map of name to type code. - MaterialMap = new Dictionary(); - MaterialMap.Add("Stone", MaterialAttributes.Material.Stone); - MaterialMap.Add("Metal", MaterialAttributes.Material.Metal); - MaterialMap.Add("Glass", MaterialAttributes.Material.Glass); - MaterialMap.Add("Wood", MaterialAttributes.Material.Wood); - MaterialMap.Add("Flesh", MaterialAttributes.Material.Flesh); - MaterialMap.Add("Plastic", MaterialAttributes.Material.Plastic); - MaterialMap.Add("Rubber", MaterialAttributes.Material.Rubber); - MaterialMap.Add("Light", MaterialAttributes.Material.Light); - MaterialMap.Add("Avatar", MaterialAttributes.Material.Avatar); - } - - // This is where all the default material attributes are defined. - public static void InitializeFromDefaults(ConfigurationParameters parms) - { - // Values from http://wiki.secondlife.com/wiki/PRIM_MATERIAL - float dDensity = parms.defaultDensity; - float dFriction = parms.defaultFriction; - float dRestitution = parms.defaultRestitution; - Attributes[(int)MaterialAttributes.Material.Stone] = - new MaterialAttributes("stone",dDensity, 0.8f, 0.4f); - Attributes[(int)MaterialAttributes.Material.Metal] = - new MaterialAttributes("metal",dDensity, 0.3f, 0.4f); - Attributes[(int)MaterialAttributes.Material.Glass] = - new MaterialAttributes("glass",dDensity, 0.2f, 0.7f); - Attributes[(int)MaterialAttributes.Material.Wood] = - new MaterialAttributes("wood",dDensity, 0.6f, 0.5f); - Attributes[(int)MaterialAttributes.Material.Flesh] = - new MaterialAttributes("flesh",dDensity, 0.9f, 0.3f); - Attributes[(int)MaterialAttributes.Material.Plastic] = - new MaterialAttributes("plastic",dDensity, 0.4f, 0.7f); - Attributes[(int)MaterialAttributes.Material.Rubber] = - new MaterialAttributes("rubber",dDensity, 0.9f, 0.9f); - Attributes[(int)MaterialAttributes.Material.Light] = - new MaterialAttributes("light",dDensity, dFriction, dRestitution); - Attributes[(int)MaterialAttributes.Material.Avatar] = - new MaterialAttributes("avatar",3.5f, 0.2f, 0f); - - Attributes[(int)MaterialAttributes.Material.Stone + (int)MaterialAttributes.Material.NumberOfTypes] = - new MaterialAttributes("stonePhysical",dDensity, 0.8f, 0.4f); - Attributes[(int)MaterialAttributes.Material.Metal + (int)MaterialAttributes.Material.NumberOfTypes] = - new MaterialAttributes("metalPhysical",dDensity, 0.3f, 0.4f); - Attributes[(int)MaterialAttributes.Material.Glass + (int)MaterialAttributes.Material.NumberOfTypes] = - new MaterialAttributes("glassPhysical",dDensity, 0.2f, 0.7f); - Attributes[(int)MaterialAttributes.Material.Wood + (int)MaterialAttributes.Material.NumberOfTypes] = - new MaterialAttributes("woodPhysical",dDensity, 0.6f, 0.5f); - Attributes[(int)MaterialAttributes.Material.Flesh + (int)MaterialAttributes.Material.NumberOfTypes] = - new MaterialAttributes("fleshPhysical",dDensity, 0.9f, 0.3f); - Attributes[(int)MaterialAttributes.Material.Plastic + (int)MaterialAttributes.Material.NumberOfTypes] = - new MaterialAttributes("plasticPhysical",dDensity, 0.4f, 0.7f); - Attributes[(int)MaterialAttributes.Material.Rubber + (int)MaterialAttributes.Material.NumberOfTypes] = - new MaterialAttributes("rubberPhysical",dDensity, 0.9f, 0.9f); - Attributes[(int)MaterialAttributes.Material.Light + (int)MaterialAttributes.Material.NumberOfTypes] = - new MaterialAttributes("lightPhysical",dDensity, dFriction, dRestitution); - Attributes[(int)MaterialAttributes.Material.Avatar + (int)MaterialAttributes.Material.NumberOfTypes] = - new MaterialAttributes("avatarPhysical",3.5f, 0.2f, 0f); - } - - // Under the [BulletSim] section, one can change the individual material - // attribute values. The format of the configuration parameter is: - // ["Physical"] = floatValue - // For instance: - // [BulletSim] - // StoneFriction = 0.2 - // FleshRestitutionPhysical = 0.8 - // Materials can have different parameters for their static and - // physical instantiations. When setting the non-physical value, - // both values are changed. Setting the physical value only changes - // the physical value. - public static void InitializefromParameters(IConfig pConfig) - { - foreach (KeyValuePair kvp in MaterialMap) - { - string matName = kvp.Key; - foreach (string attribName in MaterialAttributes.MaterialAttribs) - { - string paramName = matName + attribName; - if (pConfig.Contains(paramName)) - { - float paramValue = pConfig.GetFloat(paramName); - SetAttributeValue((int)kvp.Value, attribName, paramValue); - // set the physical value also - SetAttributeValue((int)kvp.Value + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue); - } - paramName += "Physical"; - if (pConfig.Contains(paramName)) - { - float paramValue = pConfig.GetFloat(paramName); - SetAttributeValue((int)kvp.Value + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue); - } - } - } - } - - // Use reflection to set the value in the attribute structure. - private static void SetAttributeValue(int matType, string attribName, float val) - { - MaterialAttributes thisAttrib = Attributes[matType]; - FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName.ToLower()); - if (fieldInfo != null) - { - fieldInfo.SetValue(thisAttrib, val); - Attributes[matType] = thisAttrib; - } - } - - // Given a material type, return a structure of attributes. - public static MaterialAttributes GetAttributes(MaterialAttributes.Material type, bool isPhysical) - { - int ind = (int)type; - if (isPhysical) ind += (int)MaterialAttributes.Material.NumberOfTypes; - return Attributes[ind]; - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs deleted file mode 100755 index 817a5f7..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -using System; -using System.Collections.Generic; -using System.Text; -using OpenMetaverse; -using OpenSim.Framework; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public abstract class BSMotor -{ - // Timescales and other things can be turned off by setting them to 'infinite'. - public const float Infinite = 12345.6f; - public readonly static Vector3 InfiniteVector = new Vector3(BSMotor.Infinite, BSMotor.Infinite, BSMotor.Infinite); - - public BSMotor(string useName) - { - UseName = useName; - PhysicsScene = null; - Enabled = true; - } - public virtual bool Enabled { get; set; } - public virtual void Reset() { } - public virtual void Zero() { } - public virtual void GenerateTestOutput(float timeStep) { } - - // A name passed at motor creation for easily identifyable debugging messages. - public string UseName { get; private set; } - - // Used only for outputting debug information. Might not be set so check for null. - public BSScene PhysicsScene { get; set; } - protected void MDetailLog(string msg, params Object[] parms) - { - if (PhysicsScene != null) - { - if (PhysicsScene.VehicleLoggingEnabled) - { - PhysicsScene.DetailLog(msg, parms); - } - } - } -} - -// Motor which moves CurrentValue to TargetValue over TimeScale seconds. -// The TargetValue decays in TargetValueDecayTimeScale and -// the CurrentValue will be held back by FrictionTimeScale. -// This motor will "zero itself" over time in that the targetValue will -// decay to zero and the currentValue will follow it to that zero. -// The overall effect is for the returned correction value to go from large -// values (the total difference between current and target minus friction) -// to small and eventually zero values. -// TimeScale and TargetDelayTimeScale may be 'infinite' which means no decay. - -// For instance, if something is moving at speed X and the desired speed is Y, -// CurrentValue is X and TargetValue is Y. As the motor is stepped, new -// values of CurrentValue are returned that approach the TargetValue. -// The feature of decaying TargetValue is so vehicles will eventually -// come to a stop rather than run forever. This can be disabled by -// setting TargetValueDecayTimescale to 'infinite'. -// The change from CurrentValue to TargetValue is linear over TimeScale seconds. -public class BSVMotor : BSMotor -{ - // public Vector3 FrameOfReference { get; set; } - // public Vector3 Offset { get; set; } - - public virtual float TimeScale { get; set; } - public virtual float TargetValueDecayTimeScale { get; set; } - public virtual Vector3 FrictionTimescale { get; set; } - public virtual float Efficiency { get; set; } - - public virtual float ErrorZeroThreshold { get; set; } - - public virtual Vector3 TargetValue { get; protected set; } - public virtual Vector3 CurrentValue { get; protected set; } - public virtual Vector3 LastError { get; protected set; } - - public virtual bool ErrorIsZero - { get { - return (LastError == Vector3.Zero || LastError.LengthSquared() <= ErrorZeroThreshold); - } - } - - public BSVMotor(string useName) - : base(useName) - { - TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite; - Efficiency = 1f; - FrictionTimescale = BSMotor.InfiniteVector; - CurrentValue = TargetValue = Vector3.Zero; - ErrorZeroThreshold = 0.001f; - } - public BSVMotor(string useName, float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency) - : this(useName) - { - TimeScale = timeScale; - TargetValueDecayTimeScale = decayTimeScale; - FrictionTimescale = frictionTimeScale; - Efficiency = efficiency; - CurrentValue = TargetValue = Vector3.Zero; - } - public void SetCurrent(Vector3 current) - { - CurrentValue = current; - } - public void SetTarget(Vector3 target) - { - TargetValue = target; - } - public override void Zero() - { - base.Zero(); - CurrentValue = TargetValue = Vector3.Zero; - } - - // Compute the next step and return the new current value - public virtual Vector3 Step(float timeStep) - { - if (!Enabled) return TargetValue; - - Vector3 origTarget = TargetValue; // DEBUG - Vector3 origCurrVal = CurrentValue; // DEBUG - - Vector3 correction = Vector3.Zero; - Vector3 error = TargetValue - CurrentValue; - if (!error.ApproxEquals(Vector3.Zero, ErrorZeroThreshold)) - { - correction = Step(timeStep, error); - - CurrentValue += correction; - - // The desired value reduces to zero which also reduces the difference with current. - // If the decay time is infinite, don't decay at all. - float decayFactor = 0f; - if (TargetValueDecayTimeScale != BSMotor.Infinite) - { - decayFactor = (1.0f / TargetValueDecayTimeScale) * timeStep; - TargetValue *= (1f - decayFactor); - } - - // The amount we can correct the error is reduced by the friction - Vector3 frictionFactor = Vector3.Zero; - if (FrictionTimescale != BSMotor.InfiniteVector) - { - // frictionFactor = (Vector3.One / FrictionTimescale) * timeStep; - // Individual friction components can be 'infinite' so compute each separately. - frictionFactor.X = (FrictionTimescale.X == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.X); - frictionFactor.Y = (FrictionTimescale.Y == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.Y); - frictionFactor.Z = (FrictionTimescale.Z == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.Z); - frictionFactor *= timeStep; - CurrentValue *= (Vector3.One - frictionFactor); - } - - MDetailLog("{0}, BSVMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},err={5},corr={6}", - BSScene.DetailLogZero, UseName, origCurrVal, origTarget, - timeStep, error, correction); - MDetailLog("{0}, BSVMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},frictTS={4},frictFact={5},tgt={6},curr={7}", - BSScene.DetailLogZero, UseName, - TargetValueDecayTimeScale, decayFactor, FrictionTimescale, frictionFactor, - TargetValue, CurrentValue); - } - else - { - // Difference between what we have and target is small. Motor is done. - CurrentValue = TargetValue; - MDetailLog("{0}, BSVMotor.Step,zero,{1},origTgt={2},origCurr={3},ret={4}", - BSScene.DetailLogZero, UseName, origCurrVal, origTarget, CurrentValue); - } - - return CurrentValue; - } - public virtual Vector3 Step(float timeStep, Vector3 error) - { - if (!Enabled) return Vector3.Zero; - - LastError = error; - Vector3 returnCorrection = Vector3.Zero; - if (!error.ApproxEquals(Vector3.Zero, ErrorZeroThreshold)) - { - // correction = error / secondsItShouldTakeToCorrect - Vector3 correctionAmount; - if (TimeScale == 0f || TimeScale == BSMotor.Infinite) - correctionAmount = error * timeStep; - else - correctionAmount = error / TimeScale * timeStep; - - returnCorrection = correctionAmount; - MDetailLog("{0}, BSVMotor.Step,nonZero,{1},timeStep={2},timeScale={3},err={4},corr={5}", - BSScene.DetailLogZero, UseName, timeStep, TimeScale, error, correctionAmount); - } - return returnCorrection; - } - - // The user sets all the parameters and calls this which outputs values until error is zero. - public override void GenerateTestOutput(float timeStep) - { - // maximum number of outputs to generate. - int maxOutput = 50; - MDetailLog("{0},BSVMotor.Test,{1},===================================== BEGIN Test Output", BSScene.DetailLogZero, UseName); - MDetailLog("{0},BSVMotor.Test,{1},timeScale={2},targDlyTS={3},frictTS={4},eff={5},curr={6},tgt={7}", - BSScene.DetailLogZero, UseName, - TimeScale, TargetValueDecayTimeScale, FrictionTimescale, Efficiency, - CurrentValue, TargetValue); - - LastError = BSMotor.InfiniteVector; - while (maxOutput-- > 0 && !LastError.ApproxEquals(Vector3.Zero, ErrorZeroThreshold)) - { - Vector3 lastStep = Step(timeStep); - MDetailLog("{0},BSVMotor.Test,{1},cur={2},tgt={3},lastError={4},lastStep={5}", - BSScene.DetailLogZero, UseName, CurrentValue, TargetValue, LastError, lastStep); - } - MDetailLog("{0},BSVMotor.Test,{1},===================================== END Test Output", BSScene.DetailLogZero, UseName); - - - } - - public override string ToString() - { - return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4},frictTS={5}>", - UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale, FrictionTimescale); - } -} - -public class BSFMotor : BSMotor -{ - public float TimeScale { get; set; } - public float DecayTimeScale { get; set; } - public float Friction { get; set; } - public float Efficiency { get; set; } - - public float Target { get; private set; } - public float CurrentValue { get; private set; } - - public BSFMotor(string useName, float timeScale, float decayTimescale, float friction, float efficiency) - : base(useName) - { - } - public void SetCurrent(float target) - { - } - public void SetTarget(float target) - { - } - public virtual float Step(float timeStep) - { - return 0f; - } -} - -// Proportional, Integral, Derivitive Motor -// Good description at http://www.answers.com/topic/pid-controller . Includes processes for choosing p, i and d factors. -public class BSPIDVMotor : BSVMotor -{ - // Larger makes more overshoot, smaller means converge quicker. Range of 0.1 to 10. - public Vector3 proportionFactor { get; set; } - public Vector3 integralFactor { get; set; } - public Vector3 derivFactor { get; set; } - - // Arbritrary factor range. - // EfficiencyHigh means move quickly to the correct number. EfficiencyLow means might over correct. - public float EfficiencyHigh = 0.4f; - public float EfficiencyLow = 4.0f; - - // Running integration of the error - Vector3 RunningIntegration { get; set; } - - public BSPIDVMotor(string useName) - : base(useName) - { - proportionFactor = new Vector3(1.00f, 1.00f, 1.00f); - integralFactor = new Vector3(1.00f, 1.00f, 1.00f); - derivFactor = new Vector3(1.00f, 1.00f, 1.00f); - RunningIntegration = Vector3.Zero; - LastError = Vector3.Zero; - } - - public override void Zero() - { - base.Zero(); - } - - public override float Efficiency - { - get { return base.Efficiency; } - set - { - base.Efficiency = Util.Clamp(value, 0f, 1f); - // Compute factors based on efficiency. - // If efficiency is high (1f), use a factor value that moves the error value to zero with little overshoot. - // If efficiency is low (0f), use a factor value that overcorrects. - // TODO: might want to vary contribution of different factor depending on efficiency. - float factor = ((1f - this.Efficiency) * EfficiencyHigh + EfficiencyLow) / 3f; - // float factor = (1f - this.Efficiency) * EfficiencyHigh + EfficiencyLow; - proportionFactor = new Vector3(factor, factor, factor); - integralFactor = new Vector3(factor, factor, factor); - derivFactor = new Vector3(factor, factor, factor); - } - } - - // Ignore Current and Target Values and just advance the PID computation on this error. - public override Vector3 Step(float timeStep, Vector3 error) - { - if (!Enabled) return Vector3.Zero; - - // Add up the error so we can integrate over the accumulated errors - RunningIntegration += error * timeStep; - - // A simple derivitive is the rate of change from the last error. - Vector3 derivFactor = (error - LastError) * timeStep; - LastError = error; - - // Correction = -(proportionOfPresentError + accumulationOfPastError + rateOfChangeOfError) - Vector3 ret = -( - error * proportionFactor - + RunningIntegration * integralFactor - + derivFactor * derivFactor - ); - - return ret; - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs deleted file mode 100755 index 69ac8cd..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs +++ /dev/null @@ -1,582 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OpenSim.Region.Physics.Manager; - -using OpenMetaverse; -using Nini.Config; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public static class BSParam -{ - // Level of Detail values kept as float because that's what the Meshmerizer wants - public static float MeshLOD { get; private set; } - public static float MeshMegaPrimLOD { get; private set; } - public static float MeshMegaPrimThreshold { get; private set; } - public static float SculptLOD { get; private set; } - - public static float MinimumObjectMass { get; private set; } - public static float MaximumObjectMass { get; private set; } - - public static float LinearDamping { get; private set; } - public static float AngularDamping { get; private set; } - public static float DeactivationTime { get; private set; } - public static float LinearSleepingThreshold { get; private set; } - public static float AngularSleepingThreshold { get; private set; } - public static float CcdMotionThreshold { get; private set; } - public static float CcdSweptSphereRadius { get; private set; } - public static float ContactProcessingThreshold { get; private set; } - - public static bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed - public static bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes - public static bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects - - public static float TerrainImplementation { get; private set; } - public static float TerrainFriction { get; private set; } - public static float TerrainHitFraction { get; private set; } - public static float TerrainRestitution { get; private set; } - public static float TerrainCollisionMargin { get; private set; } - - // Avatar parameters - public static float AvatarFriction { get; private set; } - public static float AvatarStandingFriction { get; private set; } - public static float AvatarAlwaysRunFactor { get; private set; } - public static float AvatarDensity { get; private set; } - public static float AvatarRestitution { get; private set; } - public static float AvatarCapsuleWidth { get; private set; } - public static float AvatarCapsuleDepth { get; private set; } - public static float AvatarCapsuleHeight { get; private set; } - public static float AvatarContactProcessingThreshold { get; private set; } - - public static float VehicleAngularDamping { get; private set; } - - public static float LinksetImplementation { get; private set; } - public static float LinkConstraintUseFrameOffset { get; private set; } - public static float LinkConstraintEnableTransMotor { get; private set; } - public static float LinkConstraintTransMotorMaxVel { get; private set; } - public static float LinkConstraintTransMotorMaxForce { get; private set; } - public static float LinkConstraintERP { get; private set; } - public static float LinkConstraintCFM { get; private set; } - public static float LinkConstraintSolverIterations { get; private set; } - - public static float PID_D { get; private set; } // derivative - public static float PID_P { get; private set; } // proportional - - // Various constants that come from that other virtual world that shall not be named - public const float MinGravityZ = -1f; - public const float MaxGravityZ = 28f; - public const float MinFriction = 0f; - public const float MaxFriction = 255f; - public const float MinDensity = 0f; - public const float MaxDensity = 22587f; - public const float MinRestitution = 0f; - public const float MaxRestitution = 1f; - public const float MaxAddForceMagnitude = 20000f; - - // =========================================================================== - public delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); - public delegate float ParamGet(BSScene scene); - public delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); - public delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val); - - public struct ParameterDefn - { - public string name; // string name of the parameter - public string desc; // a short description of what the parameter means - public float defaultValue; // default value if not specified anywhere else - public ParamUser userParam; // get the value from the configuration file - public ParamGet getter; // return the current value stored for this parameter - public ParamSet setter; // set the current value for this parameter - public SetOnObject onObject; // set the value on an object in the physical domain - public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) - { - name = n; - desc = d; - defaultValue = v; - userParam = u; - getter = g; - setter = s; - onObject = null; - } - public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o) - { - name = n; - desc = d; - defaultValue = v; - userParam = u; - getter = g; - setter = s; - onObject = o; - } - } - - // List of all of the externally visible parameters. - // For each parameter, this table maps a text name to getter and setters. - // To add a new externally referencable/settable parameter, add the paramter storage - // location somewhere in the program and make an entry in this table with the - // getters and setters. - // It is easiest to find an existing definition and copy it. - // Parameter values are floats. Booleans are converted to a floating value. - // - // A ParameterDefn() takes the following parameters: - // -- the text name of the parameter. This is used for console input and ini file. - // -- a short text description of the parameter. This shows up in the console listing. - // -- a default value (float) - // -- a delegate for fetching the parameter from the ini file. - // Should handle fetching the right type from the ini file and converting it. - // -- a delegate for getting the value as a float - // -- a delegate for setting the value from a float - // -- an optional delegate to update the value in the world. Most often used to - // push the new value to an in-world object. - // - // The single letter parameters for the delegates are: - // s = BSScene - // o = BSPhysObject - // p = string parameter name - // l = localID of referenced object - // v = value (float) - // cf = parameter configuration class (for fetching values from ini file) - private static ParameterDefn[] ParameterDefinitions = - { - new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", - ConfigurationParameters.numericTrue, - (s,cf,p,v) => { ShouldMeshSculptedPrim = cf.GetBoolean(p, BSParam.BoolNumeric(v)); }, - (s) => { return BSParam.NumericBool(ShouldMeshSculptedPrim); }, - (s,p,l,v) => { ShouldMeshSculptedPrim = BSParam.BoolNumeric(v); } ), - new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", - ConfigurationParameters.numericFalse, - (s,cf,p,v) => { ShouldForceSimplePrimMeshing = cf.GetBoolean(p, BSParam.BoolNumeric(v)); }, - (s) => { return BSParam.NumericBool(ShouldForceSimplePrimMeshing); }, - (s,p,l,v) => { ShouldForceSimplePrimMeshing = BSParam.BoolNumeric(v); } ), - new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects", - ConfigurationParameters.numericTrue, - (s,cf,p,v) => { ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, BSParam.BoolNumeric(v)); }, - (s) => { return BSParam.NumericBool(ShouldUseHullsForPhysicalObjects); }, - (s,p,l,v) => { ShouldUseHullsForPhysicalObjects = BSParam.BoolNumeric(v); } ), - - new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", - 8f, - (s,cf,p,v) => { MeshLOD = (float)cf.GetInt(p, (int)v); }, - (s) => { return MeshLOD; }, - (s,p,l,v) => { MeshLOD = v; } ), - new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters", - 16f, - (s,cf,p,v) => { MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); }, - (s) => { return MeshMegaPrimLOD; }, - (s,p,l,v) => { MeshMegaPrimLOD = v; } ), - new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD", - 10f, - (s,cf,p,v) => { MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); }, - (s) => { return MeshMegaPrimThreshold; }, - (s,p,l,v) => { MeshMegaPrimThreshold = v; } ), - new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", - 32f, - (s,cf,p,v) => { SculptLOD = (float)cf.GetInt(p, (int)v); }, - (s) => { return SculptLOD; }, - (s,p,l,v) => { SculptLOD = v; } ), - - new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps", - 10f, - (s,cf,p,v) => { s.m_maxSubSteps = cf.GetInt(p, (int)v); }, - (s) => { return (float)s.m_maxSubSteps; }, - (s,p,l,v) => { s.m_maxSubSteps = (int)v; } ), - new ParameterDefn("FixedTimeStep", "In simulation step, seconds of one substep (1/60)", - 1f / 60f, - (s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); }, - (s) => { return (float)s.m_fixedTimeStep; }, - (s,p,l,v) => { s.m_fixedTimeStep = v; } ), - new ParameterDefn("NominalFrameRate", "The base frame rate we claim", - 55f, - (s,cf,p,v) => { s.NominalFrameRate = cf.GetInt(p, (int)v); }, - (s) => { return (float)s.NominalFrameRate; }, - (s,p,l,v) => { s.NominalFrameRate = (int)v; } ), - new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame", - 2048f, - (s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); }, - (s) => { return (float)s.m_maxCollisionsPerFrame; }, - (s,p,l,v) => { s.m_maxCollisionsPerFrame = (int)v; } ), - new ParameterDefn("MaxUpdatesPerFrame", "Max updates returned at end of each frame", - 8000f, - (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); }, - (s) => { return (float)s.m_maxUpdatesPerFrame; }, - (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), - new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step", - 500f, - (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); }, - (s) => { return (float)s.m_taintsToProcessPerStep; }, - (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ), - new ParameterDefn("MinObjectMass", "Minimum object mass (0.0001)", - 0.0001f, - (s,cf,p,v) => { MinimumObjectMass = cf.GetFloat(p, v); }, - (s) => { return (float)MinimumObjectMass; }, - (s,p,l,v) => { MinimumObjectMass = v; } ), - new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", - 10000.01f, - (s,cf,p,v) => { MaximumObjectMass = cf.GetFloat(p, v); }, - (s) => { return (float)MaximumObjectMass; }, - (s,p,l,v) => { MaximumObjectMass = v; } ), - - new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", - 2200f, - (s,cf,p,v) => { PID_D = cf.GetFloat(p, v); }, - (s) => { return (float)PID_D; }, - (s,p,l,v) => { PID_D = v; } ), - new ParameterDefn("PID_P", "Parameteric factor for motion smoothing", - 900f, - (s,cf,p,v) => { PID_P = cf.GetFloat(p, v); }, - (s) => { return (float)PID_P; }, - (s,p,l,v) => { PID_P = v; } ), - - new ParameterDefn("DefaultFriction", "Friction factor used on new objects", - 0.2f, - (s,cf,p,v) => { s.UnmanagedParams[0].defaultFriction = cf.GetFloat(p, v); }, - (s) => { return s.UnmanagedParams[0].defaultFriction; }, - (s,p,l,v) => { s.UnmanagedParams[0].defaultFriction = v; } ), - new ParameterDefn("DefaultDensity", "Density for new objects" , - 10.000006836f, // Aluminum g/cm3 - (s,cf,p,v) => { s.UnmanagedParams[0].defaultDensity = cf.GetFloat(p, v); }, - (s) => { return s.UnmanagedParams[0].defaultDensity; }, - (s,p,l,v) => { s.UnmanagedParams[0].defaultDensity = v; } ), - new ParameterDefn("DefaultRestitution", "Bouncyness of an object" , - 0f, - (s,cf,p,v) => { s.UnmanagedParams[0].defaultRestitution = cf.GetFloat(p, v); }, - (s) => { return s.UnmanagedParams[0].defaultRestitution; }, - (s,p,l,v) => { s.UnmanagedParams[0].defaultRestitution = v; } ), - new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)", - 0.04f, - (s,cf,p,v) => { s.UnmanagedParams[0].collisionMargin = cf.GetFloat(p, v); }, - (s) => { return s.UnmanagedParams[0].collisionMargin; }, - (s,p,l,v) => { s.UnmanagedParams[0].collisionMargin = v; } ), - new ParameterDefn("Gravity", "Vertical force of gravity (negative means down)", - -9.80665f, - (s,cf,p,v) => { s.UnmanagedParams[0].gravity = cf.GetFloat(p, v); }, - (s) => { return s.UnmanagedParams[0].gravity; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{s.UnmanagedParams[0].gravity=x;}, p, PhysParameterEntry.APPLY_TO_NONE, v); }, - (s,o,v) => { s.PE.SetGravity(o.PhysBody, new Vector3(0f,0f,v)); } ), - - - new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)", - 0f, - (s,cf,p,v) => { LinearDamping = cf.GetFloat(p, v); }, - (s) => { return LinearDamping; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{LinearDamping=x;}, p, l, v); }, - (s,o,v) => { s.PE.SetDamping(o.PhysBody, v, AngularDamping); } ), - new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", - 0f, - (s,cf,p,v) => { AngularDamping = cf.GetFloat(p, v); }, - (s) => { return AngularDamping; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{AngularDamping=x;}, p, l, v); }, - (s,o,v) => { s.PE.SetDamping(o.PhysBody, LinearDamping, v); } ), - new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", - 0.2f, - (s,cf,p,v) => { DeactivationTime = cf.GetFloat(p, v); }, - (s) => { return DeactivationTime; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{DeactivationTime=x;}, p, l, v); }, - (s,o,v) => { s.PE.SetDeactivationTime(o.PhysBody, v); } ), - new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", - 0.8f, - (s,cf,p,v) => { LinearSleepingThreshold = cf.GetFloat(p, v); }, - (s) => { return LinearSleepingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{LinearSleepingThreshold=x;}, p, l, v); }, - (s,o,v) => { s.PE.SetSleepingThresholds(o.PhysBody, v, v); } ), - new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", - 1.0f, - (s,cf,p,v) => { AngularSleepingThreshold = cf.GetFloat(p, v); }, - (s) => { return AngularSleepingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{AngularSleepingThreshold=x;}, p, l, v); }, - (s,o,v) => { s.PE.SetSleepingThresholds(o.PhysBody, v, v); } ), - new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , - 0f, // set to zero to disable - (s,cf,p,v) => { CcdMotionThreshold = cf.GetFloat(p, v); }, - (s) => { return CcdMotionThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{CcdMotionThreshold=x;}, p, l, v); }, - (s,o,v) => { s.PE.SetCcdMotionThreshold(o.PhysBody, v); } ), - new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , - 0f, - (s,cf,p,v) => { CcdSweptSphereRadius = cf.GetFloat(p, v); }, - (s) => { return CcdSweptSphereRadius; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{CcdSweptSphereRadius=x;}, p, l, v); }, - (s,o,v) => { s.PE.SetCcdSweptSphereRadius(o.PhysBody, v); } ), - new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , - 0.1f, - (s,cf,p,v) => { ContactProcessingThreshold = cf.GetFloat(p, v); }, - (s) => { return ContactProcessingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{ContactProcessingThreshold=x;}, p, l, v); }, - (s,o,v) => { s.PE.SetContactProcessingThreshold(o.PhysBody, v); } ), - - new ParameterDefn("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)", - (float)BSTerrainPhys.TerrainImplementation.Mesh, - (s,cf,p,v) => { TerrainImplementation = cf.GetFloat(p,v); }, - (s) => { return TerrainImplementation; }, - (s,p,l,v) => { TerrainImplementation = v; } ), - new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , - 0.3f, - (s,cf,p,v) => { TerrainFriction = cf.GetFloat(p, v); }, - (s) => { return TerrainFriction; }, - (s,p,l,v) => { TerrainFriction = v; /* TODO: set on real terrain */} ), - new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" , - 0.8f, - (s,cf,p,v) => { TerrainHitFraction = cf.GetFloat(p, v); }, - (s) => { return TerrainHitFraction; }, - (s,p,l,v) => { TerrainHitFraction = v; /* TODO: set on real terrain */ } ), - new ParameterDefn("TerrainRestitution", "Bouncyness" , - 0f, - (s,cf,p,v) => { TerrainRestitution = cf.GetFloat(p, v); }, - (s) => { return TerrainRestitution; }, - (s,p,l,v) => { TerrainRestitution = v; /* TODO: set on real terrain */ } ), - new ParameterDefn("TerrainCollisionMargin", "Margin where collision checking starts" , - 0.04f, - (s,cf,p,v) => { TerrainCollisionMargin = cf.GetFloat(p, v); }, - (s) => { return TerrainCollisionMargin; }, - (s,p,l,v) => { TerrainCollisionMargin = v; /* TODO: set on real terrain */ } ), - - new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", - 0.2f, - (s,cf,p,v) => { AvatarFriction = cf.GetFloat(p, v); }, - (s) => { return AvatarFriction; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarFriction=x;}, p, l, v); } ), - new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.", - 10.0f, - (s,cf,p,v) => { AvatarStandingFriction = cf.GetFloat(p, v); }, - (s) => { return AvatarStandingFriction; }, - (s,p,l,v) => { AvatarStandingFriction = v; } ), - new ParameterDefn("AvatarAlwaysRunFactor", "Speed multiplier if avatar is set to always run", - 1.3f, - (s,cf,p,v) => { AvatarAlwaysRunFactor = cf.GetFloat(p, v); }, - (s) => { return AvatarAlwaysRunFactor; }, - (s,p,l,v) => { AvatarAlwaysRunFactor = v; } ), - new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", - 3.5f, - (s,cf,p,v) => { AvatarDensity = cf.GetFloat(p, v); }, - (s) => { return AvatarDensity; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarDensity=x;}, p, l, v); } ), - new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", - 0f, - (s,cf,p,v) => { AvatarRestitution = cf.GetFloat(p, v); }, - (s) => { return AvatarRestitution; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarRestitution=x;}, p, l, v); } ), - new ParameterDefn("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule", - 0.6f, - (s,cf,p,v) => { AvatarCapsuleWidth = cf.GetFloat(p, v); }, - (s) => { return AvatarCapsuleWidth; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarCapsuleWidth=x;}, p, l, v); } ), - new ParameterDefn("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule", - 0.45f, - (s,cf,p,v) => { AvatarCapsuleDepth = cf.GetFloat(p, v); }, - (s) => { return AvatarCapsuleDepth; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarCapsuleDepth=x;}, p, l, v); } ), - new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", - 1.5f, - (s,cf,p,v) => { AvatarCapsuleHeight = cf.GetFloat(p, v); }, - (s) => { return AvatarCapsuleHeight; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarCapsuleHeight=x;}, p, l, v); } ), - new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", - 0.1f, - (s,cf,p,v) => { AvatarContactProcessingThreshold = cf.GetFloat(p, v); }, - (s) => { return AvatarContactProcessingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarContactProcessingThreshold=x;}, p, l, v); } ), - - new ParameterDefn("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)", - 0.95f, - (s,cf,p,v) => { VehicleAngularDamping = cf.GetFloat(p, v); }, - (s) => { return VehicleAngularDamping; }, - (s,p,l,v) => { VehicleAngularDamping = v; } ), - - new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", - 0f, - (s,cf,p,v) => { s.UnmanagedParams[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); }, - (s) => { return s.UnmanagedParams[0].maxPersistantManifoldPoolSize; }, - (s,p,l,v) => { s.UnmanagedParams[0].maxPersistantManifoldPoolSize = v; } ), - new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)", - 0f, - (s,cf,p,v) => { s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); }, - (s) => { return s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize; }, - (s,p,l,v) => { s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize = v; } ), - new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count", - ConfigurationParameters.numericFalse, - (s,cf,p,v) => { s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, - (s) => { return s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation; }, - (s,p,l,v) => { s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = v; } ), - new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step", - ConfigurationParameters.numericFalse, - (s,cf,p,v) => { s.UnmanagedParams[0].shouldForceUpdateAllAabbs = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, - (s) => { return s.UnmanagedParams[0].shouldForceUpdateAllAabbs; }, - (s,p,l,v) => { s.UnmanagedParams[0].shouldForceUpdateAllAabbs = v; } ), - new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction", - ConfigurationParameters.numericTrue, - (s,cf,p,v) => { s.UnmanagedParams[0].shouldRandomizeSolverOrder = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, - (s) => { return s.UnmanagedParams[0].shouldRandomizeSolverOrder; }, - (s,p,l,v) => { s.UnmanagedParams[0].shouldRandomizeSolverOrder = v; } ), - new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands", - ConfigurationParameters.numericTrue, - (s,cf,p,v) => { s.UnmanagedParams[0].shouldSplitSimulationIslands = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, - (s) => { return s.UnmanagedParams[0].shouldSplitSimulationIslands; }, - (s,p,l,v) => { s.UnmanagedParams[0].shouldSplitSimulationIslands = v; } ), - new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching", - ConfigurationParameters.numericFalse, - (s,cf,p,v) => { s.UnmanagedParams[0].shouldEnableFrictionCaching = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, - (s) => { return s.UnmanagedParams[0].shouldEnableFrictionCaching; }, - (s,p,l,v) => { s.UnmanagedParams[0].shouldEnableFrictionCaching = v; } ), - new ParameterDefn("NumberOfSolverIterations", "Number of internal iterations (0 means default)", - 0f, // zero says use Bullet default - (s,cf,p,v) => { s.UnmanagedParams[0].numberOfSolverIterations = cf.GetFloat(p, v); }, - (s) => { return s.UnmanagedParams[0].numberOfSolverIterations; }, - (s,p,l,v) => { s.UnmanagedParams[0].numberOfSolverIterations = v; } ), - - new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)", - (float)BSLinkset.LinksetImplementation.Compound, - (s,cf,p,v) => { LinksetImplementation = cf.GetFloat(p,v); }, - (s) => { return LinksetImplementation; }, - (s,p,l,v) => { LinksetImplementation = v; } ), - new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", - ConfigurationParameters.numericFalse, - (s,cf,p,v) => { LinkConstraintUseFrameOffset = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, - (s) => { return LinkConstraintUseFrameOffset; }, - (s,p,l,v) => { LinkConstraintUseFrameOffset = v; } ), - new ParameterDefn("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints", - ConfigurationParameters.numericTrue, - (s,cf,p,v) => { LinkConstraintEnableTransMotor = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, - (s) => { return LinkConstraintEnableTransMotor; }, - (s,p,l,v) => { LinkConstraintEnableTransMotor = v; } ), - new ParameterDefn("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints", - 5.0f, - (s,cf,p,v) => { LinkConstraintTransMotorMaxVel = cf.GetFloat(p, v); }, - (s) => { return LinkConstraintTransMotorMaxVel; }, - (s,p,l,v) => { LinkConstraintTransMotorMaxVel = v; } ), - new ParameterDefn("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints", - 0.1f, - (s,cf,p,v) => { LinkConstraintTransMotorMaxForce = cf.GetFloat(p, v); }, - (s) => { return LinkConstraintTransMotorMaxForce; }, - (s,p,l,v) => { LinkConstraintTransMotorMaxForce = v; } ), - new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", - 0.1f, - (s,cf,p,v) => { LinkConstraintCFM = cf.GetFloat(p, v); }, - (s) => { return LinkConstraintCFM; }, - (s,p,l,v) => { LinkConstraintCFM = v; } ), - new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", - 0.1f, - (s,cf,p,v) => { LinkConstraintERP = cf.GetFloat(p, v); }, - (s) => { return LinkConstraintERP; }, - (s,p,l,v) => { LinkConstraintERP = v; } ), - new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)", - 40, - (s,cf,p,v) => { LinkConstraintSolverIterations = cf.GetFloat(p, v); }, - (s) => { return LinkConstraintSolverIterations; }, - (s,p,l,v) => { LinkConstraintSolverIterations = v; } ), - - new ParameterDefn("PhysicsMetricFrames", "Frames between outputting detailed phys metrics. (0 is off)", - 0f, - (s,cf,p,v) => { s.PhysicsMetricDumpFrames = cf.GetFloat(p, (int)v); }, - (s) => { return (float)s.PhysicsMetricDumpFrames; }, - (s,p,l,v) => { s.PhysicsMetricDumpFrames = (int)v; } ), - }; - - // Convert a boolean to our numeric true and false values - public static float NumericBool(bool b) - { - return (b ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse); - } - - // Convert numeric true and false values to a boolean - public static bool BoolNumeric(float b) - { - return (b == ConfigurationParameters.numericTrue ? true : false); - } - - // Search through the parameter definitions and return the matching - // ParameterDefn structure. - // Case does not matter as names are compared after converting to lower case. - // Returns 'false' if the parameter is not found. - internal static bool TryGetParameter(string paramName, out ParameterDefn defn) - { - bool ret = false; - ParameterDefn foundDefn = new ParameterDefn(); - string pName = paramName.ToLower(); - - foreach (ParameterDefn parm in ParameterDefinitions) - { - if (pName == parm.name.ToLower()) - { - foundDefn = parm; - ret = true; - break; - } - } - defn = foundDefn; - return ret; - } - - // Pass through the settable parameters and set the default values - internal static void SetParameterDefaultValues(BSScene physicsScene) - { - foreach (ParameterDefn parm in ParameterDefinitions) - { - parm.setter(physicsScene, parm.name, PhysParameterEntry.APPLY_TO_NONE, parm.defaultValue); - } - } - - // Get user set values out of the ini file. - internal static void SetParameterConfigurationValues(BSScene physicsScene, IConfig cfg) - { - foreach (ParameterDefn parm in ParameterDefinitions) - { - parm.userParam(physicsScene, cfg, parm.name, parm.defaultValue); - } - } - - internal static PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1]; - - // This creates an array in the correct format for returning the list of - // parameters. This is used by the 'list' option of the 'physics' command. - internal static void BuildParameterTable() - { - if (SettableParameters.Length < ParameterDefinitions.Length) - { - List entries = new List(); - for (int ii = 0; ii < ParameterDefinitions.Length; ii++) - { - ParameterDefn pd = ParameterDefinitions[ii]; - entries.Add(new PhysParameterEntry(pd.name, pd.desc)); - } - - // make the list in alphabetical order for estetic reasons - entries.Sort(delegate(PhysParameterEntry ppe1, PhysParameterEntry ppe2) - { - return ppe1.name.CompareTo(ppe2.name); - }); - - SettableParameters = entries.ToArray(); - } - } - - -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs deleted file mode 100755 index e7cb3e0..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OMV = OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -/* - * Class to wrap all objects. - * The rest of BulletSim doesn't need to keep checking for avatars or prims - * unless the difference is significant. - * - * Variables in the physicsl objects are in three forms: - * VariableName: used by the simulator and performs taint operations, etc - * RawVariableName: direct reference to the BulletSim storage for the variable value - * ForceVariableName: direct reference (store and fetch) to the value in the physics engine. - * The last two (and certainly the last one) should be referenced only in taint-time. - */ - -/* - * As of 20121221, the following are the call sequences (going down) for different script physical functions: - * llApplyImpulse llApplyRotImpulse llSetTorque llSetForce - * SOP.ApplyImpulse SOP.ApplyAngularImpulse SOP.SetAngularImpulse SOP.SetForce - * SOG.ApplyImpulse SOG.ApplyAngularImpulse SOG.SetAngularImpulse - * PA.AddForce PA.AddAngularForce PA.Torque = v PA.Force = v - * BS.ApplyCentralForce BS.ApplyTorque - */ - -public abstract class BSPhysObject : PhysicsActor -{ - protected BSPhysObject() - { - } - protected BSPhysObject(BSScene parentScene, uint localID, string name, string typeName) - { - PhysicsScene = parentScene; - LocalID = localID; - PhysObjectName = name; - TypeName = typeName; - - // We don't have any physical representation yet. - PhysBody = new BulletBody(localID); - PhysShape = new BulletShape(); - - // A linkset of just me - Linkset = BSLinkset.Factory(PhysicsScene, this); - LastAssetBuildFailed = false; - - // Default material type - Material = MaterialAttributes.Material.Wood; - - CollisionCollection = new CollisionEventUpdate(); - SubscribedEventsMs = 0; - CollidingStep = 0; - CollidingGroundStep = 0; - } - - // Tell the object to clean up. - public virtual void Destroy() - { - UnRegisterAllPreStepActions(); - } - - public BSScene PhysicsScene { get; protected set; } - // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor - public string PhysObjectName { get; protected set; } - public string TypeName { get; protected set; } - - public BSLinkset Linkset { get; set; } - public BSLinksetInfo LinksetInfo { get; set; } - - // Return the object mass without calculating it or having side effects - public abstract float RawMass { get; } - // Set the raw mass but also update physical mass properties (inertia, ...) - // 'inWorld' true if the object has already been added to the dynamic world. - public abstract void UpdatePhysicalMassProperties(float mass, bool inWorld); - - // The last value calculated for the prim's inertia - public OMV.Vector3 Inertia { get; set; } - - // Reference to the physical body (btCollisionObject) of this object - public BulletBody PhysBody; - // Reference to the physical shape (btCollisionShape) of this object - public BulletShape PhysShape; - - // 'true' if the mesh's underlying asset failed to build. - // This will keep us from looping after the first time the build failed. - public bool LastAssetBuildFailed { get; set; } - - // The objects base shape information. Null if not a prim type shape. - public PrimitiveBaseShape BaseShape { get; protected set; } - // Some types of objects have preferred physical representations. - // Returns SHAPE_UNKNOWN if there is no preference. - public virtual BSPhysicsShapeType PreferredPhysicalShape - { - get { return BSPhysicsShapeType.SHAPE_UNKNOWN; } - } - - // When the physical properties are updated, an EntityProperty holds the update values. - // Keep the current and last EntityProperties to enable computation of differences - // between the current update and the previous values. - public EntityProperties CurrentEntityProperties { get; set; } - public EntityProperties LastEntityProperties { get; set; } - - public virtual OMV.Vector3 Scale { get; set; } - public abstract bool IsSolid { get; } - public abstract bool IsStatic { get; } - - // Materialness - public MaterialAttributes.Material Material { get; private set; } - public override void SetMaterial(int material) - { - Material = (MaterialAttributes.Material)material; - } - - // Stop all physical motion. - public abstract void ZeroMotion(bool inTaintTime); - public abstract void ZeroAngularMotion(bool inTaintTime); - - // Step the vehicle simulation for this object. A NOOP if the vehicle was not configured. - public virtual void StepVehicle(float timeStep) { } - - // Update the physical location and motion of the object. Called with data from Bullet. - public abstract void UpdateProperties(EntityProperties entprop); - - public abstract OMV.Vector3 RawPosition { get; set; } - public abstract OMV.Vector3 ForcePosition { get; set; } - - public abstract OMV.Quaternion RawOrientation { get; set; } - public abstract OMV.Quaternion ForceOrientation { get; set; } - - // The system is telling us the velocity it wants to move at. - // protected OMV.Vector3 m_targetVelocity; // use the definition in PhysicsActor - public override OMV.Vector3 TargetVelocity - { - get { return m_targetVelocity; } - set - { - m_targetVelocity = value; - Velocity = value; - } - } - public abstract OMV.Vector3 ForceVelocity { get; set; } - - public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } - - public abstract float ForceBuoyancy { get; set; } - - public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } - - #region Collisions - - // Requested number of milliseconds between collision events. Zero means disabled. - protected int SubscribedEventsMs { get; set; } - // Given subscription, the time that a collision may be passed up - protected int NextCollisionOkTime { get; set; } - // The simulation step that last had a collision - protected long CollidingStep { get; set; } - // The simulation step that last had a collision with the ground - protected long CollidingGroundStep { get; set; } - // The simulation step that last collided with an object - protected long CollidingObjectStep { get; set; } - // The collision flags we think are set in Bullet - protected CollisionFlags CurrentCollisionFlags { get; set; } - - public override bool IsColliding { - get { return (CollidingStep == PhysicsScene.SimulationStep); } - set { - if (value) - CollidingStep = PhysicsScene.SimulationStep; - else - CollidingStep = 0; - } - } - public override bool CollidingGround { - get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } - set - { - if (value) - CollidingGroundStep = PhysicsScene.SimulationStep; - else - CollidingGroundStep = 0; - } - } - public override bool CollidingObj { - get { return (CollidingObjectStep == PhysicsScene.SimulationStep); } - set { - if (value) - CollidingObjectStep = PhysicsScene.SimulationStep; - else - CollidingObjectStep = 0; - } - } - - // The collisions that have been collected this tick - protected CollisionEventUpdate CollisionCollection; - - // The simulation step is telling this object about a collision. - // Return 'true' if a collision was processed and should be sent up. - // Called at taint time from within the Step() function - public virtual bool Collide(uint collidingWith, BSPhysObject collidee, - OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) - { - bool ret = false; - - // The following lines make IsColliding(), CollidingGround() and CollidingObj work - CollidingStep = PhysicsScene.SimulationStep; - if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID) - { - CollidingGroundStep = PhysicsScene.SimulationStep; - } - else - { - CollidingObjectStep = PhysicsScene.SimulationStep; - } - - // prims in the same linkset cannot collide with each other - if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) - { - return ret; - } - - // if someone has subscribed for collision events.... - if (SubscribedEvents()) { - CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); - DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}", - LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth); - - ret = true; - } - return ret; - } - - // Send the collected collisions into the simulator. - // Called at taint time from within the Step() function thus no locking problems - // with CollisionCollection and ObjectsWithNoMoreCollisions. - // Return 'true' if there were some actual collisions passed up - public virtual bool SendCollisions() - { - bool ret = true; - // If the 'no collision' call, force it to happen right now so quick collision_end - bool force = (CollisionCollection.Count == 0); - - // throttle the collisions to the number of milliseconds specified in the subscription - if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) - { - NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs; - - // We are called if we previously had collisions. If there are no collisions - // this time, send up one last empty event so OpenSim can sense collision end. - if (CollisionCollection.Count == 0) - { - // If I have no collisions this time, remove me from the list of objects with collisions. - ret = false; - } - - // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count); - base.SendCollisionUpdate(CollisionCollection); - - // The CollisionCollection instance is passed around in the simulator. - // Make sure we don't have a handle to that one and that a new one is used for next time. - // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here, - // a race condition is created for the other users of this instance. - CollisionCollection = new CollisionEventUpdate(); - } - return ret; - } - - // Subscribe for collision events. - // Parameter is the millisecond rate the caller wishes collision events to occur. - public override void SubscribeEvents(int ms) { - // DetailLog("{0},{1}.SubscribeEvents,subscribing,ms={2}", LocalID, TypeName, ms); - SubscribedEventsMs = ms; - if (ms > 0) - { - // make sure first collision happens - NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs); - - PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() - { - if (PhysBody.HasPhysicalBody) - CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - }); - } - else - { - // Subscribing for zero or less is the same as unsubscribing - UnSubscribeEvents(); - } - } - public override void UnSubscribeEvents() { - // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName); - SubscribedEventsMs = 0; - PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() - { - // Make sure there is a body there because sometimes destruction happens in an un-ideal order. - if (PhysBody.HasPhysicalBody) - CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - }); - } - // Return 'true' if the simulator wants collision events - public override bool SubscribedEvents() { - return (SubscribedEventsMs > 0); - } - - #endregion // Collisions - - #region Per Simulation Step actions - // There are some actions that must be performed for a physical object before each simulation step. - // These actions are optional so, rather than scanning all the physical objects and asking them - // if they have anything to do, a physical object registers for an event call before the step is performed. - // This bookkeeping makes it easy to add, remove and clean up after all these registrations. - private Dictionary RegisteredActions = new Dictionary(); - protected void RegisterPreStepAction(string op, uint id, BSScene.PreStepAction actn) - { - string identifier = op + "-" + id.ToString(); - RegisteredActions[identifier] = actn; - PhysicsScene.BeforeStep += actn; - DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier); - } - - // Unregister a pre step action. Safe to call if the action has not been registered. - protected void UnRegisterPreStepAction(string op, uint id) - { - string identifier = op + "-" + id.ToString(); - bool removed = false; - if (RegisteredActions.ContainsKey(identifier)) - { - PhysicsScene.BeforeStep -= RegisteredActions[identifier]; - RegisteredActions.Remove(identifier); - removed = true; - } - DetailLog("{0},BSPhysObject.UnRegisterPreStepAction,id={1},removed={2}", LocalID, identifier, removed); - } - - protected void UnRegisterAllPreStepActions() - { - foreach (KeyValuePair kvp in RegisteredActions) - { - PhysicsScene.BeforeStep -= kvp.Value; - } - RegisteredActions.Clear(); - DetailLog("{0},BSPhysObject.UnRegisterAllPreStepActions,", LocalID); - } - - - #endregion // Per Simulation Step actions - - // High performance detailed logging routine used by the physical objects. - protected void DetailLog(string msg, params Object[] args) - { - if (PhysicsScene.PhysicsLogging.Enabled) - PhysicsScene.DetailLog(msg, args); - } - -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs deleted file mode 100644 index 65be52a..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ - /// - /// Entry for a port of Bullet (http://bulletphysics.org/) to OpenSim. - /// This module interfaces to an unmanaged C++ library which makes the - /// actual calls into the Bullet physics engine. - /// The unmanaged library is found in opensim-libs::trunk/unmanaged/BulletSim/. - /// The unmanaged library is compiled and linked statically with Bullet - /// to create BulletSim.dll and libBulletSim.so (for both 32 and 64 bit). - /// -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() - { - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs deleted file mode 100644 index 826261c..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ /dev/null @@ -1,1513 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Reflection; -using System.Collections.Generic; -using System.Xml; -using log4net; -using OMV = OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; -using OpenSim.Region.Physics.ConvexDecompositionDotNet; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ - - [Serializable] -public sealed class BSPrim : BSPhysObject -{ - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private static readonly string LogHeader = "[BULLETS PRIM]"; - - // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. - private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user - - private bool _grabbed; - private bool _isSelected; - private bool _isVolumeDetect; - private OMV.Vector3 _position; - private float _mass; // the mass of this object - private float _density; - private OMV.Vector3 _force; - private OMV.Vector3 _velocity; - private OMV.Vector3 _torque; - private float _collisionScore; - private OMV.Vector3 _acceleration; - private OMV.Quaternion _orientation; - private int _physicsActorType; - private bool _isPhysical; - private bool _flying; - private float _friction; - private float _restitution; - private bool _setAlwaysRun; - private bool _throttleUpdates; - private bool _isColliding; - private bool _collidingGround; - private bool _collidingObj; - private bool _floatOnWater; - private OMV.Vector3 _rotationalVelocity; - private bool _kinematic; - private float _buoyancy; - - private BSDynamics _vehicle; - - private OMV.Vector3 _PIDTarget; - private bool _usePID; - private float _PIDTau; - private bool _useHoverPID; - private float _PIDHoverHeight; - private PIDHoverType _PIDHoverType; - private float _PIDHoverTao; - - public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, - OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) - : base(parent_scene, localID, primName, "BSPrim") - { - // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); - _physicsActorType = (int)ActorTypes.Prim; - _position = pos; - _size = size; - Scale = size; // prims are the size the user wants them to be (different for BSCharactes). - _orientation = rotation; - _buoyancy = 0f; - _velocity = OMV.Vector3.Zero; - _rotationalVelocity = OMV.Vector3.Zero; - BaseShape = pbs; - _isPhysical = pisPhysical; - _isVolumeDetect = false; - - // Someday set default attributes based on the material but, for now, we don't know the prim material yet. - // MaterialAttributes primMat = BSMaterials.GetAttributes(Material, pisPhysical); - _density = PhysicsScene.Params.defaultDensity; - _friction = PhysicsScene.Params.defaultFriction; - _restitution = PhysicsScene.Params.defaultRestitution; - - _vehicle = new BSDynamics(PhysicsScene, this); // add vehicleness - - _mass = CalculateMass(); - - // Cause linkset variables to be initialized (like mass) - Linkset.Refresh(this); - - DetailLog("{0},BSPrim.constructor,call", LocalID); - // do the actual object creation at taint time - PhysicsScene.TaintedObject("BSPrim.create", delegate() - { - CreateGeomAndObject(true); - - CurrentCollisionFlags = PhysicsScene.PE.GetCollisionFlags(PhysBody); - }); - } - - // called when this prim is being destroyed and we should free all the resources - public override void Destroy() - { - // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); - base.Destroy(); - - // Undo any links between me and any other object - BSPhysObject parentBefore = Linkset.LinksetRoot; - int childrenBefore = Linkset.NumberOfChildren; - - Linkset = Linkset.RemoveMeFromLinkset(this); - - DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}", - LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); - - // Undo any vehicle properties - this.VehicleType = (int)Vehicle.TYPE_NONE; - - PhysicsScene.TaintedObject("BSPrim.destroy", delegate() - { - DetailLog("{0},BSPrim.Destroy,taint,", LocalID); - // If there are physical body and shape, release my use of same. - PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); - PhysBody.Clear(); - PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); - PhysShape.Clear(); - }); - } - - // No one uses this property. - public override bool Stopped { - get { return false; } - } - public override OMV.Vector3 Size { - get { return _size; } - set { - // We presume the scale and size are the same. If scale must be changed for - // the physical shape, that is done when the geometry is built. - _size = value; - Scale = _size; - ForceBodyShapeRebuild(false); - } - } - - public override PrimitiveBaseShape Shape { - set { - BaseShape = value; - ForceBodyShapeRebuild(false); - } - } - // Whatever the linkset wants is what I want. - public override BSPhysicsShapeType PreferredPhysicalShape - { get { return Linkset.PreferredPhysicalShape(this); } } - - public override bool ForceBodyShapeRebuild(bool inTaintTime) - { - LastAssetBuildFailed = false; - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate() - { - _mass = CalculateMass(); // changing the shape changes the mass - CreateGeomAndObject(true); - }); - return true; - } - public override bool Grabbed { - set { _grabbed = value; - } - } - public override bool Selected { - set - { - if (value != _isSelected) - { - _isSelected = value; - PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() - { - DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); - SetObjectDynamic(false); - }); - } - } - } - public override void CrossingFailure() { return; } - - // link me to the specified parent - public override void link(PhysicsActor obj) { - BSPrim parent = obj as BSPrim; - if (parent != null) - { - BSPhysObject parentBefore = Linkset.LinksetRoot; - int childrenBefore = Linkset.NumberOfChildren; - - Linkset = parent.Linkset.AddMeToLinkset(this); - - DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", - LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); - } - return; - } - - // delink me from my linkset - public override void delink() { - // TODO: decide if this parent checking needs to happen at taint time - // Race condition here: if link() and delink() in same simulation tick, the delink will not happen - - BSPhysObject parentBefore = Linkset.LinksetRoot; - int childrenBefore = Linkset.NumberOfChildren; - - Linkset = Linkset.RemoveMeFromLinkset(this); - - DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", - LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); - return; - } - - // Set motion values to zero. - // Do it to the properties so the values get set in the physics engine. - // Push the setting of the values to the viewer. - // Called at taint time! - public override void ZeroMotion(bool inTaintTime) - { - _velocity = OMV.Vector3.Zero; - _acceleration = OMV.Vector3.Zero; - _rotationalVelocity = OMV.Vector3.Zero; - - // Zero some other properties in the physics engine - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() - { - if (PhysBody.HasPhysicalBody) - PhysicsScene.PE.ClearAllForces(PhysBody); - }); - } - public override void ZeroAngularMotion(bool inTaintTime) - { - _rotationalVelocity = OMV.Vector3.Zero; - // Zero some other properties in the physics engine - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() - { - // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity); - if (PhysBody.HasPhysicalBody) - { - PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity); - PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); - } - }); - } - - public override void LockAngularMotion(OMV.Vector3 axis) - { - DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); - return; - } - - public override OMV.Vector3 RawPosition - { - get { return _position; } - set { _position = value; } - } - public override OMV.Vector3 Position { - get { - /* NOTE: this refetch is not necessary. The simulator knows about linkset children - * and does not fetch this position info for children. Thus this is commented out. - // child prims move around based on their parent. Need to get the latest location - if (!Linkset.IsRoot(this)) - _position = Linkset.PositionGet(this); - */ - - // don't do the GetObjectPosition for root elements because this function is called a zillion times. - // _position = PhysicsScene.PE.GetObjectPosition2(PhysicsScene.World, BSBody); - return _position; - } - set { - // If the position must be forced into the physics engine, use ForcePosition. - // All positions are given in world positions. - if (_position == value) - { - DetailLog("{0},BSPrim.setPosition,call,positionNotChanging,pos={1},orient={2}", LocalID, _position, _orientation); - return; - } - _position = value; - PositionSanityCheck(false); - - // A linkset might need to know if a component information changed. - Linkset.UpdateProperties(this, false); - - PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() - { - DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); - ForcePosition = _position; - }); - } - } - public override OMV.Vector3 ForcePosition { - get { - _position = PhysicsScene.PE.GetPosition(PhysBody); - return _position; - } - set { - _position = value; - if (PhysBody.HasPhysicalBody) - { - PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); - ActivateIfPhysical(false); - } - } - } - - // Check that the current position is sane and, if not, modify the position to make it so. - // Check for being below terrain and being out of bounds. - // Returns 'true' of the position was made sane by some action. - private bool PositionSanityCheck(bool inTaintTime) - { - bool ret = false; - - if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(_position)) - { - // The physical object is out of the known/simulated area. - // Upper levels of code will handle the transition to other areas so, for - // the time, we just ignore the position. - return ret; - } - - float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); - OMV.Vector3 upForce = OMV.Vector3.Zero; - if (RawPosition.Z < terrainHeight) - { - DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); - float targetHeight = terrainHeight + (Size.Z / 2f); - // Upforce proportional to the distance away from the terrain. Correct the error in 1 sec. - upForce.Z = (terrainHeight - RawPosition.Z) * 1f; - ret = true; - } - - if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) - { - float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position); - // TODO: a floating motor so object will bob in the water - if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f) - { - // Upforce proportional to the distance away from the water. Correct the error in 1 sec. - upForce.Z = (waterHeight - RawPosition.Z) * 1f; - ret = true; - } - } - - // The above code computes a force to apply to correct any out-of-bounds problems. Apply same. - // TODO: This should be intergrated with a geneal physics action mechanism. - // TODO: This should be moderated with PID'ness. - if (ret) - { - // Apply upforce and overcome gravity. - OMV.Vector3 correctionForce = upForce - PhysicsScene.DefaultGravity; - DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, _position, upForce, correctionForce); - AddForce(correctionForce, false, inTaintTime); - } - return ret; - } - - // Return the effective mass of the object. - // The definition of this call is to return the mass of the prim. - // If the simulator cares about the mass of the linkset, it will sum it itself. - public override float Mass - { - get - { - return _mass; - } - } - - // used when we only want this prim's mass and not the linkset thing - public override float RawMass { - get { return _mass; } - } - // Set the physical mass to the passed mass. - // Note that this does not change _mass! - public override void UpdatePhysicalMassProperties(float physMass, bool inWorld) - { - if (PhysBody.HasPhysicalBody) - { - if (IsStatic) - { - PhysicsScene.PE.SetGravity(PhysBody, PhysicsScene.DefaultGravity); - Inertia = OMV.Vector3.Zero; - PhysicsScene.PE.SetMassProps(PhysBody, 0f, Inertia); - PhysicsScene.PE.UpdateInertiaTensor(PhysBody); - } - else - { - OMV.Vector3 grav = ComputeGravity(); - - if (inWorld) - { - // Changing interesting properties doesn't change proxy and collision cache - // information. The Bullet solution is to re-add the object to the world - // after parameters are changed. - PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); - } - - // The computation of mass props requires gravity to be set on the object. - PhysicsScene.PE.SetGravity(PhysBody, grav); - - Inertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass); - PhysicsScene.PE.SetMassProps(PhysBody, physMass, Inertia); - PhysicsScene.PE.UpdateInertiaTensor(PhysBody); - - // center of mass is at the zero of the object - // DEBUG DEBUG PhysicsScene.PE.SetCenterOfMassByPosRot(PhysBody, ForcePosition, ForceOrientation); - DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2},grav={3},inWorld={4}", LocalID, physMass, Inertia, grav, inWorld); - - if (inWorld) - { - AddObjectToPhysicalWorld(); - } - - // Must set gravity after it has been added to the world because, for unknown reasons, - // adding the object resets the object's gravity to world gravity - PhysicsScene.PE.SetGravity(PhysBody, grav); - - } - } - } - - // Return what gravity should be set to this very moment - private OMV.Vector3 ComputeGravity() - { - OMV.Vector3 ret = PhysicsScene.DefaultGravity; - - if (!IsStatic) - ret *= (1f - Buoyancy); - - return ret; - } - - // Is this used? - public override OMV.Vector3 CenterOfMass - { - get { return Linkset.CenterOfMass; } - } - - // Is this used? - public override OMV.Vector3 GeometricCenter - { - get { return Linkset.GeometricCenter; } - } - - public override OMV.Vector3 Force { - get { return _force; } - set { - _force = value; - if (_force != OMV.Vector3.Zero) - { - // If the force is non-zero, it must be reapplied each tick because - // Bullet clears the forces applied last frame. - RegisterPreStepAction("BSPrim.setForce", LocalID, - delegate(float timeStep) - { - DetailLog("{0},BSPrim.setForce,preStep,force={1}", LocalID, _force); - if (PhysBody.HasPhysicalBody) - { - PhysicsScene.PE.ApplyCentralForce(PhysBody, _force); - ActivateIfPhysical(false); - } - } - ); - } - else - { - UnRegisterPreStepAction("BSPrim.setForce", LocalID); - } - } - } - - public override int VehicleType { - get { - return (int)_vehicle.Type; // if we are a vehicle, return that type - } - set { - Vehicle type = (Vehicle)value; - - PhysicsScene.TaintedObject("setVehicleType", delegate() - { - // Done at taint time so we're sure the physics engine is not using the variables - // Vehicle code changes the parameters for this vehicle type. - _vehicle.ProcessTypeChange(type); - ActivateIfPhysical(false); - - // If an active vehicle, register the vehicle code to be called before each step - if (_vehicle.Type == Vehicle.TYPE_NONE) - UnRegisterPreStepAction("BSPrim.Vehicle", LocalID); - else - RegisterPreStepAction("BSPrim.Vehicle", LocalID, _vehicle.Step); - }); - } - } - public override void VehicleFloatParam(int param, float value) - { - PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() - { - _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); - ActivateIfPhysical(false); - }); - } - public override void VehicleVectorParam(int param, OMV.Vector3 value) - { - PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() - { - _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); - ActivateIfPhysical(false); - }); - } - public override void VehicleRotationParam(int param, OMV.Quaternion rotation) - { - PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() - { - _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); - ActivateIfPhysical(false); - }); - } - public override void VehicleFlags(int param, bool remove) - { - PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate() - { - _vehicle.ProcessVehicleFlags(param, remove); - }); - } - - // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more - public override void SetVolumeDetect(int param) { - bool newValue = (param != 0); - if (_isVolumeDetect != newValue) - { - _isVolumeDetect = newValue; - PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate() - { - // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); - SetObjectDynamic(true); - }); - } - return; - } - public override OMV.Vector3 Velocity { - get { return _velocity; } - set { - _velocity = value; - PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() - { - // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); - ForceVelocity = _velocity; - }); - } - } - public override OMV.Vector3 ForceVelocity { - get { return _velocity; } - set { - PhysicsScene.AssertInTaintTime("BSPrim.ForceVelocity"); - - _velocity = value; - if (PhysBody.HasPhysicalBody) - { - PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity); - ActivateIfPhysical(false); - } - } - } - public override OMV.Vector3 Torque { - get { return _torque; } - set { - _torque = value; - if (_torque != OMV.Vector3.Zero) - { - // If the torque is non-zero, it must be reapplied each tick because - // Bullet clears the forces applied last frame. - RegisterPreStepAction("BSPrim.setTorque", LocalID, - delegate(float timeStep) - { - if (PhysBody.HasPhysicalBody) - AddAngularForce(_torque, false, true); - } - ); - } - else - { - UnRegisterPreStepAction("BSPrim.setTorque", LocalID); - } - // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); - } - } - public override float CollisionScore { - get { return _collisionScore; } - set { _collisionScore = value; - } - } - public override OMV.Vector3 Acceleration { - get { return _acceleration; } - set { _acceleration = value; } - } - public override OMV.Quaternion RawOrientation - { - get { return _orientation; } - set { _orientation = value; } - } - public override OMV.Quaternion Orientation { - get { - /* NOTE: this refetch is not necessary. The simulator knows about linkset children - * and does not fetch this position info for children. Thus this is commented out. - // Children move around because tied to parent. Get a fresh value. - if (!Linkset.IsRoot(this)) - { - _orientation = Linkset.OrientationGet(this); - } - */ - return _orientation; - } - set { - if (_orientation == value) - return; - _orientation = value; - - // A linkset might need to know if a component information changed. - Linkset.UpdateProperties(this, false); - - PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() - { - if (PhysBody.HasPhysicalBody) - { - // _position = PhysicsScene.PE.GetObjectPosition(PhysicsScene.World, BSBody); - // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); - PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); - } - }); - } - } - // Go directly to Bullet to get/set the value. - public override OMV.Quaternion ForceOrientation - { - get - { - _orientation = PhysicsScene.PE.GetOrientation(PhysBody); - return _orientation; - } - set - { - _orientation = value; - PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); - } - } - public override int PhysicsActorType { - get { return _physicsActorType; } - set { _physicsActorType = value; } - } - public override bool IsPhysical { - get { return _isPhysical; } - set { - if (_isPhysical != value) - { - _isPhysical = value; - PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate() - { - DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); - SetObjectDynamic(true); - // whether phys-to-static or static-to-phys, the object is not moving. - ZeroMotion(true); - }); - } - } - } - - // An object is static (does not move) if selected or not physical - public override bool IsStatic - { - get { return _isSelected || !IsPhysical; } - } - - // An object is solid if it's not phantom and if it's not doing VolumeDetect - public override bool IsSolid - { - get { return !IsPhantom && !_isVolumeDetect; } - } - - // Make gravity work if the object is physical and not selected - // Called at taint-time!! - private void SetObjectDynamic(bool forceRebuild) - { - // Recreate the physical object if necessary - CreateGeomAndObject(forceRebuild); - } - - // Convert the simulator's physical properties into settings on BulletSim objects. - // There are four flags we're interested in: - // IsStatic: Object does not move, otherwise the object has mass and moves - // isSolid: other objects bounce off of this object - // isVolumeDetect: other objects pass through but can generate collisions - // collisionEvents: whether this object returns collision events - private void UpdatePhysicalParameters() - { - // DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape); - - // Mangling all the physical properties requires the object not be in the physical world. - // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). - PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); - - // Set up the object physicalness (does gravity and collisions move this object) - MakeDynamic(IsStatic); - - // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters) - _vehicle.Refresh(); - - // Arrange for collision events if the simulator wants them - EnableCollisions(SubscribedEvents()); - - // Make solid or not (do things bounce off or pass through this object). - MakeSolid(IsSolid); - - AddObjectToPhysicalWorld(); - - // Rebuild its shape - PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody); - - // Recompute any linkset parameters. - // When going from non-physical to physical, this re-enables the constraints that - // had been automatically disabled when the mass was set to zero. - // For compound based linksets, this enables and disables interactions of the children. - Linkset.Refresh(this); - - DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}", - LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape); - } - - // "Making dynamic" means changing to and from static. - // When static, gravity does not effect the object and it is fixed in space. - // When dynamic, the object can fall and be pushed by others. - // This is independent of its 'solidness' which controls what passes through - // this object and what interacts with it. - private void MakeDynamic(bool makeStatic) - { - if (makeStatic) - { - // Become a Bullet 'static' object type - CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT); - // Stop all movement - ZeroMotion(true); - - // Set various physical properties so other object interact properly - MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false); - PhysicsScene.PE.SetFriction(PhysBody, matAttrib.friction); - PhysicsScene.PE.SetRestitution(PhysBody, matAttrib.restitution); - - // Mass is zero which disables a bunch of physics stuff in Bullet - UpdatePhysicalMassProperties(0f, false); - // Set collision detection parameters - if (BSParam.CcdMotionThreshold > 0f) - { - PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); - PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); - } - - // The activation state is 'disabled' so Bullet will not try to act on it. - // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_SIMULATION); - // Start it out sleeping and physical actions could wake it up. - PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ISLAND_SLEEPING); - - // This collides like a static object - PhysBody.collisionType = CollisionType.Static; - - // There can be special things needed for implementing linksets - Linkset.MakeStatic(this); - } - else - { - // Not a Bullet static object - CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT); - - // Set various physical properties so other object interact properly - MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, true); - PhysicsScene.PE.SetFriction(PhysBody, matAttrib.friction); - PhysicsScene.PE.SetRestitution(PhysBody, matAttrib.restitution); - - // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 - // Since this can be called multiple times, only zero forces when becoming physical - // PhysicsScene.PE.ClearAllForces(BSBody); - - // For good measure, make sure the transform is set through to the motion state - PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); - - // Center of mass is at the center of the object - // DEBUG DEBUG PhysicsScene.PE.SetCenterOfMassByPosRot(Linkset.LinksetRoot.PhysBody, _position, _orientation); - - // A dynamic object has mass - UpdatePhysicalMassProperties(RawMass, false); - - // Set collision detection parameters - if (BSParam.CcdMotionThreshold > 0f) - { - PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); - PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); - } - - // Various values for simulation limits - PhysicsScene.PE.SetDamping(PhysBody, BSParam.LinearDamping, BSParam.AngularDamping); - PhysicsScene.PE.SetDeactivationTime(PhysBody, BSParam.DeactivationTime); - PhysicsScene.PE.SetSleepingThresholds(PhysBody, BSParam.LinearSleepingThreshold, BSParam.AngularSleepingThreshold); - PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); - - // This collides like an object. - PhysBody.collisionType = CollisionType.Dynamic; - - // Force activation of the object so Bullet will act on it. - // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. - PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG); - - // There might be special things needed for implementing linksets. - Linkset.MakeDynamic(this); - } - } - - // "Making solid" means that other object will not pass through this object. - // To make transparent, we create a Bullet ghost object. - // Note: This expects to be called from the UpdatePhysicalParameters() routine as - // the functions after this one set up the state of a possibly newly created collision body. - private void MakeSolid(bool makeSolid) - { - CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(PhysBody); - if (makeSolid) - { - // Verify the previous code created the correct shape for this type of thing. - if ((bodyType & CollisionObjectTypes.CO_RIGID_BODY) == 0) - { - m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType); - } - CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); - } - else - { - if ((bodyType & CollisionObjectTypes.CO_GHOST_OBJECT) == 0) - { - m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); - } - CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); - - // Change collision info from a static object to a ghosty collision object - PhysBody.collisionType = CollisionType.VolumeDetect; - } - } - - // Enable physical actions. Bullet will keep sleeping non-moving physical objects so - // they need waking up when parameters are changed. - // Called in taint-time!! - private void ActivateIfPhysical(bool forceIt) - { - if (IsPhysical && PhysBody.HasPhysicalBody) - PhysicsScene.PE.Activate(PhysBody, forceIt); - } - - // Turn on or off the flag controlling whether collision events are returned to the simulator. - private void EnableCollisions(bool wantsCollisionEvents) - { - if (wantsCollisionEvents) - { - CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - } - else - { - CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - } - } - - // Add me to the physical world. - // Object MUST NOT already be in the world. - // This routine exists because some assorted properties get mangled by adding to the world. - internal void AddObjectToPhysicalWorld() - { - if (PhysBody.HasPhysicalBody) - { - PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody); - } - else - { - m_log.ErrorFormat("{0} Attempt to add physical object without body. id={1}", LogHeader, LocalID); - DetailLog("{0},BSPrim.UpdatePhysicalParameters,addObjectWithoutBody,cType={1}", LocalID, PhysBody.collisionType); - } - } - - // prims don't fly - public override bool Flying { - get { return _flying; } - set { - _flying = value; - } - } - public override bool SetAlwaysRun { - get { return _setAlwaysRun; } - set { _setAlwaysRun = value; } - } - public override bool ThrottleUpdates { - get { return _throttleUpdates; } - set { _throttleUpdates = value; } - } - public bool IsPhantom { - get { - // SceneObjectPart removes phantom objects from the physics scene - // so, although we could implement touching and such, we never - // are invoked as a phantom object - return false; - } - } - public override bool FloatOnWater { - set { - _floatOnWater = value; - PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate() - { - if (_floatOnWater) - CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); - else - CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); - }); - } - } - public override OMV.Vector3 RotationalVelocity { - get { - return _rotationalVelocity; - } - set { - _rotationalVelocity = value; - // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); - PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() - { - DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); - ForceRotationalVelocity = _rotationalVelocity; - }); - } - } - public override OMV.Vector3 ForceRotationalVelocity { - get { - return _rotationalVelocity; - } - set { - _rotationalVelocity = value; - if (PhysBody.HasPhysicalBody) - { - PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); - ActivateIfPhysical(false); - } - } - } - public override bool Kinematic { - get { return _kinematic; } - set { _kinematic = value; - // m_log.DebugFormat("{0}: Kinematic={1}", LogHeader, _kinematic); - } - } - public override float Buoyancy { - get { return _buoyancy; } - set { - _buoyancy = value; - PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() - { - ForceBuoyancy = _buoyancy; - }); - } - } - public override float ForceBuoyancy { - get { return _buoyancy; } - set { - _buoyancy = value; - // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - // Force the recalculation of the various inertia,etc variables in the object - DetailLog("{0},BSPrim.ForceBuoyancy,buoy={1},mass={2}", LocalID, _buoyancy, _mass); - UpdatePhysicalMassProperties(_mass, true); - ActivateIfPhysical(false); - } - } - - // Used for MoveTo - public override OMV.Vector3 PIDTarget { - set { _PIDTarget = value; } - } - public override float PIDTau { - set { _PIDTau = value; } - } - public override bool PIDActive { - set { _usePID = value; } - } - - // Used for llSetHoverHeight and maybe vehicle height - // Hover Height will override MoveTo target's Z - public override bool PIDHoverActive { - set { _useHoverPID = value; } - } - public override float PIDHoverHeight { - set { _PIDHoverHeight = value; } - } - public override PIDHoverType PIDHoverType { - set { _PIDHoverType = value; } - } - public override float PIDHoverTau { - set { _PIDHoverTao = value; } - } - - // For RotLookAt - public override OMV.Quaternion APIDTarget { set { return; } } - public override bool APIDActive { set { return; } } - public override float APIDStrength { set { return; } } - public override float APIDDamping { set { return; } } - - public override void AddForce(OMV.Vector3 force, bool pushforce) { - // Since this force is being applied in only one step, make this a force per second. - OMV.Vector3 addForce = force / PhysicsScene.LastTimeStep; - AddForce(addForce, pushforce, false); - } - // Applying a force just adds this to the total force on the object. - // This added force will only last the next simulation tick. - public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { - // for an object, doesn't matter if force is a pushforce or not - if (force.IsFinite()) - { - float magnitude = force.Length(); - if (magnitude > BSParam.MaxAddForceMagnitude) - { - // Force has a limit - force = force / magnitude * BSParam.MaxAddForceMagnitude; - } - - OMV.Vector3 addForce = force; - DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce); - - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() - { - // Bullet adds this central force to the total force for this tick - DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce); - if (PhysBody.HasPhysicalBody) - { - PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce); - ActivateIfPhysical(false); - } - }); - } - else - { - m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); - return; - } - } - - public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { - AddAngularForce(force, pushforce, false); - } - public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) - { - if (force.IsFinite()) - { - OMV.Vector3 angForce = force; - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate() - { - if (PhysBody.HasPhysicalBody) - { - PhysicsScene.PE.ApplyTorque(PhysBody, angForce); - ActivateIfPhysical(false); - } - }); - } - else - { - m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); - return; - } - } - - // A torque impulse. - // ApplyTorqueImpulse adds torque directly to the angularVelocity. - // AddAngularForce accumulates the force and applied it to the angular velocity all at once. - // Computed as: angularVelocity += impulse * inertia; - public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) - { - OMV.Vector3 applyImpulse = impulse; - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() - { - if (PhysBody.HasPhysicalBody) - { - PhysicsScene.PE.ApplyTorqueImpulse(PhysBody, applyImpulse); - ActivateIfPhysical(false); - } - }); - } - - public override void SetMomentum(OMV.Vector3 momentum) { - // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); - } - #region Mass Calculation - - private float CalculateMass() - { - float volume = _size.X * _size.Y * _size.Z; // default - float tmp; - - float returnMass = 0; - float hollowAmount = (float)BaseShape.ProfileHollow * 2.0e-5f; - float hollowVolume = hollowAmount * hollowAmount; - - switch (BaseShape.ProfileShape) - { - case ProfileShape.Square: - // default box - - if (BaseShape.PathCurve == (byte)Extrusion.Straight) - { - if (hollowAmount > 0.0) - { - switch (BaseShape.HollowShape) - { - case HollowShape.Square: - case HollowShape.Same: - break; - - case HollowShape.Circle: - - hollowVolume *= 0.78539816339f; - break; - - case HollowShape.Triangle: - - hollowVolume *= (0.5f * .5f); - break; - - default: - hollowVolume = 0; - break; - } - volume *= (1.0f - hollowVolume); - } - } - - else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) - { - //a tube - - volume *= 0.78539816339e-2f * (float)(200 - BaseShape.PathScaleX); - tmp= 1.0f -2.0e-2f * (float)(200 - BaseShape.PathScaleY); - volume -= volume*tmp*tmp; - - if (hollowAmount > 0.0) - { - hollowVolume *= hollowAmount; - - switch (BaseShape.HollowShape) - { - case HollowShape.Square: - case HollowShape.Same: - break; - - case HollowShape.Circle: - hollowVolume *= 0.78539816339f;; - break; - - case HollowShape.Triangle: - hollowVolume *= 0.5f * 0.5f; - break; - default: - hollowVolume = 0; - break; - } - volume *= (1.0f - hollowVolume); - } - } - - break; - - case ProfileShape.Circle: - - if (BaseShape.PathCurve == (byte)Extrusion.Straight) - { - volume *= 0.78539816339f; // elipse base - - if (hollowAmount > 0.0) - { - switch (BaseShape.HollowShape) - { - case HollowShape.Same: - case HollowShape.Circle: - break; - - case HollowShape.Square: - hollowVolume *= 0.5f * 2.5984480504799f; - break; - - case HollowShape.Triangle: - hollowVolume *= .5f * 1.27323954473516f; - break; - - default: - hollowVolume = 0; - break; - } - volume *= (1.0f - hollowVolume); - } - } - - else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) - { - volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - BaseShape.PathScaleX); - tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY); - volume *= (1.0f - tmp * tmp); - - if (hollowAmount > 0.0) - { - - // calculate the hollow volume by it's shape compared to the prim shape - hollowVolume *= hollowAmount; - - switch (BaseShape.HollowShape) - { - case HollowShape.Same: - case HollowShape.Circle: - break; - - case HollowShape.Square: - hollowVolume *= 0.5f * 2.5984480504799f; - break; - - case HollowShape.Triangle: - hollowVolume *= .5f * 1.27323954473516f; - break; - - default: - hollowVolume = 0; - break; - } - volume *= (1.0f - hollowVolume); - } - } - break; - - case ProfileShape.HalfCircle: - if (BaseShape.PathCurve == (byte)Extrusion.Curve1) - { - volume *= 0.52359877559829887307710723054658f; - } - break; - - case ProfileShape.EquilateralTriangle: - - if (BaseShape.PathCurve == (byte)Extrusion.Straight) - { - volume *= 0.32475953f; - - if (hollowAmount > 0.0) - { - - // calculate the hollow volume by it's shape compared to the prim shape - switch (BaseShape.HollowShape) - { - case HollowShape.Same: - case HollowShape.Triangle: - hollowVolume *= .25f; - break; - - case HollowShape.Square: - hollowVolume *= 0.499849f * 3.07920140172638f; - break; - - case HollowShape.Circle: - // Hollow shape is a perfect cyllinder in respect to the cube's scale - // Cyllinder hollow volume calculation - - hollowVolume *= 0.1963495f * 3.07920140172638f; - break; - - default: - hollowVolume = 0; - break; - } - volume *= (1.0f - hollowVolume); - } - } - else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) - { - volume *= 0.32475953f; - volume *= 0.01f * (float)(200 - BaseShape.PathScaleX); - tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY); - volume *= (1.0f - tmp * tmp); - - if (hollowAmount > 0.0) - { - - hollowVolume *= hollowAmount; - - switch (BaseShape.HollowShape) - { - case HollowShape.Same: - case HollowShape.Triangle: - hollowVolume *= .25f; - break; - - case HollowShape.Square: - hollowVolume *= 0.499849f * 3.07920140172638f; - break; - - case HollowShape.Circle: - - hollowVolume *= 0.1963495f * 3.07920140172638f; - break; - - default: - hollowVolume = 0; - break; - } - volume *= (1.0f - hollowVolume); - } - } - break; - - default: - break; - } - - - - float taperX1; - float taperY1; - float taperX; - float taperY; - float pathBegin; - float pathEnd; - float profileBegin; - float profileEnd; - - if (BaseShape.PathCurve == (byte)Extrusion.Straight || BaseShape.PathCurve == (byte)Extrusion.Flexible) - { - taperX1 = BaseShape.PathScaleX * 0.01f; - if (taperX1 > 1.0f) - taperX1 = 2.0f - taperX1; - taperX = 1.0f - taperX1; - - taperY1 = BaseShape.PathScaleY * 0.01f; - if (taperY1 > 1.0f) - taperY1 = 2.0f - taperY1; - taperY = 1.0f - taperY1; - } - else - { - taperX = BaseShape.PathTaperX * 0.01f; - if (taperX < 0.0f) - taperX = -taperX; - taperX1 = 1.0f - taperX; - - taperY = BaseShape.PathTaperY * 0.01f; - if (taperY < 0.0f) - taperY = -taperY; - taperY1 = 1.0f - taperY; - - } - - - volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); - - pathBegin = (float)BaseShape.PathBegin * 2.0e-5f; - pathEnd = 1.0f - (float)BaseShape.PathEnd * 2.0e-5f; - volume *= (pathEnd - pathBegin); - - // this is crude aproximation - profileBegin = (float)BaseShape.ProfileBegin * 2.0e-5f; - profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f; - volume *= (profileEnd - profileBegin); - - returnMass = _density * volume; - - /* Comment out code that computes the mass of the linkset. That is done in the Linkset class. - if (IsRootOfLinkset) - { - foreach (BSPrim prim in _childrenPrims) - { - returnMass += prim.CalculateMass(); - } - } - */ - - returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass); - - return returnMass; - }// end CalculateMass - #endregion Mass Calculation - - // Rebuild the geometry and object. - // This is called when the shape changes so we need to recreate the mesh/hull. - // Called at taint-time!!! - public void CreateGeomAndObject(bool forceRebuild) - { - // If this prim is part of a linkset, we must remove and restore the physical - // links if the body is rebuilt. - bool needToRestoreLinkset = false; - bool needToRestoreVehicle = false; - - // Create the correct physical representation for this type of object. - // Updates PhysBody and PhysShape with the new information. - // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. - PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody) - { - // Called if the current prim body is about to be destroyed. - // Remove all the physical dependencies on the old body. - // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...) - needToRestoreLinkset = Linkset.RemoveBodyDependencies(this); - needToRestoreVehicle = _vehicle.RemoveBodyDependencies(this); - }); - - if (needToRestoreLinkset) - { - // If physical body dependencies were removed, restore them - Linkset.RestoreBodyDependencies(this); - } - if (needToRestoreVehicle) - { - // If physical body dependencies were removed, restore them - _vehicle.RestoreBodyDependencies(this); - } - - // Make sure the properties are set on the new object - UpdatePhysicalParameters(); - return; - } - - // The physics engine says that properties have updated. Update same and inform - // the world that things have changed. - // TODO: do we really need to check for changed? Maybe just copy values and call RequestPhysicsterseUpdate() - enum UpdatedProperties { - Position = 1 << 0, - Rotation = 1 << 1, - Velocity = 1 << 2, - Acceleration = 1 << 3, - RotationalVel = 1 << 4 - } - - const float ROTATION_TOLERANCE = 0.01f; - const float VELOCITY_TOLERANCE = 0.001f; - const float POSITION_TOLERANCE = 0.05f; - const float ACCELERATION_TOLERANCE = 0.01f; - const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; - - public override void UpdateProperties(EntityProperties entprop) - { - // Updates only for individual prims and for the root object of a linkset. - if (Linkset.IsRoot(this)) - { - // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet - // TODO: handle physics introduced by Bullet with computed vehicle physics. - if (_vehicle.IsActive) - { - entprop.RotationalVelocity = OMV.Vector3.Zero; - } - - // Assign directly to the local variables so the normal set action does not happen - _position = entprop.Position; - _orientation = entprop.Rotation; - _velocity = entprop.Velocity; - _acceleration = entprop.Acceleration; - _rotationalVelocity = entprop.RotationalVelocity; - - // The sanity check can change the velocity and/or position. - if (IsPhysical && PositionSanityCheck(true)) - { - entprop.Position = _position; - entprop.Velocity = _velocity; - } - - OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG - DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", - LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); - - // remember the current and last set values - LastEntityProperties = CurrentEntityProperties; - CurrentEntityProperties = entprop; - - base.RequestPhysicsterseUpdate(); - } - /* - else - { - // For debugging, report the movement of children - DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", - LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, - entprop.Acceleration, entprop.RotationalVelocity); - } - */ - - // The linkset implimentation might want to know about this. - Linkset.UpdateProperties(this, true); - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs deleted file mode 100644 index 7017194..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ /dev/null @@ -1,946 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading; -using OpenSim.Framework; -using OpenSim.Region.Framework; -using OpenSim.Region.CoreModules; -using Logging = OpenSim.Region.CoreModules.Framework.Statistics.Logging; -using OpenSim.Region.Physics.Manager; -using Nini.Config; -using log4net; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public sealed class BSScene : PhysicsScene, IPhysicsParameters -{ - internal static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - internal static readonly string LogHeader = "[BULLETS SCENE]"; - - // The name of the region we're working for. - public string RegionName { get; private set; } - - public string BulletSimVersion = "?"; - - // The handle to the underlying managed or unmanaged version of Bullet being used. - public string BulletEngineName { get; private set; } - public BSAPITemplate PE; - - public Dictionary PhysObjects; - public BSShapeCollection Shapes; - - // Keeping track of the objects with collisions so we can report begin and end of a collision - public HashSet ObjectsWithCollisions = new HashSet(); - public HashSet ObjectsWithNoMoreCollisions = new HashSet(); - // Keep track of all the avatars so we can send them a collision event - // every tick so OpenSim will update its animation. - private HashSet m_avatars = new HashSet(); - - // let my minuions use my logger - public ILog Logger { get { return m_log; } } - - public IMesher mesher; - public uint WorldID { get; private set; } - public BulletWorld World { get; private set; } - - // All the constraints that have been allocated in this instance. - public BSConstraintCollection Constraints { get; private set; } - - // Simulation parameters - internal int m_maxSubSteps; - internal float m_fixedTimeStep; - internal long m_simulationStep = 0; - internal float NominalFrameRate { get; set; } - public long SimulationStep { get { return m_simulationStep; } } - internal int m_taintsToProcessPerStep; - internal float LastTimeStep { get; private set; } - - // Physical objects can register for prestep or poststep events - public delegate void PreStepAction(float timeStep); - public delegate void PostStepAction(float timeStep); - public event PreStepAction BeforeStep; - public event PreStepAction AfterStep; - - // A value of the time now so all the collision and update routines do not have to get their own - // Set to 'now' just before all the prims and actors are called for collisions and updates - public int SimulationNowTime { get; private set; } - - // True if initialized and ready to do simulation steps - private bool m_initialized = false; - - // Flag which is true when processing taints. - // Not guaranteed to be correct all the time (don't depend on this) but good for debugging. - public bool InTaintTime { get; private set; } - - // Pinned memory used to pass step information between managed and unmanaged - internal int m_maxCollisionsPerFrame; - internal CollisionDesc[] m_collisionArray; - - internal int m_maxUpdatesPerFrame; - internal EntityProperties[] m_updateArray; - - public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero - public const uint GROUNDPLANE_ID = 1; - public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here - - public float SimpleWaterLevel { get; set; } - public BSTerrainManager TerrainManager { get; private set; } - - public ConfigurationParameters Params - { - get { return UnmanagedParams[0]; } - } - public Vector3 DefaultGravity - { - get { return new Vector3(0f, 0f, Params.gravity); } - } - // Just the Z value of the gravity - public float DefaultGravityZ - { - get { return Params.gravity; } - } - - // When functions in the unmanaged code must be called, it is only - // done at a known time just before the simulation step. The taint - // system saves all these function calls and executes them in - // order before the simulation. - public delegate void TaintCallback(); - private struct TaintCallbackEntry - { - public String ident; - public TaintCallback callback; - public TaintCallbackEntry(string i, TaintCallback c) - { - ident = i; - callback = c; - } - } - private Object _taintLock = new Object(); // lock for using the next object - private List _taintOperations; - private Dictionary _postTaintOperations; - private List _postStepOperations; - - // A pointer to an instance if this structure is passed to the C++ code - // Used to pass basic configuration values to the unmanaged code. - internal ConfigurationParameters[] UnmanagedParams; - - // Sometimes you just have to log everything. - public Logging.LogWriter PhysicsLogging; - private bool m_physicsLoggingEnabled; - private string m_physicsLoggingDir; - private string m_physicsLoggingPrefix; - private int m_physicsLoggingFileMinutes; - private bool m_physicsLoggingDoFlush; - private bool m_physicsPhysicalDumpEnabled; - public float PhysicsMetricDumpFrames { get; set; } - // 'true' of the vehicle code is to log lots of details - public bool VehicleLoggingEnabled { get; private set; } - public bool VehiclePhysicalLoggingEnabled { get; private set; } - - #region Construction and Initialization - public BSScene(string identifier) - { - m_initialized = false; - // we are passed the name of the region we're working for. - RegionName = identifier; - } - - public override void Initialise(IMesher meshmerizer, IConfigSource config) - { - mesher = meshmerizer; - _taintOperations = new List(); - _postTaintOperations = new Dictionary(); - _postStepOperations = new List(); - PhysObjects = new Dictionary(); - Shapes = new BSShapeCollection(this); - - // Allocate pinned memory to pass parameters. - UnmanagedParams = new ConfigurationParameters[1]; - - // Set default values for physics parameters plus any overrides from the ini file - GetInitialParameterValues(config); - - // Get the connection to the physics engine (could be native or one of many DLLs) - PE = SelectUnderlyingBulletEngine(BulletEngineName); - - // Enable very detailed logging. - // By creating an empty logger when not logging, the log message invocation code - // can be left in and every call doesn't have to check for null. - if (m_physicsLoggingEnabled) - { - PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes); - PhysicsLogging.ErrorLogger = m_log; // for DEBUG. Let's the logger output error messages. - } - else - { - PhysicsLogging = new Logging.LogWriter(); - } - - // Allocate memory for returning of the updates and collisions from the physics engine - m_collisionArray = new CollisionDesc[m_maxCollisionsPerFrame]; - m_updateArray = new EntityProperties[m_maxUpdatesPerFrame]; - - // The bounding box for the simulated world. The origin is 0,0,0 unless we're - // a child in a mega-region. - // Bullet actually doesn't care about the extents of the simulated - // area. It tracks active objects no matter where they are. - Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); - - World = PE.Initialize(worldExtent, Params, m_maxCollisionsPerFrame, ref m_collisionArray, m_maxUpdatesPerFrame, ref m_updateArray); - - Constraints = new BSConstraintCollection(World); - - TerrainManager = new BSTerrainManager(this); - TerrainManager.CreateInitialGroundPlaneAndTerrain(); - - m_log.WarnFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)BSParam.LinksetImplementation); - - InTaintTime = false; - m_initialized = true; - } - - // All default parameter values are set here. There should be no values set in the - // variable definitions. - private void GetInitialParameterValues(IConfigSource config) - { - ConfigurationParameters parms = new ConfigurationParameters(); - UnmanagedParams[0] = parms; - - BSParam.SetParameterDefaultValues(this); - - if (config != null) - { - // If there are specifications in the ini file, use those values - IConfig pConfig = config.Configs["BulletSim"]; - if (pConfig != null) - { - BSParam.SetParameterConfigurationValues(this, pConfig); - - // There are two Bullet implementations to choose from - BulletEngineName = pConfig.GetString("BulletEngine", "BulletUnmanaged"); - - // Very detailed logging for physics debugging - // TODO: the boolean values can be moved to the normal parameter processing. - m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); - m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", "."); - m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-"); - m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); - m_physicsLoggingDoFlush = pConfig.GetBoolean("PhysicsLoggingDoFlush", false); - m_physicsPhysicalDumpEnabled = pConfig.GetBoolean("PhysicsPhysicalDumpEnabled", false); - // Very detailed logging for vehicle debugging - VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); - VehiclePhysicalLoggingEnabled = pConfig.GetBoolean("VehiclePhysicalLoggingEnabled", false); - - // Do any replacements in the parameters - m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName); - } - - // The material characteristics. - BSMaterials.InitializeFromDefaults(Params); - if (pConfig != null) - { - // Let the user add new and interesting material property values. - BSMaterials.InitializefromParameters(pConfig); - } - } - } - - // A helper function that handles a true/false parameter and returns the proper float number encoding - float ParamBoolean(IConfig config, string parmName, float deflt) - { - float ret = deflt; - if (config.Contains(parmName)) - { - ret = ConfigurationParameters.numericFalse; - if (config.GetBoolean(parmName, false)) - { - ret = ConfigurationParameters.numericTrue; - } - } - return ret; - } - - // Select the connection to the actual Bullet implementation. - // The main engine selection is the engineName up to the first hypen. - // So "Bullet-2.80-OpenCL-Intel" specifies the 'bullet' class here and the whole name - // is passed to the engine to do its special selection, etc. - private BSAPITemplate SelectUnderlyingBulletEngine(string engineName) - { - // For the moment, do a simple switch statement. - // Someday do fancyness with looking up the interfaces in the assembly. - BSAPITemplate ret = null; - - string selectionName = engineName.ToLower(); - int hyphenIndex = engineName.IndexOf("-"); - if (hyphenIndex > 0) - selectionName = engineName.ToLower().Substring(0, hyphenIndex - 1); - - switch (selectionName) - { - case "bulletunmanaged": - ret = new BSAPIUnman(engineName, this); - break; - case "bulletxna": - ret = new BSAPIXNA(engineName, this); - break; - } - - if (ret == null) - { - m_log.ErrorFormat("{0) COULD NOT SELECT BULLET ENGINE: '[BulletSim]PhysicsEngine' must be either 'BulletUnmanaged-*' or 'BulletXNA-*'", LogHeader); - } - else - { - m_log.WarnFormat("{0} Selected bullet engine {1} -> {2}/{3}", LogHeader, engineName, ret.BulletEngineName, ret.BulletEngineVersion); - } - - return ret; - } - - public override void Dispose() - { - // m_log.DebugFormat("{0}: Dispose()", LogHeader); - - // make sure no stepping happens while we're deleting stuff - m_initialized = false; - - foreach (KeyValuePair kvp in PhysObjects) - { - kvp.Value.Destroy(); - } - PhysObjects.Clear(); - - // Now that the prims are all cleaned up, there should be no constraints left - if (Constraints != null) - { - Constraints.Dispose(); - Constraints = null; - } - - if (Shapes != null) - { - Shapes.Dispose(); - Shapes = null; - } - - if (TerrainManager != null) - { - TerrainManager.ReleaseGroundPlaneAndTerrain(); - TerrainManager.Dispose(); - TerrainManager = null; - } - - // Anything left in the unmanaged code should be cleaned out - PE.Shutdown(World); - - // Not logging any more - PhysicsLogging.Close(); - } - #endregion // Construction and Initialization - - #region Prim and Avatar addition and removal - - 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); - - if (!m_initialized) return null; - - BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying); - lock (PhysObjects) PhysObjects.Add(localID, actor); - - // TODO: Remove kludge someday. - // We must generate a collision for avatars whether they collide or not. - // This is required by OpenSim to update avatar animations, etc. - lock (m_avatars) m_avatars.Add(actor); - - return actor; - } - - public override void RemoveAvatar(PhysicsActor actor) - { - // m_log.DebugFormat("{0}: RemoveAvatar", LogHeader); - - if (!m_initialized) return; - - BSCharacter bsactor = actor as BSCharacter; - if (bsactor != null) - { - try - { - lock (PhysObjects) PhysObjects.Remove(actor.LocalID); - // Remove kludge someday - lock (m_avatars) m_avatars.Remove(bsactor); - } - catch (Exception e) - { - m_log.WarnFormat("{0}: Attempt to remove avatar that is not in physics scene: {1}", LogHeader, e); - } - bsactor.Destroy(); - // bsactor.dispose(); - } - } - - public override void RemovePrim(PhysicsActor prim) - { - if (!m_initialized) return; - - BSPrim bsprim = prim as BSPrim; - if (bsprim != null) - { - DetailLog("{0},RemovePrim,call", bsprim.LocalID); - // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); - try - { - lock (PhysObjects) PhysObjects.Remove(bsprim.LocalID); - } - catch (Exception e) - { - m_log.ErrorFormat("{0}: Attempt to remove prim that is not in physics scene: {1}", LogHeader, e); - } - bsprim.Destroy(); - // bsprim.dispose(); - } - else - { - m_log.ErrorFormat("{0}: Attempt to remove prim that is not a BSPrim type.", LogHeader); - } - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, - Vector3 size, Quaternion rotation, bool isPhysical, uint localID) - { - // m_log.DebugFormat("{0}: AddPrimShape2: {1}", LogHeader, primName); - - if (!m_initialized) return null; - - DetailLog("{0},AddPrimShape,call", localID); - - BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); - lock (PhysObjects) PhysObjects.Add(localID, prim); - return prim; - } - - // This is a call from the simulator saying that some physical property has been updated. - // The BulletSim driver senses the changing of relevant properties so this taint - // information call is not needed. - public override void AddPhysicsActorTaint(PhysicsActor prim) { } - - #endregion // Prim and Avatar addition and removal - - #region Simulation - // Simulate one timestep - public override float Simulate(float timeStep) - { - // prevent simulation until we've been initialized - if (!m_initialized) return 5.0f; - - LastTimeStep = timeStep; - - int updatedEntityCount = 0; - int collidersCount = 0; - - int beforeTime = 0; - int simTime = 0; - - // update the prim states while we know the physics engine is not busy - int numTaints = _taintOperations.Count; - - InTaintTime = true; // Only used for debugging so locking is not necessary. - - ProcessTaints(); - - // Some of the physical objects requre individual, pre-step calls - TriggerPreStepEvent(timeStep); - - // the prestep actions might have added taints - numTaints += _taintOperations.Count; - ProcessTaints(); - - InTaintTime = false; // Only used for debugging so locking is not necessary. - - // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world. - // Only enable this in a limited test world with few objects. - if (m_physicsPhysicalDumpEnabled) - PE.DumpAllInfo(World); - - // step the physical world one interval - m_simulationStep++; - int numSubSteps = 0; - try - { - if (PhysicsLogging.Enabled) - beforeTime = Util.EnvironmentTickCount(); - - numSubSteps = PE.PhysicsStep(World, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out collidersCount); - - if (PhysicsLogging.Enabled) - { - simTime = Util.EnvironmentTickCountSubtract(beforeTime); - DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}", - DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, - updatedEntityCount, collidersCount, ObjectsWithCollisions.Count); - } - } - catch (Exception e) - { - m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}", - LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e); - DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}", - DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount); - updatedEntityCount = 0; - collidersCount = 0; - } - - if ((m_simulationStep % PhysicsMetricDumpFrames) == 0) - PE.DumpPhysicsStatistics(World); - - // Get a value for 'now' so all the collision and update routines don't have to get their own. - SimulationNowTime = Util.EnvironmentTickCount(); - - // If there were collisions, process them by sending the event to the prim. - // Collisions must be processed before updates. - if (collidersCount > 0) - { - for (int ii = 0; ii < collidersCount; ii++) - { - uint cA = m_collisionArray[ii].aID; - uint cB = m_collisionArray[ii].bID; - Vector3 point = m_collisionArray[ii].point; - Vector3 normal = m_collisionArray[ii].normal; - SendCollision(cA, cB, point, normal, 0.01f); - SendCollision(cB, cA, point, -normal, 0.01f); - } - } - - // The above SendCollision's batch up the collisions on the objects. - // Now push the collisions into the simulator. - if (ObjectsWithCollisions.Count > 0) - { - foreach (BSPhysObject bsp in ObjectsWithCollisions) - if (!bsp.SendCollisions()) - { - // If the object is done colliding, see that it's removed from the colliding list - ObjectsWithNoMoreCollisions.Add(bsp); - } - } - - // This is a kludge to get avatar movement updates. - // The simulator expects collisions for avatars even if there are have been no collisions. - // The event updates avatar animations and stuff. - // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. - foreach (BSPhysObject bsp in m_avatars) - if (!ObjectsWithCollisions.Contains(bsp)) // don't call avatars twice - bsp.SendCollisions(); - - // Objects that are done colliding are removed from the ObjectsWithCollisions list. - // Not done above because it is inside an iteration of ObjectWithCollisions. - // This complex collision processing is required to create an empty collision - // event call after all real collisions have happened on an object. This enables - // the simulator to generate the 'collision end' event. - if (ObjectsWithNoMoreCollisions.Count > 0) - { - foreach (BSPhysObject po in ObjectsWithNoMoreCollisions) - ObjectsWithCollisions.Remove(po); - ObjectsWithNoMoreCollisions.Clear(); - } - // Done with collisions. - - // If any of the objects had updated properties, tell the object it has been changed by the physics engine - if (updatedEntityCount > 0) - { - for (int ii = 0; ii < updatedEntityCount; ii++) - { - EntityProperties entprop = m_updateArray[ii]; - BSPhysObject pobj; - if (PhysObjects.TryGetValue(entprop.ID, out pobj)) - { - pobj.UpdateProperties(entprop); - } - } - } - - TriggerPostStepEvent(timeStep); - - // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world. - // Only enable this in a limited test world with few objects. - if (m_physicsPhysicalDumpEnabled) - PE.DumpAllInfo(World); - - // The physics engine returns the number of milliseconds it simulated this call. - // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. - // Multiply by a fixed nominal frame rate to give a rate similar to the simulator (usually 55). - return (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate; - } - - // Something has collided - private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penetration) - { - if (localID <= TerrainManager.HighestTerrainID) - { - return; // don't send collisions to the terrain - } - - BSPhysObject collider; - if (!PhysObjects.TryGetValue(localID, out collider)) - { - // If the object that is colliding cannot be found, just ignore the collision. - DetailLog("{0},BSScene.SendCollision,colliderNotInObjectList,id={1},with={2}", DetailLogZero, localID, collidingWith); - return; - } - - // The terrain is not in the physical object list so 'collidee' can be null when Collide() is called. - BSPhysObject collidee = null; - PhysObjects.TryGetValue(collidingWith, out collidee); - - // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); - - if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration)) - { - // If a collision was posted, remember to send it to the simulator - ObjectsWithCollisions.Add(collider); - } - - return; - } - - #endregion // Simulation - - public override void GetResults() { } - - #region Terrain - - public override void SetTerrain(float[] heightMap) { - TerrainManager.SetTerrain(heightMap); - } - - public override void SetWaterLevel(float baseheight) - { - SimpleWaterLevel = baseheight; - } - - public override void DeleteTerrain() - { - // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader); - } - - // Although no one seems to check this, I do support combining. - public override bool SupportsCombining() - { - return TerrainManager.SupportsCombining(); - } - // This call says I am a child to region zero in a mega-region. 'pScene' is that - // of region zero, 'offset' is my offset from regions zero's origin, and - // 'extents' is the largest XY that is handled in my region. - public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) - { - TerrainManager.Combine(pScene, offset, extents); - } - - // Unhook all the combining that I know about. - public override void UnCombine(PhysicsScene pScene) - { - TerrainManager.UnCombine(pScene); - } - - #endregion // Terrain - - public override Dictionary GetTopColliders() - { - return new Dictionary(); - } - - public override bool IsThreaded { get { return false; } } - - #region Taints - // The simulation execution order is: - // Simulate() - // DoOneTimeTaints - // TriggerPreStepEvent - // DoOneTimeTaints - // Step() - // ProcessAndForwardCollisions - // ProcessAndForwardPropertyUpdates - // TriggerPostStepEvent - - // Calls to the PhysicsActors can't directly call into the physics engine - // because it might be busy. 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(String ident, TaintCallback callback) - { - if (!m_initialized) return; - - lock (_taintLock) - { - _taintOperations.Add(new TaintCallbackEntry(ident, callback)); - } - - return; - } - - // Sometimes a potentially tainted operation can be used in and out of taint time. - // This routine executes the command immediately if in taint-time otherwise it is queued. - public void TaintedObject(bool inTaintTime, string ident, TaintCallback callback) - { - if (inTaintTime) - callback(); - else - TaintedObject(ident, callback); - } - - private void TriggerPreStepEvent(float timeStep) - { - PreStepAction actions = BeforeStep; - if (actions != null) - actions(timeStep); - - } - - private void TriggerPostStepEvent(float timeStep) - { - PreStepAction actions = AfterStep; - if (actions != null) - actions(timeStep); - - } - - // 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() - { - ProcessRegularTaints(); - ProcessPostTaintTaints(); - } - - private void ProcessRegularTaints() - { - if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process - { - // swizzle a new list into the list location so we can process what's there - List oldList; - lock (_taintLock) - { - oldList = _taintOperations; - _taintOperations = new List(); - } - - foreach (TaintCallbackEntry tcbe in oldList) - { - try - { - DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG - tcbe.callback(); - } - catch (Exception e) - { - m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e); - } - } - oldList.Clear(); - } - } - - // Schedule an update to happen after all the regular taints are processed. - // Note that new requests for the same operation ("ident") for the same object ("ID") - // will replace any previous operation by the same object. - public void PostTaintObject(String ident, uint ID, TaintCallback callback) - { - string uniqueIdent = ident + "-" + ID.ToString(); - lock (_taintLock) - { - _postTaintOperations[uniqueIdent] = new TaintCallbackEntry(uniqueIdent, callback); - } - - return; - } - - // Taints that happen after the normal taint processing but before the simulation step. - private void ProcessPostTaintTaints() - { - if (_postTaintOperations.Count > 0) - { - Dictionary oldList; - lock (_taintLock) - { - oldList = _postTaintOperations; - _postTaintOperations = new Dictionary(); - } - - foreach (KeyValuePair kvp in oldList) - { - try - { - DetailLog("{0},BSScene.ProcessPostTaintTaints,doTaint,id={1}", DetailLogZero, kvp.Key); // DEBUG DEBUG DEBUG - kvp.Value.callback(); - } - catch (Exception e) - { - m_log.ErrorFormat("{0}: ProcessPostTaintTaints: {1}: Exception: {2}", LogHeader, kvp.Key, e); - } - } - oldList.Clear(); - } - } - - // Only used for debugging. Does not change state of anything so locking is not necessary. - public bool AssertInTaintTime(string whereFrom) - { - if (!InTaintTime) - { - DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom); - m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom); - Util.PrintCallStack(DetailLog); - } - return InTaintTime; - } - - #endregion // Taints - - #region INI and command line parameter processing - - #region IPhysicsParameters - // Get the list of parameters this physics engine supports - public PhysParameterEntry[] GetParameterList() - { - BSParam.BuildParameterTable(); - return BSParam.SettableParameters; - } - - // Set parameter on a specific or all instances. - // Return 'false' if not able to set the parameter. - // Setting the value in the m_params block will change the value the physics engine - // will use the next time since it's pinned and shared memory. - // Some of the values require calling into the physics engine to get the new - // value activated ('terrainFriction' for instance). - public bool SetPhysicsParameter(string parm, float val, uint localID) - { - bool ret = false; - BSParam.ParameterDefn theParam; - if (BSParam.TryGetParameter(parm, out theParam)) - { - theParam.setter(this, parm, localID, val); - ret = true; - } - return ret; - } - - // update all the localIDs specified - // If the local ID is APPLY_TO_NONE, just change the default value - // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs - // If the localID is a specific object, apply the parameter change to only that object - internal delegate void AssignVal(float x); - internal void UpdateParameterObject(AssignVal setDefault, string parm, uint localID, float val) - { - List objectIDs = new List(); - switch (localID) - { - case PhysParameterEntry.APPLY_TO_NONE: - setDefault(val); // setting only the default value - // This will cause a call into the physical world if some operation is specified (SetOnObject). - objectIDs.Add(TERRAIN_ID); - TaintedUpdateParameter(parm, objectIDs, val); - break; - case PhysParameterEntry.APPLY_TO_ALL: - setDefault(val); // setting ALL also sets the default value - lock (PhysObjects) objectIDs = new List(PhysObjects.Keys); - TaintedUpdateParameter(parm, objectIDs, val); - break; - default: - // setting only one localID - objectIDs.Add(localID); - TaintedUpdateParameter(parm, objectIDs, val); - break; - } - } - - // schedule the actual updating of the paramter to when the phys engine is not busy - private void TaintedUpdateParameter(string parm, List lIDs, float val) - { - float xval = val; - List xlIDs = lIDs; - string xparm = parm; - TaintedObject("BSScene.UpdateParameterSet", delegate() { - BSParam.ParameterDefn thisParam; - if (BSParam.TryGetParameter(xparm, out thisParam)) - { - if (thisParam.onObject != null) - { - foreach (uint lID in xlIDs) - { - BSPhysObject theObject = null; - PhysObjects.TryGetValue(lID, out theObject); - thisParam.onObject(this, theObject, xval); - } - } - } - }); - } - - // Get parameter. - // Return 'false' if not able to get the parameter. - public bool GetPhysicsParameter(string parm, out float value) - { - float val = 0f; - bool ret = false; - BSParam.ParameterDefn theParam; - if (BSParam.TryGetParameter(parm, out theParam)) - { - val = theParam.getter(this); - ret = true; - } - value = val; - return ret; - } - - #endregion IPhysicsParameters - - #endregion Runtime settable parameters - - // Invoke the detailed logger and output something if it's enabled. - public void DetailLog(string msg, params Object[] args) - { - PhysicsLogging.Write(msg, args); - // Add the Flush() if debugging crashes. Gets all the messages written out. - if (m_physicsLoggingDoFlush) PhysicsLogging.Flush(); - } - // Used to fill in the LocalID when there isn't one. It's the correct number of characters. - public const string DetailLogZero = "0000000000"; - -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs deleted file mode 100755 index d361f18..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ /dev/null @@ -1,1009 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using OMV = OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; -using OpenSim.Region.Physics.ConvexDecompositionDotNet; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public sealed class BSShapeCollection : IDisposable -{ - private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; - - private BSScene PhysicsScene { get; set; } - - private Object m_collectionActivityLock = new Object(); - - // Description of a Mesh - private struct MeshDesc - { - public BulletShape shape; - public int referenceCount; - public DateTime lastReferenced; - public UInt64 shapeKey; - } - - // Description of a hull. - // Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations. - private struct HullDesc - { - public BulletShape shape; - public int referenceCount; - public DateTime lastReferenced; - public UInt64 shapeKey; - } - - // The sharable set of meshes and hulls. Indexed by their shape hash. - private Dictionary Meshes = new Dictionary(); - private Dictionary Hulls = new Dictionary(); - - private bool DDetail = false; - - public BSShapeCollection(BSScene physScene) - { - PhysicsScene = physScene; - // Set the next to 'true' for very detailed shape update detailed logging (detailed details?) - // While detailed debugging is still active, this is better than commenting out all the - // DetailLog statements. When debugging slows down, this and the protected logging - // statements can be commented/removed. - DDetail = true; - } - - public void Dispose() - { - // TODO!!!!!!!!! - } - - // Callbacks called just before either the body or shape is destroyed. - // Mostly used for changing bodies out from under Linksets. - // Useful for other cases where parameters need saving. - // Passing 'null' says no callback. - public delegate void ShapeDestructionCallback(BulletShape shape); - public delegate void BodyDestructionCallback(BulletBody body); - - // Called to update/change the body and shape for an object. - // First checks the shape and updates that if necessary then makes - // sure the body is of the right type. - // Return 'true' if either the body or the shape changed. - // 'shapeCallback' and 'bodyCallback' are, if non-null, functions called just before - // the current shape or body is destroyed. This allows the caller to remove any - // higher level dependencies on the shape or body. Mostly used for LinkSets to - // remove the physical constraints before the body is destroyed. - // Called at taint-time!! - public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim, - ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) - { - PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape"); - - bool ret = false; - - // This lock could probably be pushed down lower but building shouldn't take long - lock (m_collectionActivityLock) - { - // Do we have the correct geometry for this type of object? - // Updates prim.BSShape with information/pointers to shape. - // Returns 'true' of BSShape is changed to a new shape. - bool newGeom = CreateGeom(forceRebuild, prim, shapeCallback); - // If we had to select a new shape geometry for the object, - // rebuild the body around it. - // Updates prim.BSBody with information/pointers to requested body - // Returns 'true' if BSBody was changed. - bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, - prim.PhysShape, bodyCallback); - ret = newGeom || newBody; - } - DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", - prim.LocalID, forceRebuild, ret, prim.PhysBody, prim.PhysShape); - - return ret; - } - - public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim) - { - return GetBodyAndShape(forceRebuild, sim, prim, null, null); - } - - // Track another user of a body. - // We presume the caller has allocated the body. - // Bodies only have one user so the body is just put into the world if not already there. - public void ReferenceBody(BulletBody body, bool inTaintTime) - { - lock (m_collectionActivityLock) - { - if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body); - PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate() - { - if (!PhysicsScene.PE.IsInWorld(PhysicsScene.World, body)) - { - PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, body); - if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); - } - }); - } - } - - // Release the usage of a body. - // Called when releasing use of a BSBody. BSShape is handled separately. - public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback ) - { - if (!body.HasPhysicalBody) - return; - - lock (m_collectionActivityLock) - { - PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate() - { - if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}", - body.ID, body, inTaintTime); - // If the caller needs to know the old body is going away, pass the event up. - if (bodyCallback != null) bodyCallback(body); - - if (PhysicsScene.PE.IsInWorld(PhysicsScene.World, body)) - { - PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body); - if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body); - } - - // Zero any reference to the shape so it is not freed when the body is deleted. - PhysicsScene.PE.SetCollisionShape(PhysicsScene.World, body, null); - PhysicsScene.PE.DestroyObject(PhysicsScene.World, body); - }); - } - } - - // Track the datastructures and use count for a shape. - // When creating a hull, this is called first to reference the mesh - // and then again to reference the hull. - // Meshes and hulls for the same shape have the same hash key. - // NOTE that native shapes are not added to the mesh list or removed. - // Returns 'true' if this is the initial reference to the shape. Otherwise reused. - public bool ReferenceShape(BulletShape shape) - { - bool ret = false; - switch (shape.type) - { - case BSPhysicsShapeType.SHAPE_MESH: - MeshDesc meshDesc; - if (Meshes.TryGetValue(shape.shapeKey, out meshDesc)) - { - // There is an existing instance of this mesh. - meshDesc.referenceCount++; - if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}", - BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); - } - else - { - // This is a new reference to a mesh - meshDesc.shape = shape.Clone(); - meshDesc.shapeKey = shape.shapeKey; - // We keep a reference to the underlying IMesh data so a hull can be built - meshDesc.referenceCount = 1; - if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}", - BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); - ret = true; - } - meshDesc.lastReferenced = System.DateTime.Now; - Meshes[shape.shapeKey] = meshDesc; - break; - case BSPhysicsShapeType.SHAPE_HULL: - HullDesc hullDesc; - if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) - { - // There is an existing instance of this hull. - hullDesc.referenceCount++; - if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}", - BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); - } - else - { - // This is a new reference to a hull - hullDesc.shape = shape.Clone(); - hullDesc.shapeKey = shape.shapeKey; - hullDesc.referenceCount = 1; - if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}", - BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); - ret = true; - - } - hullDesc.lastReferenced = System.DateTime.Now; - Hulls[shape.shapeKey] = hullDesc; - break; - case BSPhysicsShapeType.SHAPE_UNKNOWN: - break; - default: - // Native shapes are not tracked and they don't go into any list - break; - } - return ret; - } - - // Release the usage of a shape. - public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback) - { - if (!shape.HasPhysicalShape) - return; - - PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate() - { - if (shape.HasPhysicalShape) - { - if (shape.isNativeShape) - { - // Native shapes are not tracked and are released immediately - if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", - BSScene.DetailLogZero, shape.AddrString, inTaintTime); - if (shapeCallback != null) shapeCallback(shape); - PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape); - } - else - { - switch (shape.type) - { - case BSPhysicsShapeType.SHAPE_HULL: - DereferenceHull(shape, shapeCallback); - break; - case BSPhysicsShapeType.SHAPE_MESH: - DereferenceMesh(shape, shapeCallback); - break; - case BSPhysicsShapeType.SHAPE_COMPOUND: - DereferenceCompound(shape, shapeCallback); - break; - case BSPhysicsShapeType.SHAPE_UNKNOWN: - break; - default: - break; - } - } - } - }); - } - - // Count down the reference count for a mesh shape - // Called at taint-time. - private void DereferenceMesh(BulletShape shape, ShapeDestructionCallback shapeCallback) - { - MeshDesc meshDesc; - if (Meshes.TryGetValue(shape.shapeKey, out meshDesc)) - { - meshDesc.referenceCount--; - // TODO: release the Bullet storage - if (shapeCallback != null) shapeCallback(shape); - meshDesc.lastReferenced = System.DateTime.Now; - Meshes[shape.shapeKey] = meshDesc; - if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}", - BSScene.DetailLogZero, shape, meshDesc.referenceCount); - - } - } - - // Count down the reference count for a hull shape - // Called at taint-time. - private void DereferenceHull(BulletShape shape, ShapeDestructionCallback shapeCallback) - { - HullDesc hullDesc; - if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) - { - hullDesc.referenceCount--; - // TODO: release the Bullet storage (aging old entries?) - - // Tell upper layers that, if they have dependencies on this shape, this link is going away - if (shapeCallback != null) shapeCallback(shape); - - hullDesc.lastReferenced = System.DateTime.Now; - Hulls[shape.shapeKey] = hullDesc; - if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}", - BSScene.DetailLogZero, shape, hullDesc.referenceCount); - } - } - - // Remove a reference to a compound shape. - // Taking a compound shape apart is a little tricky because if you just delete the - // physical shape, it will free all the underlying children. We can't do that because - // they could be shared. So, this removes each of the children from the compound and - // dereferences them separately before destroying the compound collision object itself. - // Called at taint-time. - private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback) - { - if (!PhysicsScene.PE.IsCompound(shape)) - { - // Failed the sanity check!! - PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}", - LogHeader, shape.type, shape.AddrString); - if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}", - BSScene.DetailLogZero, shape.type, shape.AddrString); - return; - } - - int numChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(shape); - if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren); - - for (int ii = numChildren - 1; ii >= 0; ii--) - { - BulletShape childShape = PhysicsScene.PE.RemoveChildShapeFromCompoundShapeIndex(shape, ii); - DereferenceAnonCollisionShape(childShape); - } - PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape); - } - - // Sometimes we have a pointer to a collision shape but don't know what type it is. - // Figure out type and call the correct dereference routine. - // Called at taint-time. - private void DereferenceAnonCollisionShape(BulletShape shapeInfo) - { - MeshDesc meshDesc; - HullDesc hullDesc; - - if (TryGetMeshByPtr(shapeInfo, out meshDesc)) - { - shapeInfo.type = BSPhysicsShapeType.SHAPE_MESH; - shapeInfo.shapeKey = meshDesc.shapeKey; - } - else - { - if (TryGetHullByPtr(shapeInfo, out hullDesc)) - { - shapeInfo.type = BSPhysicsShapeType.SHAPE_HULL; - shapeInfo.shapeKey = hullDesc.shapeKey; - } - else - { - if (PhysicsScene.PE.IsCompound(shapeInfo)) - { - shapeInfo.type = BSPhysicsShapeType.SHAPE_COMPOUND; - } - else - { - if (PhysicsScene.PE.IsNativeShape(shapeInfo)) - { - shapeInfo.isNativeShape = true; - shapeInfo.type = BSPhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) - } - } - } - } - - if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo); - - if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN) - { - DereferenceShape(shapeInfo, true, null); - } - else - { - PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}", - LogHeader, PhysicsScene.RegionName, shapeInfo.AddrString); - } - } - - // Create the geometry information in Bullet for later use. - // The objects needs a hull if it's physical otherwise a mesh is enough. - // if 'forceRebuild' is true, the geometry is unconditionally rebuilt. For meshes and hulls, - // shared geometries will be used. If the parameters of the existing shape are the same - // as this request, the shape is not rebuilt. - // Info in prim.BSShape is updated to the new shape. - // Returns 'true' if the geometry was rebuilt. - // Called at taint-time! - private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - bool ret = false; - bool haveShape = false; - - if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE) - { - // an avatar capsule is close to a native shape (it is not shared) - GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE, shapeCallback); - if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); - ret = true; - haveShape = true; - } - - // Compound shapes are handled special as they are rebuilt from scratch. - // This isn't too great a hardship since most of the child shapes will have already been created. - if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND) - { - ret = GetReferenceToCompoundShape(prim, shapeCallback); - if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape); - haveShape = true; - } - - if (!haveShape) - { - ret = CreateGeomNonSpecial(forceRebuild, prim, shapeCallback); - } - - return ret; - } - - // Create a mesh/hull shape or a native shape if 'nativeShapePossible' is 'true'. - public bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - bool ret = false; - bool haveShape = false; - bool nativeShapePossible = true; - PrimitiveBaseShape pbs = prim.BaseShape; - - // If the prim attributes are simple, this could be a simple Bullet native shape - if (!haveShape - && pbs != null - && nativeShapePossible - && ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) - || (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) ) ) - { - // Get the scale of any existing shape so we can see if the new shape is same native type and same size. - OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero; - if (prim.PhysShape.HasPhysicalShape) - scaleOfExistingShape = PhysicsScene.PE.GetLocalScaling(prim.PhysShape); - - if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}", - prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.type); - - // It doesn't look like Bullet scales spheres so make sure the scales are all equal - if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) - && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z) - { - haveShape = true; - if (forceRebuild - || prim.Scale != scaleOfExistingShape - || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE - ) - { - ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE, - FixedShapeKey.KEY_SPHERE, shapeCallback); - if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", - prim.LocalID, forceRebuild, prim.PhysShape); - } - } - if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) - { - haveShape = true; - if (forceRebuild - || prim.Scale != scaleOfExistingShape - || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX - ) - { - ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX, - FixedShapeKey.KEY_BOX, shapeCallback); - if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", - prim.LocalID, forceRebuild, prim.PhysShape); - } - } - } - - // If a simple shape is not happening, create a mesh and possibly a hull. - if (!haveShape && pbs != null) - { - ret = CreateGeomMeshOrHull(prim, shapeCallback); - } - - return ret; - } - - public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - - bool ret = false; - // Note that if it's a native shape, the check for physical/non-physical is not - // made. Native shapes work in either case. - if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects) - { - // Update prim.BSShape to reference a hull of this shape. - ret = GetReferenceToHull(prim,shapeCallback); - if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", - prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); - } - else - { - ret = GetReferenceToMesh(prim, shapeCallback); - if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", - prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); - } - return ret; - } - - // Creates a native shape and assignes it to prim.BSShape. - // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape(). - private bool GetReferenceToNativeShape(BSPhysObject prim, - BSPhysicsShapeType shapeType, FixedShapeKey shapeKey, - ShapeDestructionCallback shapeCallback) - { - // release any previous shape - DereferenceShape(prim.PhysShape, true, shapeCallback); - - BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey); - - // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. - if (DDetail) DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", - prim.LocalID, newShape, prim.Scale); - - // native shapes are scaled by Bullet - prim.PhysShape = newShape; - return true; - } - - private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, BSPhysicsShapeType shapeType, - FixedShapeKey shapeKey) - { - BulletShape newShape; - // Need to make sure the passed shape information is for the native type. - ShapeData nativeShapeData = new ShapeData(); - nativeShapeData.Type = shapeType; - nativeShapeData.ID = prim.LocalID; - nativeShapeData.Scale = prim.Scale; - nativeShapeData.Size = prim.Scale; // unneeded, I think. - nativeShapeData.MeshKey = (ulong)shapeKey; - nativeShapeData.HullKey = (ulong)shapeKey; - - if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE) - { - - newShape = PhysicsScene.PE.BuildCapsuleShape(PhysicsScene.World, 1f, 1f, prim.Scale); - if (DDetail) DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); - } - else - { - // Native shapes are scaled in Bullet so set the scaling to the size - newShape = PhysicsScene.PE.BuildNativeShape(PhysicsScene.World, nativeShapeData); - - } - if (!newShape.HasPhysicalShape) - { - PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", - LogHeader, prim.LocalID, shapeType); - } - newShape.shapeKey = (System.UInt64)shapeKey; - newShape.isNativeShape = true; - - return newShape; - } - - // Builds a mesh shape in the physical world and updates prim.BSShape. - // Dereferences previous shape in BSShape and adds a reference for this new shape. - // Returns 'true' of a mesh was actually built. Otherwise . - // Called at taint-time! - private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - BulletShape newShape = new BulletShape(); - - float lod; - System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); - - // if this new shape is the same as last time, don't recreate the mesh - if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH) - return false; - - if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}", - prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); - - // Since we're recreating new, get rid of the reference to the previous shape - DereferenceShape(prim.PhysShape, true, shapeCallback); - - newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, prim.BaseShape, prim.Size, lod); - // Take evasive action if the mesh was not constructed. - newShape = VerifyMeshCreated(newShape, prim); - - ReferenceShape(newShape); - - prim.PhysShape = newShape; - - return true; // 'true' means a new shape has been added to this prim - } - - private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) - { - BulletShape newShape = new BulletShape(); - IMesh meshData = null; - - MeshDesc meshDesc; - if (Meshes.TryGetValue(newMeshKey, out meshDesc)) - { - // If the mesh has already been built just use it. - newShape = meshDesc.shape.Clone(); - } - else - { - meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false); - - if (meshData != null) - { - int[] indices = meshData.getIndexListAsInt(); - List vertices = meshData.getVertexList(); - - float[] verticesAsFloats = new float[vertices.Count * 3]; - int vi = 0; - foreach (OMV.Vector3 vv in vertices) - { - verticesAsFloats[vi++] = vv.X; - verticesAsFloats[vi++] = vv.Y; - verticesAsFloats[vi++] = vv.Z; - } - - // m_log.DebugFormat("{0}: BSShapeCollection.CreatePhysicalMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", - // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); - - newShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World, - indices.GetLength(0), indices, vertices.Count, verticesAsFloats); - } - } - newShape.shapeKey = newMeshKey; - - return newShape; - } - - // See that hull shape exists in the physical world and update prim.BSShape. - // We could be creating the hull because scale changed or whatever. - private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - BulletShape newShape; - - float lod; - System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); - - // if the hull hasn't changed, don't rebuild it - if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL) - return false; - - if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}", - prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); - - // Remove usage of the previous shape. - DereferenceShape(prim.PhysShape, true, shapeCallback); - - newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod); - newShape = VerifyMeshCreated(newShape, prim); - - ReferenceShape(newShape); - - prim.PhysShape = newShape; - return true; // 'true' means a new shape has been added to this prim - } - - List m_hulls; - private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) - { - - BulletShape newShape = new BulletShape(); - IntPtr hullPtr = IntPtr.Zero; - - HullDesc hullDesc; - if (Hulls.TryGetValue(newHullKey, out hullDesc)) - { - // If the hull shape already is created, just use it. - newShape = hullDesc.shape.Clone(); - } - else - { - // Build a new hull in the physical world - // Pass true for physicalness as this creates some sort of bounding box which we don't need - IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false); - if (meshData != null) - { - - int[] indices = meshData.getIndexListAsInt(); - List vertices = meshData.getVertexList(); - - //format conversion from IMesh format to DecompDesc format - List convIndices = new List(); - List convVertices = new List(); - for (int ii = 0; ii < indices.GetLength(0); ii++) - { - convIndices.Add(indices[ii]); - } - foreach (OMV.Vector3 vv in vertices) - { - convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); - } - - // setup and do convex hull conversion - m_hulls = new List(); - DecompDesc dcomp = new DecompDesc(); - dcomp.mIndices = convIndices; - dcomp.mVertices = convVertices; - ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); - // create the hull into the _hulls variable - convexBuilder.process(dcomp); - - // Convert the vertices and indices for passing to unmanaged. - // The hull information is passed as a large floating point array. - // The format is: - // convHulls[0] = number of hulls - // convHulls[1] = number of vertices in first hull - // convHulls[2] = hull centroid X coordinate - // convHulls[3] = hull centroid Y coordinate - // convHulls[4] = hull centroid Z coordinate - // convHulls[5] = first hull vertex X - // convHulls[6] = first hull vertex Y - // convHulls[7] = first hull vertex Z - // convHulls[8] = second hull vertex X - // ... - // convHulls[n] = number of vertices in second hull - // convHulls[n+1] = second hull centroid X coordinate - // ... - // - // TODO: is is very inefficient. Someday change the convex hull generator to return - // data structures that do not need to be converted in order to pass to Bullet. - // And maybe put the values directly into pinned memory rather than marshaling. - int hullCount = m_hulls.Count; - int totalVertices = 1; // include one for the count of the hulls - foreach (ConvexResult cr in m_hulls) - { - totalVertices += 4; // add four for the vertex count and centroid - totalVertices += cr.HullIndices.Count * 3; // we pass just triangles - } - float[] convHulls = new float[totalVertices]; - - convHulls[0] = (float)hullCount; - int jj = 1; - foreach (ConvexResult cr in m_hulls) - { - // copy vertices for index access - float3[] verts = new float3[cr.HullVertices.Count]; - int kk = 0; - foreach (float3 ff in cr.HullVertices) - { - verts[kk++] = ff; - } - - // add to the array one hull's worth of data - convHulls[jj++] = cr.HullIndices.Count; - convHulls[jj++] = 0f; // centroid x,y,z - convHulls[jj++] = 0f; - convHulls[jj++] = 0f; - foreach (int ind in cr.HullIndices) - { - convHulls[jj++] = verts[ind].x; - convHulls[jj++] = verts[ind].y; - convHulls[jj++] = verts[ind].z; - } - } - // create the hull data structure in Bullet - newShape = PhysicsScene.PE.CreateHullShape(PhysicsScene.World, hullCount, convHulls); - } - } - - newShape.shapeKey = newHullKey; - - return newShape; - } - - // Callback from convex hull creater with a newly created hull. - // Just add it to our collection of hulls for this shape. - private void HullReturn(ConvexResult result) - { - m_hulls.Add(result); - return; - } - - // Compound shapes are always built from scratch. - // This shouldn't be to bad since most of the parts will be meshes that had been built previously. - private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - // Remove reference to the old shape - // Don't need to do this as the shape is freed when the new root shape is created below. - // DereferenceShape(prim.PhysShape, true, shapeCallback); - - - BulletShape cShape = PhysicsScene.PE.CreateCompoundShape(PhysicsScene.World, false); - - // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. - CreateGeomMeshOrHull(prim, shapeCallback); - PhysicsScene.PE.AddChildShapeToCompoundShape(cShape, prim.PhysShape, OMV.Vector3.Zero, OMV.Quaternion.Identity); - if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}", - prim.LocalID, cShape, prim.PhysShape); - - prim.PhysShape = cShape; - - return true; - } - - // Create a hash of all the shape parameters to be used as a key - // for this particular shape. - private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) - { - // level of detail based on size and type of the object - float lod = BSParam.MeshLOD; - if (pbs.SculptEntry) - lod = BSParam.SculptLOD; - - // Mega prims usually get more detail because one can interact with shape approximations at this size. - float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z)); - if (maxAxis > BSParam.MeshMegaPrimThreshold) - lod = BSParam.MeshMegaPrimLOD; - - retLod = lod; - return pbs.GetMeshKey(size, lod); - } - // For those who don't want the LOD - private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs) - { - float lod; - return ComputeShapeKey(size, pbs, out lod); - } - - // The creation of a mesh or hull can fail if an underlying asset is not available. - // There are two cases: 1) the asset is not in the cache and it needs to be fetched; - // and 2) the asset cannot be converted (like failed decompression of JPEG2000s). - // The first case causes the asset to be fetched. The second case requires - // us to not loop forever. - // Called after creating a physical mesh or hull. If the physical shape was created, - // just return. - private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim) - { - // If the shape was successfully created, nothing more to do - if (newShape.HasPhysicalShape) - return newShape; - - // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset - if (prim.BaseShape.SculptEntry && !prim.LastAssetBuildFailed && prim.BaseShape.SculptTexture != OMV.UUID.Zero) - { - prim.LastAssetBuildFailed = true; - BSPhysObject xprim = prim; - DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lID={1},lastFailed={2}", - LogHeader, prim.LocalID, prim.LastAssetBuildFailed); - Util.FireAndForget(delegate - { - RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; - if (assetProvider != null) - { - BSPhysObject yprim = xprim; // probably not necessary, but, just in case. - assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset) - { - if (!yprim.BaseShape.SculptEntry) - return; - if (yprim.BaseShape.SculptTexture.ToString() != asset.ID) - return; - - yprim.BaseShape.SculptData = asset.Data; - // This will cause the prim to see that the filler shape is not the right - // one and try again to build the object. - // No race condition with the normal shape setting since the rebuild is at taint time. - yprim.ForceBodyShapeRebuild(false); - - }); - } - }); - } - else - { - if (prim.LastAssetBuildFailed) - { - PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}", - LogHeader, prim.LocalID, prim.BaseShape.SculptTexture); - } - } - - // While we figure out the real problem, stick a simple native shape on the object. - BulletShape fillinShape = - BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); - - return fillinShape; - } - - // Create a body object in Bullet. - // Updates prim.BSBody with the information about the new body if one is created. - // Returns 'true' if an object was actually created. - // Called at taint-time. - private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, BulletShape shape, - BodyDestructionCallback bodyCallback) - { - bool ret = false; - - // the mesh, hull or native shape must have already been created in Bullet - bool mustRebuild = !prim.PhysBody.HasPhysicalBody; - - // If there is an existing body, verify it's of an acceptable type. - // If not a solid object, body is a GhostObject. Otherwise a RigidBody. - if (!mustRebuild) - { - CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(prim.PhysBody); - if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY - || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) - { - // If the collisionObject is not the correct type for solidness, rebuild what's there - mustRebuild = true; - } - } - - if (mustRebuild || forceRebuild) - { - // Free any old body - DereferenceBody(prim.PhysBody, true, bodyCallback); - - BulletBody aBody; - if (prim.IsSolid) - { - aBody = PhysicsScene.PE.CreateBodyFromShape(sim, shape, prim.LocalID, prim.RawPosition, prim.RawOrientation); - if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,mesh,body={1}", prim.LocalID, aBody); - } - else - { - aBody = PhysicsScene.PE.CreateGhostFromShape(sim, shape, prim.LocalID, prim.RawPosition, prim.RawOrientation); - if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody); - } - - ReferenceBody(aBody, true); - - prim.PhysBody = aBody; - - ret = true; - } - - return ret; - } - - private bool TryGetMeshByPtr(BulletShape shape, out MeshDesc outDesc) - { - bool ret = false; - MeshDesc foundDesc = new MeshDesc(); - foreach (MeshDesc md in Meshes.Values) - { - if (md.shape.ReferenceSame(shape)) - { - foundDesc = md; - ret = true; - break; - } - - } - outDesc = foundDesc; - return ret; - } - - private bool TryGetHullByPtr(BulletShape shape, out HullDesc outDesc) - { - bool ret = false; - HullDesc foundDesc = new HullDesc(); - foreach (HullDesc hd in Hulls.Values) - { - if (hd.shape.ReferenceSame(shape)) - { - foundDesc = hd; - ret = true; - break; - } - - } - outDesc = foundDesc; - return ret; - } - - private void DetailLog(string msg, params Object[] args) - { - if (PhysicsScene.PhysicsLogging.Enabled) - PhysicsScene.DetailLog(msg, args); - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs deleted file mode 100755 index c75eb9b..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public abstract class BSShape -{ - public IntPtr ptr { get; set; } - public BSPhysicsShapeType type { get; set; } - public System.UInt64 key { get; set; } - public int referenceCount { get; set; } - public DateTime lastReferenced { get; set; } - - public BSShape() - { - ptr = IntPtr.Zero; - type = BSPhysicsShapeType.SHAPE_UNKNOWN; - key = 0; - referenceCount = 0; - lastReferenced = DateTime.Now; - } - - // Get a reference to a physical shape. Create if it doesn't exist - public static BSShape GetShapeReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) - { - BSShape ret = null; - - if (prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE) - { - // an avatar capsule is close to a native shape (it is not shared) - ret = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_CAPSULE, - FixedShapeKey.KEY_CAPSULE); - physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret); - } - - // Compound shapes are handled special as they are rebuilt from scratch. - // This isn't too great a hardship since most of the child shapes will already been created. - if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND) - { - // Getting a reference to a compound shape gets you the compound shape with the root prim shape added - ret = BSShapeCompound.GetReference(prim); - physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret); - } - - if (ret == null) - ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim); - - return ret; - } - public static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) - { - return null; - } - public static BSShape GetShapeReferenceNonNative(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) - { - return null; - } - - // Release the use of a physical shape. - public abstract void Dereference(BSScene physicsScene); - - // All shapes have a static call to get a reference to the physical shape - // protected abstract static BSShape GetReference(); - - // Returns a string for debugging that uniquily identifies the memory used by this instance - public string AddrString - { - get { return ptr.ToString("X"); } - } - - public override string ToString() - { - StringBuilder buff = new StringBuilder(); - buff.Append(""); - return buff.ToString(); - } -} - -public class BSShapeNull : BSShape -{ - public BSShapeNull() : base() - { - } - public static BSShape GetReference() { return new BSShapeNull(); } - public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ } -} - -public class BSShapeNative : BSShape -{ - private static string LogHeader = "[BULLETSIM SHAPE NATIVE]"; - public BSShapeNative() : base() - { - } - public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim, - BSPhysicsShapeType shapeType, FixedShapeKey shapeKey) - { - // Native shapes are not shared and are always built anew. - //return new BSShapeNative(physicsScene, prim, shapeType, shapeKey); - return null; - } - - private BSShapeNative(BSScene physicsScene, BSPhysObject prim, - BSPhysicsShapeType shapeType, FixedShapeKey shapeKey) - { - ShapeData nativeShapeData = new ShapeData(); - nativeShapeData.Type = shapeType; - nativeShapeData.ID = prim.LocalID; - nativeShapeData.Scale = prim.Scale; - nativeShapeData.Size = prim.Scale; - nativeShapeData.MeshKey = (ulong)shapeKey; - nativeShapeData.HullKey = (ulong)shapeKey; - - - /* - if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE) - { - ptr = PhysicsScene.PE.BuildCapsuleShape(physicsScene.World, 1f, 1f, prim.Scale); - physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); - } - else - { - ptr = PhysicsScene.PE.BuildNativeShape(physicsScene.World, nativeShapeData); - } - if (ptr == IntPtr.Zero) - { - physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", - LogHeader, prim.LocalID, shapeType); - } - type = shapeType; - key = (UInt64)shapeKey; - */ - } - // Make this reference to the physical shape go away since native shapes are not shared. - public override void Dereference(BSScene physicsScene) - { - /* - // Native shapes are not tracked and are released immediately - physicsScene.DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this); - PhysicsScene.PE.DeleteCollisionShape(physicsScene.World, this); - ptr = IntPtr.Zero; - // Garbage collection will free up this instance. - */ - } -} - -public class BSShapeMesh : BSShape -{ - private static string LogHeader = "[BULLETSIM SHAPE MESH]"; - private static Dictionary Meshes = new Dictionary(); - - public BSShapeMesh() : base() - { - } - public static BSShape GetReference() { return new BSShapeNull(); } - public override void Dereference(BSScene physicsScene) { } -} - -public class BSShapeHull : BSShape -{ - private static string LogHeader = "[BULLETSIM SHAPE HULL]"; - private static Dictionary Hulls = new Dictionary(); - - public BSShapeHull() : base() - { - } - public static BSShape GetReference() { return new BSShapeNull(); } - public override void Dereference(BSScene physicsScene) { } -} - -public class BSShapeCompound : BSShape -{ - private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]"; - public BSShapeCompound() : base() - { - } - public static BSShape GetReference(BSPhysObject prim) - { - return new BSShapeNull(); - } - public override void Dereference(BSScene physicsScene) { } -} - -public class BSShapeAvatar : BSShape -{ - private static string LogHeader = "[BULLETSIM SHAPE AVATAR]"; - public BSShapeAvatar() : base() - { - } - public static BSShape GetReference(BSPhysObject prim) - { - return new BSShapeNull(); - } - public override void Dereference(BSScene physicsScene) { } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs deleted file mode 100755 index e4fecc3..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OpenSim.Framework; -using OpenSim.Region.Framework; -using OpenSim.Region.CoreModules; -using OpenSim.Region.Physics.Manager; - -using Nini.Config; -using log4net; - -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public sealed class BSTerrainHeightmap : BSTerrainPhys -{ - static string LogHeader = "[BULLETSIM TERRAIN HEIGHTMAP]"; - - BulletHMapInfo m_mapInfo = null; - - // Constructor to build a default, flat heightmap terrain. - public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize) - : base(physicsScene, regionBase, id) - { - Vector3 minTerrainCoords = new Vector3(0f, 0f, BSTerrainManager.HEIGHT_INITIALIZATION - BSTerrainManager.HEIGHT_EQUAL_FUDGE); - Vector3 maxTerrainCoords = new Vector3(regionSize.X, regionSize.Y, BSTerrainManager.HEIGHT_INITIALIZATION); - int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y; - float[] initialMap = new float[totalHeights]; - for (int ii = 0; ii < totalHeights; ii++) - { - initialMap[ii] = BSTerrainManager.HEIGHT_INITIALIZATION; - } - m_mapInfo = new BulletHMapInfo(id, initialMap); - m_mapInfo.minCoords = minTerrainCoords; - m_mapInfo.maxCoords = maxTerrainCoords; - m_mapInfo.terrainRegionBase = TerrainBase; - // Don't have to free any previous since we just got here. - BuildHeightmapTerrain(); - } - - // This minCoords and maxCoords passed in give the size of the terrain (min and max Z - // are the high and low points of the heightmap). - public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, - Vector3 minCoords, Vector3 maxCoords) - : base(physicsScene, regionBase, id) - { - m_mapInfo = new BulletHMapInfo(id, initialMap); - m_mapInfo.minCoords = minCoords; - m_mapInfo.maxCoords = maxCoords; - m_mapInfo.minZ = minCoords.Z; - m_mapInfo.maxZ = maxCoords.Z; - m_mapInfo.terrainRegionBase = TerrainBase; - - // Don't have to free any previous since we just got here. - BuildHeightmapTerrain(); - } - - public override void Dispose() - { - ReleaseHeightMapTerrain(); - } - - // Using the information in m_mapInfo, create the physical representation of the heightmap. - private void BuildHeightmapTerrain() - { - // Create the terrain shape from the mapInfo - m_mapInfo.terrainShape = PhysicsScene.PE.CreateTerrainShape( m_mapInfo.ID, - new Vector3(m_mapInfo.sizeX, m_mapInfo.sizeY, 0), m_mapInfo.minZ, m_mapInfo.maxZ, - m_mapInfo.heightMap, 1f, BSParam.TerrainCollisionMargin); - - - // The terrain object initial position is at the center of the object - Vector3 centerPos; - centerPos.X = m_mapInfo.minCoords.X + (m_mapInfo.sizeX / 2f); - centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f); - centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f); - - m_mapInfo.terrainBody = PhysicsScene.PE.CreateBodyWithDefaultMotionState(m_mapInfo.terrainShape, - m_mapInfo.ID, centerPos, Quaternion.Identity); - - // Set current terrain attributes - PhysicsScene.PE.SetFriction(m_mapInfo.terrainBody, BSParam.TerrainFriction); - PhysicsScene.PE.SetHitFraction(m_mapInfo.terrainBody, BSParam.TerrainHitFraction); - PhysicsScene.PE.SetRestitution(m_mapInfo.terrainBody, BSParam.TerrainRestitution); - PhysicsScene.PE.SetCollisionFlags(m_mapInfo.terrainBody, CollisionFlags.CF_STATIC_OBJECT); - - // Return the new terrain to the world of physical objects - PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_mapInfo.terrainBody); - - // redo its bounding box now that it is in the world - PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_mapInfo.terrainBody); - - m_mapInfo.terrainBody.collisionType = CollisionType.Terrain; - m_mapInfo.terrainBody.ApplyCollisionMask(PhysicsScene); - - // Make it so the terrain will not move or be considered for movement. - PhysicsScene.PE.ForceActivationState(m_mapInfo.terrainBody, ActivationState.DISABLE_SIMULATION); - - return; - } - - // If there is information in m_mapInfo pointing to physical structures, release same. - private void ReleaseHeightMapTerrain() - { - if (m_mapInfo != null) - { - if (m_mapInfo.terrainBody.HasPhysicalBody) - { - PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_mapInfo.terrainBody); - // Frees both the body and the shape. - PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_mapInfo.terrainBody); - } - } - m_mapInfo = null; - } - - // The passed position is relative to the base of the region. - public override float GetTerrainHeightAtXYZ(Vector3 pos) - { - float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; - - int mapIndex = (int)pos.Y * (int)m_mapInfo.sizeY + (int)pos.X; - try - { - ret = m_mapInfo.heightMap[mapIndex]; - } - catch - { - // Sometimes they give us wonky values of X and Y. Give a warning and return something. - PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", - LogHeader, m_mapInfo.terrainRegionBase, pos); - ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; - } - return ret; - } - - // The passed position is relative to the base of the region. - public override float GetWaterLevelAtXYZ(Vector3 pos) - { - return PhysicsScene.SimpleWaterLevel; - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs deleted file mode 100755 index 2e9db39..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OpenSim.Framework; -using OpenSim.Region.Framework; -using OpenSim.Region.CoreModules; -using OpenSim.Region.Physics.Manager; - -using Nini.Config; -using log4net; - -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ - -// The physical implementation of the terrain is wrapped in this class. -public abstract class BSTerrainPhys : IDisposable -{ - public enum TerrainImplementation - { - Heightmap = 0, - Mesh = 1 - } - - public BSScene PhysicsScene { get; private set; } - // Base of the region in world coordinates. Coordinates inside the region are relative to this. - public Vector3 TerrainBase { get; private set; } - public uint ID { get; private set; } - - public BSTerrainPhys(BSScene physicsScene, Vector3 regionBase, uint id) - { - PhysicsScene = physicsScene; - TerrainBase = regionBase; - ID = id; - } - public abstract void Dispose(); - public abstract float GetTerrainHeightAtXYZ(Vector3 pos); - public abstract float GetWaterLevelAtXYZ(Vector3 pos); -} - -// ========================================================================================== -public sealed class BSTerrainManager : IDisposable -{ - static string LogHeader = "[BULLETSIM TERRAIN MANAGER]"; - - // These height values are fractional so the odd values will be - // noticable when debugging. - public const float HEIGHT_INITIALIZATION = 24.987f; - public const float HEIGHT_INITIAL_LASTHEIGHT = 24.876f; - public const float HEIGHT_GETHEIGHT_RET = 24.765f; - public const float WATER_HEIGHT_GETHEIGHT_RET = 19.998f; - - // If the min and max height are equal, we reduce the min by this - // amount to make sure that a bounding box is built for the terrain. - public const float HEIGHT_EQUAL_FUDGE = 0.2f; - - // Until the whole simulator is changed to pass us the region size, we rely on constants. - public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); - - // The scene that I am part of - private BSScene PhysicsScene { get; set; } - - // The ground plane created to keep thing from falling to infinity. - private BulletBody m_groundPlane; - - // If doing mega-regions, if we're region zero we will be managing multiple - // region terrains since region zero does the physics for the whole mega-region. - private Dictionary m_terrains; - - // Flags used to know when to recalculate the height. - private bool m_terrainModified = false; - - // If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount. - // This is incremented before assigning to new region so it is the last ID allocated. - private uint m_terrainCount = BSScene.CHILDTERRAIN_ID - 1; - public uint HighestTerrainID { get {return m_terrainCount; } } - - // If doing mega-regions, this holds our offset from region zero of - // the mega-regions. "parentScene" points to the PhysicsScene of region zero. - private Vector3 m_worldOffset; - // If the parent region (region 0), this is the extent of the combined regions - // relative to the origin of region zero - private Vector3 m_worldMax; - private PhysicsScene MegaRegionParentPhysicsScene { get; set; } - - public BSTerrainManager(BSScene physicsScene) - { - PhysicsScene = physicsScene; - m_terrains = new Dictionary(); - - // Assume one region of default size - m_worldOffset = Vector3.Zero; - m_worldMax = new Vector3(DefaultRegionSize); - MegaRegionParentPhysicsScene = null; - } - - public void Dispose() - { - ReleaseGroundPlaneAndTerrain(); - } - - // Create the initial instance of terrain and the underlying ground plane. - // This is called from the initialization routine so we presume it is - // safe to call Bullet in real time. We hope no one is moving prims around yet. - public void CreateInitialGroundPlaneAndTerrain() - { - // The ground plane is here to catch things that are trying to drop to negative infinity - BulletShape groundPlaneShape = PhysicsScene.PE.CreateGroundPlaneShape(BSScene.GROUNDPLANE_ID, 1f, BSParam.TerrainCollisionMargin); - m_groundPlane = PhysicsScene.PE.CreateBodyWithDefaultMotionState(groundPlaneShape, - BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity); - - PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_groundPlane); - PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_groundPlane); - // Ground plane does not move - PhysicsScene.PE.ForceActivationState(m_groundPlane, ActivationState.DISABLE_SIMULATION); - // Everything collides with the ground plane. - m_groundPlane.collisionType = CollisionType.Groundplane; - m_groundPlane.ApplyCollisionMask(PhysicsScene); - - // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain. - BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize); - m_terrains.Add(Vector3.Zero, initialTerrain); - } - - // Release all the terrain structures we might have allocated - public void ReleaseGroundPlaneAndTerrain() - { - if (m_groundPlane.HasPhysicalBody) - { - if (PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_groundPlane)) - { - PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_groundPlane); - } - m_groundPlane.Clear(); - } - - ReleaseTerrain(); - } - - // Release all the terrain we have allocated - public void ReleaseTerrain() - { - lock (m_terrains) - { - foreach (KeyValuePair kvp in m_terrains) - { - kvp.Value.Dispose(); - } - m_terrains.Clear(); - } - } - - // The simulator wants to set a new heightmap for the terrain. - public void SetTerrain(float[] heightMap) { - float[] localHeightMap = heightMap; - // If there are multiple requests for changes to the same terrain between ticks, - // only do that last one. - PhysicsScene.PostTaintObject("TerrainManager.SetTerrain-"+ m_worldOffset.ToString(), 0, delegate() - { - if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null) - { - // If a child of a mega-region, we shouldn't have any terrain allocated for us - ReleaseGroundPlaneAndTerrain(); - // If doing the mega-prim stuff and we are the child of the zero region, - // the terrain is added to our parent - if (MegaRegionParentPhysicsScene is BSScene) - { - DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", - BSScene.DetailLogZero, m_worldOffset, m_worldMax); - ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateTerrain( - BSScene.CHILDTERRAIN_ID, localHeightMap, - m_worldOffset, m_worldOffset + DefaultRegionSize, true); - } - } - else - { - // If not doing the mega-prim thing, just change the terrain - DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero); - - UpdateTerrain(BSScene.TERRAIN_ID, localHeightMap, - m_worldOffset, m_worldOffset + DefaultRegionSize, true); - } - }); - } - - // If called with no mapInfo for the terrain, this will create a new mapInfo and terrain - // based on the passed information. The 'id' should be either the terrain id or - // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used. - // The latter feature is for creating child terrains for mega-regions. - // If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new - // terrain shape is created and added to the body. - // This call is most often used to update the heightMap and parameters of the terrain. - // (The above does suggest that some simplification/refactoring is in order.) - // Called during taint-time. - private void UpdateTerrain(uint id, float[] heightMap, - Vector3 minCoords, Vector3 maxCoords, bool inTaintTime) - { - DetailLog("{0},BSTerrainManager.UpdateTerrain,call,minC={1},maxC={2},inTaintTime={3}", - BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime); - - // Find high and low points of passed heightmap. - // The min and max passed in is usually the area objects can be in (maximum - // object height, for instance). The terrain wants the bounding box for the - // terrain so replace passed min and max Z with the actual terrain min/max Z. - float minZ = float.MaxValue; - float maxZ = float.MinValue; - foreach (float height in heightMap) - { - if (height < minZ) minZ = height; - if (height > maxZ) maxZ = height; - } - if (minZ == maxZ) - { - // If min and max are the same, reduce min a little bit so a good bounding box is created. - minZ -= BSTerrainManager.HEIGHT_EQUAL_FUDGE; - } - minCoords.Z = minZ; - maxCoords.Z = maxZ; - - Vector3 terrainRegionBase = new Vector3(minCoords.X, minCoords.Y, 0f); - - lock (m_terrains) - { - BSTerrainPhys terrainPhys; - if (m_terrains.TryGetValue(terrainRegionBase, out terrainPhys)) - { - // There is already a terrain in this spot. Free the old and build the new. - DetailLog("{0},UpdateTerrain:UpdateExisting,call,id={1},base={2},minC={3},maxC={4}", - BSScene.DetailLogZero, id, terrainRegionBase, minCoords, minCoords); - - // Remove old terrain from the collection - m_terrains.Remove(terrainRegionBase); - // Release any physical memory it may be using. - terrainPhys.Dispose(); - - if (MegaRegionParentPhysicsScene == null) - { - BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords); - m_terrains.Add(terrainRegionBase, newTerrainPhys); - - m_terrainModified = true; - } - else - { - // It's possible that Combine() was called after this code was queued. - // If we are a child of combined regions, we don't create any terrain for us. - DetailLog("{0},BSTerrainManager.UpdateTerrain:AmACombineChild,taint", BSScene.DetailLogZero); - - // Get rid of any terrain that may have been allocated for us. - ReleaseGroundPlaneAndTerrain(); - - // I hate doing this, but just bail - return; - } - } - else - { - // We don't know about this terrain so either we are creating a new terrain or - // our mega-prim child is giving us a new terrain to add to the phys world - - // if this is a child terrain, calculate a unique terrain id - uint newTerrainID = id; - if (newTerrainID >= BSScene.CHILDTERRAIN_ID) - newTerrainID = ++m_terrainCount; - - DetailLog("{0},UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}", - BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); - BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords); - m_terrains.Add(terrainRegionBase, newTerrainPhys); - - m_terrainModified = true; - } - } - } - - // TODO: redo terrain implementation selection to allow other base types than heightMap. - private BSTerrainPhys BuildPhysicalTerrain(Vector3 terrainRegionBase, uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords) - { - PhysicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}", - LogHeader, PhysicsScene.RegionName, terrainRegionBase, - (BSTerrainPhys.TerrainImplementation)BSParam.TerrainImplementation); - BSTerrainPhys newTerrainPhys = null; - switch ((int)BSParam.TerrainImplementation) - { - case (int)BSTerrainPhys.TerrainImplementation.Heightmap: - newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, - heightMap, minCoords, maxCoords); - break; - case (int)BSTerrainPhys.TerrainImplementation.Mesh: - newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id, - heightMap, minCoords, maxCoords); - break; - default: - PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}", - LogHeader, - (int)BSParam.TerrainImplementation, - BSParam.TerrainImplementation, - PhysicsScene.RegionName, terrainRegionBase); - break; - } - return newTerrainPhys; - } - - // Return 'true' of this position is somewhere in known physical terrain space - public bool IsWithinKnownTerrain(Vector3 pos) - { - Vector3 terrainBaseXYZ; - BSTerrainPhys physTerrain; - return GetTerrainPhysicalAtXYZ(pos, out physTerrain, out terrainBaseXYZ); - } - - // Given an X and Y, find the height of the terrain. - // Since we could be handling multiple terrains for a mega-region, - // the base of the region is calcuated assuming all regions are - // the same size and that is the default. - // Once the heightMapInfo is found, we have all the information to - // compute the offset into the array. - private float lastHeightTX = 999999f; - private float lastHeightTY = 999999f; - private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT; - public float GetTerrainHeightAtXYZ(Vector3 pos) - { - float tX = pos.X; - float tY = pos.Y; - // You'd be surprized at the number of times this routine is called - // with the same parameters as last time. - if (!m_terrainModified && (lastHeightTX == tX) && (lastHeightTY == tY)) - return lastHeight; - m_terrainModified = false; - - lastHeightTX = tX; - lastHeightTY = tY; - float ret = HEIGHT_GETHEIGHT_RET; - - Vector3 terrainBaseXYZ; - BSTerrainPhys physTerrain; - if (GetTerrainPhysicalAtXYZ(pos, out physTerrain, out terrainBaseXYZ)) - { - ret = physTerrain.GetTerrainHeightAtXYZ(pos - terrainBaseXYZ); - } - else - { - PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", - LogHeader, PhysicsScene.RegionName, tX, tY); - DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,terrainNotFound,pos={1},base={2}", - BSScene.DetailLogZero, pos, terrainBaseXYZ); - } - - lastHeight = ret; - return ret; - } - - public float GetWaterLevelAtXYZ(Vector3 pos) - { - float ret = WATER_HEIGHT_GETHEIGHT_RET; - - Vector3 terrainBaseXYZ; - BSTerrainPhys physTerrain; - if (GetTerrainPhysicalAtXYZ(pos, out physTerrain, out terrainBaseXYZ)) - { - ret = physTerrain.GetWaterLevelAtXYZ(pos); - } - else - { - PhysicsScene.Logger.ErrorFormat("{0} GetWaterHeightAtXY: terrain not found: pos={1}, terrainBase={2}, height={3}", - LogHeader, PhysicsScene.RegionName, pos, terrainBaseXYZ, ret); - } - return ret; - } - - // Given an address, return 'true' of there is a description of that terrain and output - // the descriptor class and the 'base' fo the addresses therein. - private bool GetTerrainPhysicalAtXYZ(Vector3 pos, out BSTerrainPhys outPhysTerrain, out Vector3 outTerrainBase) - { - int offsetX = ((int)(pos.X / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X; - int offsetY = ((int)(pos.Y / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y; - Vector3 terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f); - - BSTerrainPhys physTerrain = null; - lock (m_terrains) - { - m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain); - } - outTerrainBase = terrainBaseXYZ; - outPhysTerrain = physTerrain; - return (physTerrain != null); - } - - // Although no one seems to check this, I do support combining. - public bool SupportsCombining() - { - return true; - } - - // This routine is called two ways: - // One with 'offset' and 'pScene' zero and null but 'extents' giving the maximum - // extent of the combined regions. This is to inform the parent of the size - // of the combined regions. - // and one with 'offset' as the offset of the child region to the base region, - // 'pScene' pointing to the parent and 'extents' of zero. This informs the - // child of its relative base and new parent. - public void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) - { - m_worldOffset = offset; - m_worldMax = extents; - MegaRegionParentPhysicsScene = pScene; - if (pScene != null) - { - // We are a child. - // We want m_worldMax to be the highest coordinate of our piece of terrain. - m_worldMax = offset + DefaultRegionSize; - } - DetailLog("{0},BSTerrainManager.Combine,offset={1},extents={2},wOffset={3},wMax={4}", - BSScene.DetailLogZero, offset, extents, m_worldOffset, m_worldMax); - } - - // Unhook all the combining that I know about. - public void UnCombine(PhysicsScene pScene) - { - // Just like ODE, we don't do anything yet. - DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero); - } - - - private void DetailLog(string msg, params Object[] args) - { - PhysicsScene.PhysicsLogging.Write(msg, args); - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs deleted file mode 100755 index 1d55ce3..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OpenSim.Framework; -using OpenSim.Region.Framework; -using OpenSim.Region.CoreModules; -using OpenSim.Region.Physics.Manager; - -using Nini.Config; -using log4net; - -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public sealed class BSTerrainMesh : BSTerrainPhys -{ - static string LogHeader = "[BULLETSIM TERRAIN MESH]"; - - private float[] m_savedHeightMap; - int m_sizeX; - int m_sizeY; - - BulletShape m_terrainShape; - BulletBody m_terrainBody; - - public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize) - : base(physicsScene, regionBase, id) - { - } - - public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id /* parameters for making mesh */) - : base(physicsScene, regionBase, id) - { - } - - // Create terrain mesh from a heightmap. - public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, - Vector3 minCoords, Vector3 maxCoords) - : base(physicsScene, regionBase, id) - { - int indicesCount; - int[] indices; - int verticesCount; - float[] vertices; - - m_savedHeightMap = initialMap; - - m_sizeX = (int)(maxCoords.X - minCoords.X); - m_sizeY = (int)(maxCoords.Y - minCoords.Y); - - if (!BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene, initialMap, - m_sizeX, m_sizeY, - (float)m_sizeX, (float)m_sizeY, - Vector3.Zero, 1.0f, - out indicesCount, out indices, out verticesCount, out vertices)) - { - // DISASTER!! - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap", ID); - PhysicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase); - // Something is very messed up and a crash is in our future. - return; - } - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,indices={1},indSz={2},vertices={3},vertSz={4}", - ID, indicesCount, indices.Length, verticesCount, vertices.Length); - - m_terrainShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World, indicesCount, indices, verticesCount, vertices); - if (!m_terrainShape.HasPhysicalShape) - { - // DISASTER!! - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID); - physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase); - // Something is very messed up and a crash is in our future. - return; - } - - Vector3 pos = regionBase; - Quaternion rot = Quaternion.Identity; - - m_terrainBody = PhysicsScene.PE.CreateBodyWithDefaultMotionState(m_terrainShape, ID, pos, rot); - if (!m_terrainBody.HasPhysicalBody) - { - // DISASTER!! - physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase); - // Something is very messed up and a crash is in our future. - return; - } - - // Set current terrain attributes - PhysicsScene.PE.SetFriction(m_terrainBody, BSParam.TerrainFriction); - PhysicsScene.PE.SetHitFraction(m_terrainBody, BSParam.TerrainHitFraction); - PhysicsScene.PE.SetRestitution(m_terrainBody, BSParam.TerrainRestitution); - PhysicsScene.PE.SetCollisionFlags(m_terrainBody, CollisionFlags.CF_STATIC_OBJECT); - - // Static objects are not very massive. - PhysicsScene.PE.SetMassProps(m_terrainBody, 0f, Vector3.Zero); - - // Put the new terrain to the world of physical objects - PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_terrainBody); - - // Redo its bounding box now that it is in the world - PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_terrainBody); - - m_terrainBody.collisionType = CollisionType.Terrain; - m_terrainBody.ApplyCollisionMask(PhysicsScene); - - // Make it so the terrain will not move or be considered for movement. - PhysicsScene.PE.ForceActivationState(m_terrainBody, ActivationState.DISABLE_SIMULATION); - } - - public override void Dispose() - { - if (m_terrainBody.HasPhysicalBody) - { - PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_terrainBody); - // Frees both the body and the shape. - PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_terrainBody); - } - } - - public override float GetTerrainHeightAtXYZ(Vector3 pos) - { - // For the moment use the saved heightmap to get the terrain height. - // TODO: raycast downward to find the true terrain below the position. - float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; - - int mapIndex = (int)pos.Y * m_sizeY + (int)pos.X; - try - { - ret = m_savedHeightMap[mapIndex]; - } - catch - { - // Sometimes they give us wonky values of X and Y. Give a warning and return something. - PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", - LogHeader, TerrainBase, pos); - ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; - } - return ret; - } - - // The passed position is relative to the base of the region. - public override float GetWaterLevelAtXYZ(Vector3 pos) - { - return PhysicsScene.SimpleWaterLevel; - } - - // Convert the passed heightmap to mesh information suitable for CreateMeshShape2(). - // Return 'true' if successfully created. - public static bool ConvertHeightmapToMesh( - BSScene physicsScene, - float[] heightMap, int sizeX, int sizeY, // parameters of incoming heightmap - float extentX, float extentY, // zero based range for output vertices - Vector3 extentBase, // base to be added to all vertices - float magnification, // number of vertices to create between heightMap coords - out int indicesCountO, out int[] indicesO, - out int verticesCountO, out float[] verticesO) - { - bool ret = false; - - int indicesCount = 0; - int verticesCount = 0; - int[] indices = new int[0]; - float[] vertices = new float[0]; - - // Simple mesh creation which assumes magnification == 1. - // TODO: do a more general solution that scales, adds new vertices and smoothes the result. - - // Create an array of vertices that is sizeX+1 by sizeY+1 (note the loop - // from zero to <= sizeX). The triangle indices are then generated as two triangles - // per heightmap point. There are sizeX by sizeY of these squares. The extra row and - // column of vertices are used to complete the triangles of the last row and column - // of the heightmap. - try - { - // One vertice per heightmap value plus the vertices off the top and bottom edge. - int totalVertices = (sizeX + 1) * (sizeY + 1); - vertices = new float[totalVertices * 3]; - int totalIndices = sizeX * sizeY * 6; - indices = new int[totalIndices]; - - float magX = (float)sizeX / extentX; - float magY = (float)sizeY / extentY; - physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2},extentBase={3},magX={4},magY={5}", - BSScene.DetailLogZero, totalVertices, totalIndices, extentBase, magX, magY); - float minHeight = float.MaxValue; - // Note that sizeX+1 vertices are created since there is land between this and the next region. - for (int yy = 0; yy <= sizeY; yy++) - { - for (int xx = 0; xx <= sizeX; xx++) // Hint: the "<=" means we go around sizeX + 1 times - { - int offset = yy * sizeX + xx; - // Extend the height with the height from the last row or column - if (yy == sizeY) offset -= sizeX; - if (xx == sizeX) offset -= 1; - float height = heightMap[offset]; - minHeight = Math.Min(minHeight, height); - vertices[verticesCount + 0] = (float)xx * magX + extentBase.X; - vertices[verticesCount + 1] = (float)yy * magY + extentBase.Y; - vertices[verticesCount + 2] = height + extentBase.Z; - verticesCount += 3; - } - } - verticesCount = verticesCount / 3; - - for (int yy = 0; yy < sizeY; yy++) - { - for (int xx = 0; xx < sizeX; xx++) - { - int offset = yy * (sizeX + 1) + xx; - // Each vertices is presumed to be the upper left corner of a box of two triangles - indices[indicesCount + 0] = offset; - indices[indicesCount + 1] = offset + 1; - indices[indicesCount + 2] = offset + sizeX + 1; // accounting for the extra column - indices[indicesCount + 3] = offset + 1; - indices[indicesCount + 4] = offset + sizeX + 2; - indices[indicesCount + 5] = offset + sizeX + 1; - indicesCount += 6; - } - } - - ret = true; - } - catch (Exception e) - { - physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. For={1}/{2}, e={3}", - LogHeader, physicsScene.RegionName, extentBase, e); - } - - indicesCountO = indicesCount; - indicesO = indices; - verticesCountO = verticesCount; - verticesO = vertices; - - return ret; - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs deleted file mode 100755 index 662dd68..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using OMV = OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -// Classes to allow some type checking for the API -// These hold pointers to allocated objects in the unmanaged space. -// These classes are subclassed by the various physical implementations of -// objects. In particular, there is a version for physical instances in -// unmanaged memory ("unman") and one for in managed memory ("XNA"). - -// Currently, the instances of these classes are a reference to a -// physical representation and this has no releationship to other -// instances. Someday, refarb the usage of these classes so each instance -// refers to a particular physical instance and this class controls reference -// counts and such. This should be done along with adding BSShapes. - -public class BulletWorld -{ - public BulletWorld(uint worldId, BSScene bss) - { - worldID = worldId; - physicsScene = bss; - } - public uint worldID; - // The scene is only in here so very low level routines have a handle to print debug/error messages - public BSScene physicsScene; -} - -// An allocated Bullet btRigidBody -public class BulletBody -{ - public BulletBody(uint id) - { - ID = id; - collisionType = CollisionType.Static; - } - public uint ID; - public CollisionType collisionType; - - public virtual void Clear() { } - public virtual bool HasPhysicalBody { get { return false; } } - - // Apply the specificed collision mask into the physical world - public virtual bool ApplyCollisionMask(BSScene physicsScene) - { - // Should assert the body has been added to the physical world. - // (The collision masks are stored in the collision proxy cache which only exists for - // a collision body that is in the world.) - return physicsScene.PE.SetCollisionGroupMask(this, - BulletSimData.CollisionTypeMasks[collisionType].group, - BulletSimData.CollisionTypeMasks[collisionType].mask); - } - - // Used for log messages for a unique display of the memory/object allocated to this instance - public virtual string AddrString - { - get { return "unknown"; } - } - - public override string ToString() - { - StringBuilder buff = new StringBuilder(); - buff.Append(""); - return buff.ToString(); - } -} - -public class BulletShape -{ - public BulletShape() - { - type = BSPhysicsShapeType.SHAPE_UNKNOWN; - shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE; - isNativeShape = false; - } - public BSPhysicsShapeType type; - public System.UInt64 shapeKey; - public bool isNativeShape; - - public virtual void Clear() { } - public virtual bool HasPhysicalShape { get { return false; } } - // Make another reference to this physical object. - public virtual BulletShape Clone() { return new BulletShape(); } - // Return 'true' if this and other refer to the same physical object - public virtual bool ReferenceSame(BulletShape xx) { return false; } - - // Used for log messages for a unique display of the memory/object allocated to this instance - public virtual string AddrString - { - get { return "unknown"; } - } - - public override string ToString() - { - StringBuilder buff = new StringBuilder(); - buff.Append(""); - return buff.ToString(); - } -} - -// An allocated Bullet btConstraint -public class BulletConstraint -{ - public BulletConstraint() - { - } - public virtual void Clear() { } - public virtual bool HasPhysicalConstraint { get { return false; } } - - // Used for log messages for a unique display of the memory/object allocated to this instance - public virtual string AddrString - { - get { return "unknown"; } - } -} - -// An allocated HeightMapThing which holds various heightmap info. -// Made a class rather than a struct so there would be only one -// instance of this and C# will pass around pointers rather -// than making copies. -public class BulletHMapInfo -{ - public BulletHMapInfo(uint id, float[] hm) { - ID = id; - heightMap = hm; - terrainRegionBase = OMV.Vector3.Zero; - minCoords = new OMV.Vector3(100f, 100f, 25f); - maxCoords = new OMV.Vector3(101f, 101f, 26f); - minZ = maxZ = 0f; - sizeX = sizeY = 256f; - } - public uint ID; - public float[] heightMap; - public OMV.Vector3 terrainRegionBase; - public OMV.Vector3 minCoords; - public OMV.Vector3 maxCoords; - public float sizeX, sizeY; - public float minZ, maxZ; - public BulletShape terrainShape; - public BulletBody terrainBody; -} - -// The general class of collsion object. -public enum CollisionType -{ - Avatar, - Groundplane, - Terrain, - Static, - Dynamic, - VolumeDetect, - // Linkset, // A linkset should be either Static or Dynamic - LinksetChild, - Unknown -}; - -// Hold specification of group and mask collision flags for a CollisionType -public struct CollisionTypeFilterGroup -{ - public CollisionTypeFilterGroup(CollisionType t, uint g, uint m) - { - type = t; - group = g; - mask = m; - } - public CollisionType type; - public uint group; - public uint mask; -}; - -public static class BulletSimData -{ - -// Map of collisionTypes to flags for collision groups and masks. -// As mentioned above, don't use the CollisionFilterGroups definitions directly in the code -// but, instead, use references to this dictionary. Finding and debugging -// collision flag problems will be made easier. -public static Dictionary CollisionTypeMasks - = new Dictionary() -{ - { CollisionType.Avatar, - new CollisionTypeFilterGroup(CollisionType.Avatar, - (uint)CollisionFilterGroups.BCharacterGroup, - (uint)CollisionFilterGroups.BAllGroup) - }, - { CollisionType.Groundplane, - new CollisionTypeFilterGroup(CollisionType.Groundplane, - (uint)CollisionFilterGroups.BGroundPlaneGroup, - (uint)CollisionFilterGroups.BAllGroup) - }, - { CollisionType.Terrain, - new CollisionTypeFilterGroup(CollisionType.Terrain, - (uint)CollisionFilterGroups.BTerrainGroup, - (uint)(CollisionFilterGroups.BAllGroup & ~CollisionFilterGroups.BStaticGroup)) - }, - { CollisionType.Static, - new CollisionTypeFilterGroup(CollisionType.Static, - (uint)CollisionFilterGroups.BStaticGroup, - (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup)) - }, - { CollisionType.Dynamic, - new CollisionTypeFilterGroup(CollisionType.Dynamic, - (uint)CollisionFilterGroups.BSolidGroup, - (uint)(CollisionFilterGroups.BAllGroup)) - }, - { CollisionType.VolumeDetect, - new CollisionTypeFilterGroup(CollisionType.VolumeDetect, - (uint)CollisionFilterGroups.BSensorTrigger, - (uint)(~CollisionFilterGroups.BSensorTrigger)) - }, - { CollisionType.LinksetChild, - new CollisionTypeFilterGroup(CollisionType.LinksetChild, - (uint)CollisionFilterGroups.BLinksetChildGroup, - (uint)(CollisionFilterGroups.BNoneGroup)) - // (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup)) - }, -}; - -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt deleted file mode 100755 index a8a4ff5..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt +++ /dev/null @@ -1,272 +0,0 @@ -CURRENT PRIORITIES -================================================= -Redo BulletSimAPI to allow native C# implementation of Bullet option. -Avatar movement - flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle - walking up stairs is not calibrated correctly (stairs out of Kepler cabin) - avatar capsule rotation completed -llMoveToTarget -Enable vehicle border crossings (at least as poorly as ODE) - Terrain skirts - Avatar created in previous region and not new region when crossing border - Vehicle recreated in new sim at small Z value (offset from root value?) (DONE) -Vehicle movement on terrain smoothness -Vehicle script tuning/debugging - Avanti speed script - Weapon shooter script -limitMotorUp calibration (more down?) -Boats float low in the water -Add material densities to the material types. - -CRASHES -================================================= -20121129.1411: editting/moving phys object across region boundries causes crash - getPos-> btRigidBody::upcast -> getBodyType -> BOOM -20121128.1600: mesh object not rezzing (no physics mesh). - Causes many errors. Doesn't stop after first error with box shape. - Eventually crashes when deleting the object. -20121206.1434: rez Sam-pan into OSGrid BulletSim11 region - Immediate simulator crash. Mono does not output any stacktrace and - log just stops after reporting taint-time linking of the linkset. - -VEHICLES TODO LIST: -================================================= -Angular motor direction is global coordinates rather than local coordinates -Border crossing with linked vehicle causes crash -Vehicles (Move smoothly) -Add vehicle collisions so IsColliding is properly reported. - Needed for banking, limitMotorUp, movementLimiting, ... -VehicleAddForce is not scaled by the simulation step but it is only - applied for one step. Should it be scaled? -Some vehicles should not be able to turn if no speed or off ground. -Cannot edit/move a vehicle being ridden: it jumps back to the origional position. -Neb car jiggling left and right - Happens on terrain and any other mesh object. Flat cubes are much smoother. - This has been reduced but not eliminated. -Implement referenceFrame for all the motion routines. -Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE. - Verify that angular motion specified around Z moves in the vehicle coordinates. -Verify llGetVel() is returning a smooth and good value for vehicle movement. -llGetVel() should return the root's velocity if requested in a child prim. -Implement function efficiency for lineaar and angular motion. -After getting off a vehicle, the root prim is phantom (can be walked through) - Need to force a position update for the root prim after compound shape destruction -Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint) -For limitMotorUp, use raycast down to find if vehicle is in the air. -Remove vehicle angular velocity zeroing in BSPrim.UpdateProperties(). - A kludge that isn't fixing the real problem of Bullet adding extra motion. -Incorporate inter-relationship of angular corrections. For instance, angularDeflection - and angularMotorUp will compute same X or Y correction. When added together - creates over-correction and over-shoot and wabbling. - -BULLETSIM TODO LIST: -================================================= -Implement an avatar mesh shape. The Bullet capsule is way too limited. - Consider just hand creating a vertex/index array in a new BSShapeAvatar. -Revisit CollisionMargin. Builders notice the 0.04 spacing between prims. -Duplicating a physical prim causes old prim to jump away - Dup a phys prim and the original become unselected and thus interacts w/ selected prim. -Scenes with hundred of thousands of static objects take a lot of physics CPU time. -BSPrim.Force should set a continious force on the prim. The force should be - applied each tick. Some limits? -Gun sending shooter flying. -Collision margin (gap between physical objects lying on each other) -Boundry checking (crashes related to crossing boundry) - Add check for border edge position for avatars and objects. - Verify the events are created for border crossings. -Avatar rotation (check out changes to ScenePresence for physical rotation) -Avatar running (what does phys engine need to do?) -Small physical objects do not interact correctly - Create chain of .5x.5x.1 torui and make all but top physical so to hang. - The chain will fall apart and pairs will dance around on ground - Chains of 1x1x.2 will stay connected but will dance. - Chains above 2x2x.4 are more stable and get stablier as torui get larger. -Add PID motor for avatar movement (slow to stop, ...) -setForce should set a constant force. Different than AddImpulse. -Implement raycast. -Implement ShapeCollection.Dispose() -Implement water as a plain so raycasting and collisions can happen with same. -Add osGetPhysicsEngineName() so scripters can tell whether BulletSim or ODE - Also osGetPhysicsEngineVerion() maybe. -Linkset.Position and Linkset.Orientation requre rewrite to properly return - child position. LinksetConstraint acts like it's at taint time!! -Implement LockAngularMotion -- implements llSetStatus(ROTATE_AXIS_*, T/F) -Should the different PID factors have non-equal contributions for different - values of Efficiency? -Selecting and deselecting physical objects causes CPU processing time to jump - http://www.youtube.com/watch?v=Hjg57fWg8yI&hd=1 - put thousand physical objects, select and deselect same. CPU time will be large. -Re-implement buoyancy as a separate force on the object rather than diddling gravity. - Register a pre-step event to add the force. -More efficient memory usage when passing hull information from BSPrim to BulletSim -Avatar movement motor check for zero or small movement. Somehow suppress small movements - when avatar has stopped and is just standing. Simple test for near zero has - the problem of preventing starting up (increase from zero) especially when falling. -Physical and phantom will drop through the terrain - - -LINKSETS -====================================================== -Offset the center of the linkset to be the geometric center of all the prims - Not quite the same as the center-of-gravity -Linksets should allow collisions to individual children - Add LocalID to children shapes in LinksetCompound and create events for individuals -LinksetCompound: when one of the children changes orientation (like tires - turning on a vehicle, the whole compound object is rebuilt. Optimize this - so orientation/position of individual children can change without a rebuild. -Verify/think through scripts in children of linksets. What do they reference - and return when getting position, velocity, ... -Confirm constraint linksets still work after making all the changes for compound linksets. -Add 'changed' flag or similar to reduce the number of times a linkset is rebuilt. - For compound linksets, add ability to remove or reposition individual child shapes. -Disable activity of passive linkset children. - Since the linkset is a compound object, the old prims are left lying - around and need to be phantomized so they don't collide, ... -Speed up creation of large physical linksets - For instance, sitting in Neb's car (130 prims) takes several seconds to become physical. - REALLY bad for very large physical linksets (freezes the sim for many seconds). -Eliminate collisions between objects in a linkset. (LinksetConstraint) - Have UserPointer point to struct with localID and linksetID? - Objects in original linkset still collide with each other? - -MORE -====================================================== -Test avatar walking up stairs. How does compare with SL. - Radius of the capsule affects ability to climb edges. -Debounce avatar contact so legs don't keep folding up when standing. -Implement LSL physics controls. Like STATUS_ROTATE_X. -Add border extensions to terrain to help region crossings and objects leaving region. -Use a different capsule shape for avatar when sitting - LL uses a pyrimidal shape scaled by the avatar's bounding box - http://wiki.secondlife.com/wiki/File:Avmeshforms.png - -Performance test with lots of avatars. Can BulletSim support a thousand? -Optimize collisions in C++: only send up to the object subscribed to collisions. - Use collision subscription and remove the collsion(A,B) and collision(B,A) -Check whether SimMotionState needs large if statement (see TODO). - -Implement 'top colliders' info. -Avatar jump -Performance measurement and changes to make quicker. -Implement detailed physics stats (GetStats()). - -Measure performance improvement from hulls -Test not using ghost objects for volume detect implementation. -Performance of closures and delegates for taint processing - Are there faster ways? - Is any slowdown introduced by the existing implementation significant? -Is there are more efficient method of implementing pre and post step actions? - See http://www.codeproject.com/Articles/29922/Weak-Events-in-C - -Physics Arena central pyramid: why is one side permiable? - -In SL, perfect spheres don't seem to have rolling friction. Add special case. -Enforce physical parameter min/max: - Gravity: [-1, 28] - Friction: [0, 255] - Density: [1, 22587] - Restitution [0, 1] - http://wiki.secondlife.com/wiki/Physics_Material_Settings_test -Avatar attachments have no mass? http://forums-archive.secondlife.com/54/f0/31796/1.html - -INTERNAL IMPROVEMENT/CLEANUP -================================================= -Create the physical wrapper classes (BulletBody, BulletShape) by methods on - BSAPITemplate and make their actual implementation Bullet engine specific. - For the short term, just call the existing functions in ShapeCollection. -Consider moving prim/character body and shape destruction in destroy() - to postTimeTime rather than protecting all the potential sets that - might have been queued up. -Remove unused fields from ShapeData (not used in API2) -Remove unused fields from pinned memory shared parameter block - Create parameter variables in BSScene to replace same. -Breakout code for mesh/hull/compound/native into separate BSShape* classes - Standardize access to building and reference code. - The skeleton classes are in the sources but are not complete or linked in. -Make BSBody and BSShape real classes to centralize creation/changin/destruction - Convert state and parameter calls from BulletSimAPI direct calls to - calls on BSBody and BSShape -Generalize Dynamics and PID with standardized motors. -Generalize Linkset and vehicles into PropertyManagers - Methods for Refresh, RemoveBodyDependencies, RestoreBodyDependencies - Potentially add events for shape destruction, etc. -Complete implemention of preStepActions - Replace vehicle step call with prestep event. - Is there a need for postStepActions? postStepTaints? -Implement linkset by setting position of children when root updated. (LinksetManual) - Linkset implementation using manual prim movement. -LinkablePrim class? Would that simplify/centralize the linkset logic? -BSScene.UpdateParameterSet() is broken. How to set params on objects? -Remove HeightmapInfo from terrain specification - Since C++ code does not need terrain height, this structure et al are not needed. -Add floating motor for BS_FLOATS_ON_WATER so prim and avatar will - bob at the water level. BSPrim.PositionSanityCheck(). -Should taints check for existance or activeness of target? - When destroying linksets/etc, taints can be generated for objects that are - actually gone when the taint happens. Crashes don't happen because the taint closure - keeps the object from being freed, but that is just an accident. - Possibly have and 'active' flag that is checked by the taint processor? -Parameters for physics logging should be moved from BSScene to BSParam (at least boolean ones) -Can some of the physical wrapper classes (BulletBody, BulletWorld, BulletShape) be 'sealed'? -There are TOO MANY interfaces from BulletSim core to Bullet itself - Think of something to eliminate one or more of the layers - -THREADING -================================================= -Do taint action immediately if not actually executing Bullet. - Add lock around Bullet execution and just do taint actions if simulation is not happening. - -DONE DONE DONE DONE -================================================= -Cleanup code in BSDynamics by using motors. (Resolution: started) -Consider implementing terrain with a mesh rather than heightmap. (Resolution: done) - Would have better and adjustable resolution. -Build terrain mesh so heighmap is height of the center of the square meter. - Resolution: NOT DONE: SL and ODE define meter square as being at one corner with one diagional. -Terrain as mesh. (Resolution: done) -How are static linksets seen by the physics engine? - Resolution: they are not linked in physics. When moved, all the children are repositioned. -Convert BSCharacter to use all API2 (Resolution: done) -Avatar pushing difficult (too heavy?) -Use asset service passed to BulletSim to get sculptie bodies, etc. (Resolution: done) -Remove old code in DLL (all non-API2 stuff). (Resolution: done) -Measurements of mega-physical prim performance (with graph) (Resolution: done, email) -Debug Bullet internal stats output (why is timing all wrong?) - Resolution: Bullet stats logging only works with a single instance of Bullet (one region). -Implement meshes or just verify that they work. (Resolution: they do!) -Do prim hash codes work for sculpties and meshes? (Resolution: yes) -Linkset implementation using compound shapes. (Resolution: implemented LinksetCompound) - Compound shapes will need the LocalID in the shapes and collision - processing to get it from there. -Light cycle not banking (Resolution: It doesn't. Banking is roll adding yaw.) -Package Bullet source mods for Bullet internal stats output - (Resolution: move code into WorldData.h rather than relying on patches) -Single prim vehicles don't seem to properly vehiclize. - (Resolution: mass was not getting set properly for single prim linksets) -Add material type linkage and input all the material property definitions. - Skeleton classes and table are in the sources but are not filled or used. - (Resolution: -Neb vehicle taking > 25ms of physics time!! - (Resolution: compound linksets were being rebuild WAY too often) -Avatar height off after unsitting (floats off ground) - Editting appearance then moving restores. - Must not be initializing height when recreating capsule after unsit. - (Resolution: confusion of scale vs size for native objects removed) -Light cycle falling over when driving (Resolution: implemented angularMotorUp) -Should vehicle angular/linear movement friction happen after all the components - or does it only apply to the basic movement? - (Resolution: friction added before returning newly computed motor value. - What is expected by some vehicles (turning up friction to moderate speed)) -Tune terrain/object friction to be closer to SL. - (Resolution: added material type with friction and resolution) -Smooth avatar movement with motor (DONE) - Should motor update be all at taint-time? (Yes, DONE) - Fix avatar slowly sliding when standing (zero motion when stopped) (DONE) - (Resolution: added BSVMotor for avatar starting and stopping) -llApplyImpulse() - Compare mass/movement in OS and SL. Calibrate actions. (DONE) - (Resolution: tested on SL and OS. AddForce scales the force for timestep) -llSetBuoyancy() (DONE) - (Resolution: Bullet resets object gravity when added to world. Moved set gravity) -Avatar density is WAY off. Compare and calibrate with what's in SL. (DONE) - (Resolution: set default density to 3.5 (from 60) which is closer to SL) diff --git a/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs deleted file mode 100644 index 0d1db3b..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("OpenSim.Region.Physics.BulletSPlugin")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("http://opensimulator.org")] -[assembly: AssemblyProduct("OpenSim")] -[assembly: AssemblyCopyright("OpenSimulator developers")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("520ea11b-20cb-449d-ba05-c01015fed841")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -[assembly: AssemblyVersion("0.7.5.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/CTri.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/CTri.cs deleted file mode 100644 index 4d84c44..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/CTri.cs +++ /dev/null @@ -1,341 +0,0 @@ -/* The MIT License - * - * Copyright (c) 2010 Intel Corporation. - * All rights reserved. - * - * Based on the convexdecomposition library from - * 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 vertices = new List { mP1, mP2, mP3, mNear1, mNear2, mNear3 }; - List indexList = new List(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 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; - } - } -} diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/Concavity.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/Concavity.cs deleted file mode 100644 index cc6383a..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/Concavity.cs +++ /dev/null @@ -1,233 +0,0 @@ -/* The MIT License - * - * Copyright (c) 2010 Intel Corporation. - * All rights reserved. - * - * Based on the convexdecomposition library from - * 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 vertices, List 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 tris = new List(); - - 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 ftris = new List(); // 'feature' triangles. - List input_mesh = new List(); - - 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 tris, List 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 vertices, List 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 vertices, List 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; - } - } -} diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/ConvexBuilder.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/ConvexBuilder.cs deleted file mode 100644 index dfaede1..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/ConvexBuilder.cs +++ /dev/null @@ -1,411 +0,0 @@ -/* The MIT License - * - * Copyright (c) 2010 Intel Corporation. - * All rights reserved. - * - * Based on the convexdecomposition library from - * 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 mVertices; - public List 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 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 mChulls = new List(); - 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 indices) - { - List 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 indices = new List(); - - getMesh(a.mResult, vc, indices); - getMesh(b.mResult, vc, indices); - - int vcount = vc.GetSize(); - List 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 output = new List(); // 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 hulls) - { - hulls.Sort(delegate(CHull a, CHull b) { return a.mVolume.CompareTo(b.mVolume); }); - } - } -} diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/ConvexDecomposition.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/ConvexDecomposition.cs deleted file mode 100644 index 2e2bb70..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/ConvexDecomposition.cs +++ /dev/null @@ -1,200 +0,0 @@ -/* The MIT License - * - * Copyright (c) 2010 Intel Corporation. - * All rights reserved. - * - * Based on the convexdecomposition library from - * 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 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 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 vertices, List 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 ifront = new List(); - List iback = new List(); - - 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 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 vertices2 = vback.GetVertices(); - int tcount = iback.Count / 3; - - calcConvexDecomposition(vertices2, iback, callback, masterVolume, depth + 1, maxDepth, concavePercent, mergePercent); - } - - iback.Clear(); - vback.Clear(); - } - } -} diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/ConvexResult.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/ConvexResult.cs deleted file mode 100644 index 87758b5..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/ConvexResult.cs +++ /dev/null @@ -1,74 +0,0 @@ -/* The MIT License - * - * Copyright (c) 2010 Intel Corporation. - * All rights reserved. - * - * Based on the convexdecomposition library from - * 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 HullVertices; - public List 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(); - HullIndices = new List(); - } - - public ConvexResult(List hvertices, List hindices) - { - HullVertices = hvertices; - HullIndices = hindices; - } - - public ConvexResult(ConvexResult r) - { - HullVertices = new List(r.HullVertices); - HullIndices = new List(r.HullIndices); - } - - public void Dispose() - { - HullVertices = null; - HullIndices = null; - } - } -} diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/HullClasses.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/HullClasses.cs deleted file mode 100644 index d81df26..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/HullClasses.cs +++ /dev/null @@ -1,171 +0,0 @@ -/* The MIT License - * - * Copyright (c) 2010 Intel Corporation. - * All rights reserved. - * - * Based on the convexdecomposition library from - * 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 OutputVertices = new List(); - public List 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 Vertices = new List(); - public List Indices = new List(); - } - - [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 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(); - NormalEpsilon = 0.001f; - MaxVertices = 4096; - MaxFaces = 4096; - SkinWidth = 0.01f; - } - - public HullDesc(HullFlag flags, List vertices) - { - Flags = flags; - Vertices = new List(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 vertices = new List(); - public List edges = new List(); - public List facets = new List(); - - public ConvexH(int vertices_size, int edges_size, int facets_size) - { - vertices = new List(vertices_size); - edges = new List(edges_size); - facets = new List(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; - } -} diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/HullTriangle.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/HullTriangle.cs deleted file mode 100644 index 1119a75..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/HullTriangle.cs +++ /dev/null @@ -1,99 +0,0 @@ -/* The MIT License - * - * Copyright (c) 2010 Intel Corporation. - * All rights reserved. - * - * Based on the convexdecomposition library from - * 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 tris; - - public HullTriangle(int a, int b, int c, List 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; - } - } - } - } -} diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/HullUtils.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/HullUtils.cs deleted file mode 100644 index c9ccfe2..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/HullUtils.cs +++ /dev/null @@ -1,1868 +0,0 @@ -/* The MIT License - * - * Copyright (c) 2010 Intel Corporation. - * All rights reserved. - * - * Based on the convexdecomposition library from - * 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 static class HullUtils - { - public static int argmin(float[] a, int n) - { - int r = 0; - for (int i = 1; i < n; i++) - { - if (a[i] < a[r]) - { - r = i; - } - } - return r; - } - - public static float clampf(float a) - { - return Math.Min(1.0f, Math.Max(0.0f, a)); - } - - public static float Round(float a, float precision) - { - return (float)Math.Floor(0.5f + a / precision) * precision; - } - - public static float Interpolate(float f0, float f1, float alpha) - { - return f0 * (1 - alpha) + f1 * alpha; - } - - public static void Swap(ref T a, ref T b) - { - T tmp = a; - a = b; - b = tmp; - } - - public static bool above(List vertices, int3 t, float3 p, float epsilon) - { - float3 vtx = vertices[t.x]; - float3 n = TriNormal(vtx, vertices[t.y], vertices[t.z]); - return (float3.dot(n, p - vtx) > epsilon); // EPSILON??? - } - - public static int hasedge(int3 t, int a, int b) - { - for (int i = 0; i < 3; i++) - { - int i1 = (i + 1) % 3; - if (t[i] == a && t[i1] == b) - return 1; - } - return 0; - } - - public static bool hasvert(int3 t, int v) - { - return (t[0] == v || t[1] == v || t[2] == v); - } - - public static int shareedge(int3 a, int3 b) - { - int i; - for (i = 0; i < 3; i++) - { - int i1 = (i + 1) % 3; - if (hasedge(a, b[i1], b[i]) != 0) - return 1; - } - return 0; - } - - public static void b2bfix(HullTriangle s, HullTriangle t, List tris) - { - int i; - for (i = 0; i < 3; i++) - { - int i1 = (i + 1) % 3; - int i2 = (i + 2) % 3; - int a = (s)[i1]; - int b = (s)[i2]; - Debug.Assert(tris[s.neib(a, b)].neib(b, a) == s.id); - Debug.Assert(tris[t.neib(a, b)].neib(b, a) == t.id); - tris[s.neib(a, b)].setneib(b, a, t.neib(b, a)); - tris[t.neib(b, a)].setneib(a, b, s.neib(a, b)); - } - } - - public static void removeb2b(HullTriangle s, HullTriangle t, List tris) - { - b2bfix(s, t, tris); - s.Dispose(); - t.Dispose(); - } - - public static void checkit(HullTriangle t, List tris) - { - int i; - Debug.Assert(tris[t.id] == t); - for (i = 0; i < 3; i++) - { - int i1 = (i + 1) % 3; - int i2 = (i + 2) % 3; - int a = (t)[i1]; - int b = (t)[i2]; - Debug.Assert(a != b); - Debug.Assert(tris[t.n[i]].neib(b, a) == t.id); - } - } - - public static void extrude(HullTriangle t0, int v, List tris) - { - int3 t = t0; - int n = tris.Count; - HullTriangle ta = new HullTriangle(v, t[1], t[2], tris); - ta.n = new int3(t0.n[0], n + 1, n + 2); - tris[t0.n[0]].setneib(t[1], t[2], n + 0); - HullTriangle tb = new HullTriangle(v, t[2], t[0], tris); - tb.n = new int3(t0.n[1], n + 2, n + 0); - tris[t0.n[1]].setneib(t[2], t[0], n + 1); - HullTriangle tc = new HullTriangle(v, t[0], t[1], tris); - tc.n = new int3(t0.n[2], n + 0, n + 1); - tris[t0.n[2]].setneib(t[0], t[1], n + 2); - checkit(ta, tris); - checkit(tb, tris); - checkit(tc, tris); - if (hasvert(tris[ta.n[0]], v)) - removeb2b(ta, tris[ta.n[0]], tris); - if (hasvert(tris[tb.n[0]], v)) - removeb2b(tb, tris[tb.n[0]], tris); - if (hasvert(tris[tc.n[0]], v)) - removeb2b(tc, tris[tc.n[0]], tris); - t0.Dispose(); - } - - public static HullTriangle extrudable(float epsilon, List tris) - { - int i; - HullTriangle t = null; - for (i = 0; i < tris.Count; i++) - { - if (t == null || (tris.Count > i && (object)tris[i] != null && t.rise < tris[i].rise)) - { - t = tris[i]; - } - } - return (t.rise > epsilon) ? t : null; - } - - public static Quaternion RotationArc(float3 v0, float3 v1) - { - Quaternion q = new Quaternion(); - v0 = float3.normalize(v0); // Comment these two lines out if you know its not needed. - v1 = float3.normalize(v1); // If vector is already unit length then why do it again? - float3 c = float3.cross(v0, v1); - float d = float3.dot(v0, v1); - if (d <= -1.0f) // 180 about x axis - { - return new Quaternion(1f, 0f, 0f, 0f); - } - float s = (float)Math.Sqrt((1 + d) * 2f); - q.x = c.x / s; - q.y = c.y / s; - q.z = c.z / s; - q.w = s / 2.0f; - return q; - } - - public static float3 PlaneLineIntersection(Plane plane, float3 p0, float3 p1) - { - // returns the point where the line p0-p1 intersects the plane n&d - float3 dif = p1 - p0; - float dn = float3.dot(plane.normal, dif); - float t = -(plane.dist + float3.dot(plane.normal, p0)) / dn; - return p0 + (dif * t); - } - - public static float3 LineProject(float3 p0, float3 p1, float3 a) - { - float3 w = new float3(); - w = p1 - p0; - float t = float3.dot(w, (a - p0)) / (w.x * w.x + w.y * w.y + w.z * w.z); - return p0 + w * t; - } - - public static float3 PlaneProject(Plane plane, float3 point) - { - return point - plane.normal * (float3.dot(point, plane.normal) + plane.dist); - } - - public static float LineProjectTime(float3 p0, float3 p1, float3 a) - { - float3 w = new float3(); - w = p1 - p0; - float t = float3.dot(w, (a - p0)) / (w.x * w.x + w.y * w.y + w.z * w.z); - return t; - } - - public static float3 ThreePlaneIntersection(Plane p0, Plane p1, Plane p2) - { - float3x3 mp = float3x3.Transpose(new float3x3(p0.normal, p1.normal, p2.normal)); - float3x3 mi = float3x3.Inverse(mp); - float3 b = new float3(p0.dist, p1.dist, p2.dist); - return -b * mi; - } - - public static bool PolyHit(List vert, float3 v0, float3 v1) - { - float3 impact = new float3(); - float3 normal = new float3(); - return PolyHit(vert, v0, v1, out impact, out normal); - } - - public static bool PolyHit(List vert, float3 v0, float3 v1, out float3 impact) - { - float3 normal = new float3(); - return PolyHit(vert, v0, v1, out impact, out normal); - } - - public static bool PolyHit(List vert, float3 v0, float3 v1, out float3 impact, out float3 normal) - { - float3 the_point = new float3(); - - impact = null; - normal = null; - - int i; - float3 nrml = new float3(0, 0, 0); - for (i = 0; i < vert.Count; i++) - { - int i1 = (i + 1) % vert.Count; - int i2 = (i + 2) % vert.Count; - nrml = nrml + float3.cross(vert[i1] - vert[i], vert[i2] - vert[i1]); - } - - float m = float3.magnitude(nrml); - if (m == 0.0) - { - return false; - } - nrml = nrml * (1.0f / m); - float dist = -float3.dot(nrml, vert[0]); - float d0; - float d1; - if ((d0 = float3.dot(v0, nrml) + dist) < 0 || (d1 = float3.dot(v1, nrml) + dist) > 0) - { - return false; - } - - // By using the cached plane distances d0 and d1 - // we can optimize the following: - // the_point = planelineintersection(nrml,dist,v0,v1); - float a = d0 / (d0 - d1); - the_point = v0 * (1 - a) + v1 * a; - - - bool inside = true; - for (int j = 0; inside && j < vert.Count; j++) - { - // let inside = 0 if outside - float3 pp1 = new float3(); - float3 pp2 = new float3(); - float3 side = new float3(); - pp1 = vert[j]; - pp2 = vert[(j + 1) % vert.Count]; - side = float3.cross((pp2 - pp1), (the_point - pp1)); - inside = (float3.dot(nrml, side) >= 0.0); - } - if (inside) - { - if (normal != null) - { - normal = nrml; - } - if (impact != null) - { - impact = the_point; - } - } - return inside; - } - - public static bool BoxInside(float3 p, float3 bmin, float3 bmax) - { - return (p.x >= bmin.x && p.x <= bmax.x && p.y >= bmin.y && p.y <= bmax.y && p.z >= bmin.z && p.z <= bmax.z); - } - - public static bool BoxIntersect(float3 v0, float3 v1, float3 bmin, float3 bmax, float3 impact) - { - if (BoxInside(v0, bmin, bmax)) - { - impact = v0; - return true; - } - if (v0.x <= bmin.x && v1.x >= bmin.x) - { - float a = (bmin.x - v0.x) / (v1.x - v0.x); - //v.x = bmin.x; - float vy = (1 - a) * v0.y + a * v1.y; - float vz = (1 - a) * v0.z + a * v1.z; - if (vy >= bmin.y && vy <= bmax.y && vz >= bmin.z && vz <= bmax.z) - { - impact.x = bmin.x; - impact.y = vy; - impact.z = vz; - return true; - } - } - else if (v0.x >= bmax.x && v1.x <= bmax.x) - { - float a = (bmax.x - v0.x) / (v1.x - v0.x); - //v.x = bmax.x; - float vy = (1 - a) * v0.y + a * v1.y; - float vz = (1 - a) * v0.z + a * v1.z; - if (vy >= bmin.y && vy <= bmax.y && vz >= bmin.z && vz <= bmax.z) - { - impact.x = bmax.x; - impact.y = vy; - impact.z = vz; - return true; - } - } - if (v0.y <= bmin.y && v1.y >= bmin.y) - { - float a = (bmin.y - v0.y) / (v1.y - v0.y); - float vx = (1 - a) * v0.x + a * v1.x; - //v.y = bmin.y; - float vz = (1 - a) * v0.z + a * v1.z; - if (vx >= bmin.x && vx <= bmax.x && vz >= bmin.z && vz <= bmax.z) - { - impact.x = vx; - impact.y = bmin.y; - impact.z = vz; - return true; - } - } - else if (v0.y >= bmax.y && v1.y <= bmax.y) - { - float a = (bmax.y - v0.y) / (v1.y - v0.y); - float vx = (1 - a) * v0.x + a * v1.x; - // vy = bmax.y; - float vz = (1 - a) * v0.z + a * v1.z; - if (vx >= bmin.x && vx <= bmax.x && vz >= bmin.z && vz <= bmax.z) - { - impact.x = vx; - impact.y = bmax.y; - impact.z = vz; - return true; - } - } - if (v0.z <= bmin.z && v1.z >= bmin.z) - { - float a = (bmin.z - v0.z) / (v1.z - v0.z); - float vx = (1 - a) * v0.x + a * v1.x; - float vy = (1 - a) * v0.y + a * v1.y; - // v.z = bmin.z; - if (vy >= bmin.y && vy <= bmax.y && vx >= bmin.x && vx <= bmax.x) - { - impact.x = vx; - impact.y = vy; - impact.z = bmin.z; - return true; - } - } - else if (v0.z >= bmax.z && v1.z <= bmax.z) - { - float a = (bmax.z - v0.z) / (v1.z - v0.z); - float vx = (1 - a) * v0.x + a * v1.x; - float vy = (1 - a) * v0.y + a * v1.y; - // v.z = bmax.z; - if (vy >= bmin.y && vy <= bmax.y && vx >= bmin.x && vx <= bmax.x) - { - impact.x = vx; - impact.y = vy; - impact.z = bmax.z; - return true; - } - } - return false; - } - - public static float DistanceBetweenLines(float3 ustart, float3 udir, float3 vstart, float3 vdir, float3 upoint) - { - return DistanceBetweenLines(ustart, udir, vstart, vdir, upoint, null); - } - - public static float DistanceBetweenLines(float3 ustart, float3 udir, float3 vstart, float3 vdir) - { - return DistanceBetweenLines(ustart, udir, vstart, vdir, null, null); - } - - public static float DistanceBetweenLines(float3 ustart, float3 udir, float3 vstart, float3 vdir, float3 upoint, float3 vpoint) - { - float3 cp = float3.normalize(float3.cross(udir, vdir)); - - float distu = -float3.dot(cp, ustart); - float distv = -float3.dot(cp, vstart); - float dist = (float)Math.Abs(distu - distv); - if (upoint != null) - { - Plane plane = new Plane(); - plane.normal = float3.normalize(float3.cross(vdir, cp)); - plane.dist = -float3.dot(plane.normal, vstart); - upoint = PlaneLineIntersection(plane, ustart, ustart + udir); - } - if (vpoint != null) - { - Plane plane = new Plane(); - plane.normal = float3.normalize(float3.cross(udir, cp)); - plane.dist = -float3.dot(plane.normal, ustart); - vpoint = PlaneLineIntersection(plane, vstart, vstart + vdir); - } - return dist; - } - - public static float3 TriNormal(float3 v0, float3 v1, float3 v2) - { - // return the normal of the triangle - // inscribed by v0, v1, and v2 - float3 cp = float3.cross(v1 - v0, v2 - v1); - float m = float3.magnitude(cp); - if (m == 0) - return new float3(1, 0, 0); - return cp * (1.0f / m); - } - - public static int PlaneTest(Plane p, float3 v, float planetestepsilon) - { - float a = float3.dot(v, p.normal) + p.dist; - int flag = (a > planetestepsilon) ? (2) : ((a < -planetestepsilon) ? (1) : (0)); - return flag; - } - - public static int SplitTest(ref ConvexH convex, Plane plane, float planetestepsilon) - { - int flag = 0; - for (int i = 0; i < convex.vertices.Count; i++) - { - flag |= PlaneTest(plane, convex.vertices[i], planetestepsilon); - } - return flag; - } - - public static Quaternion VirtualTrackBall(float3 cop, float3 cor, float3 dir1, float3 dir2) - { - // routine taken from game programming gems. - // Implement track ball functionality to spin stuf on the screen - // cop center of projection - // cor center of rotation - // dir1 old mouse direction - // dir2 new mouse direction - // pretend there is a sphere around cor. Then find the points - // where dir1 and dir2 intersect that sphere. Find the - // rotation that takes the first point to the second. - float m; - // compute plane - float3 nrml = cor - cop; - float fudgefactor = 1.0f / (float3.magnitude(nrml) * 0.25f); // since trackball proportional to distance from cop - nrml = float3.normalize(nrml); - float dist = -float3.dot(nrml, cor); - float3 u = PlaneLineIntersection(new Plane(nrml, dist), cop, cop + dir1); - u = u - cor; - u = u * fudgefactor; - m = float3.magnitude(u); - if (m > 1) - { - u /= m; - } - else - { - u = u - (nrml * (float)Math.Sqrt(1 - m * m)); - } - float3 v = PlaneLineIntersection(new Plane(nrml, dist), cop, cop + dir2); - v = v - cor; - v = v * fudgefactor; - m = float3.magnitude(v); - if (m > 1) - { - v /= m; - } - else - { - v = v - (nrml * (float)Math.Sqrt(1 - m * m)); - } - return RotationArc(u, v); - } - - public static bool AssertIntact(ConvexH convex, float planetestepsilon) - { - int i; - int estart = 0; - for (i = 0; i < convex.edges.Count; i++) - { - if (convex.edges[estart].p != convex.edges[i].p) - { - estart = i; - } - int inext = i + 1; - if (inext >= convex.edges.Count || convex.edges[inext].p != convex.edges[i].p) - { - inext = estart; - } - Debug.Assert(convex.edges[inext].p == convex.edges[i].p); - int nb = convex.edges[i].ea; - Debug.Assert(nb != 255); - if (nb == 255 || nb == -1) - return false; - Debug.Assert(nb != -1); - Debug.Assert(i == convex.edges[nb].ea); - } - for (i = 0; i < convex.edges.Count; i++) - { - Debug.Assert((0) == PlaneTest(convex.facets[convex.edges[i].p], convex.vertices[convex.edges[i].v], planetestepsilon)); - if ((0) != PlaneTest(convex.facets[convex.edges[i].p], convex.vertices[convex.edges[i].v], planetestepsilon)) - return false; - if (convex.edges[estart].p != convex.edges[i].p) - { - estart = i; - } - int i1 = i + 1; - if (i1 >= convex.edges.Count || convex.edges[i1].p != convex.edges[i].p) - { - i1 = estart; - } - int i2 = i1 + 1; - if (i2 >= convex.edges.Count || convex.edges[i2].p != convex.edges[i].p) - { - i2 = estart; - } - if (i == i2) // i sliced tangent to an edge and created 2 meaningless edges - continue; - float3 localnormal = TriNormal(convex.vertices[convex.edges[i].v], convex.vertices[convex.edges[i1].v], convex.vertices[convex.edges[i2].v]); - Debug.Assert(float3.dot(localnormal, convex.facets[convex.edges[i].p].normal) > 0); - if (float3.dot(localnormal, convex.facets[convex.edges[i].p].normal) <= 0) - return false; - } - return true; - } - - public static ConvexH test_btbq(float planetestepsilon) - { - // back to back quads - ConvexH convex = new ConvexH(4, 8, 2); - convex.vertices[0] = new float3(0, 0, 0); - convex.vertices[1] = new float3(1, 0, 0); - convex.vertices[2] = new float3(1, 1, 0); - convex.vertices[3] = new float3(0, 1, 0); - convex.facets[0] = new Plane(new float3(0, 0, 1), 0); - convex.facets[1] = new Plane(new float3(0, 0, -1), 0); - convex.edges[0] = new ConvexH.HalfEdge(7, 0, 0); - convex.edges[1] = new ConvexH.HalfEdge(6, 1, 0); - convex.edges[2] = new ConvexH.HalfEdge(5, 2, 0); - convex.edges[3] = new ConvexH.HalfEdge(4, 3, 0); - - convex.edges[4] = new ConvexH.HalfEdge(3, 0, 1); - convex.edges[5] = new ConvexH.HalfEdge(2, 3, 1); - convex.edges[6] = new ConvexH.HalfEdge(1, 2, 1); - convex.edges[7] = new ConvexH.HalfEdge(0, 1, 1); - AssertIntact(convex, planetestepsilon); - return convex; - } - - public static ConvexH test_cube() - { - ConvexH convex = new ConvexH(8, 24, 6); - convex.vertices[0] = new float3(0, 0, 0); - convex.vertices[1] = new float3(0, 0, 1); - convex.vertices[2] = new float3(0, 1, 0); - convex.vertices[3] = new float3(0, 1, 1); - convex.vertices[4] = new float3(1, 0, 0); - convex.vertices[5] = new float3(1, 0, 1); - convex.vertices[6] = new float3(1, 1, 0); - convex.vertices[7] = new float3(1, 1, 1); - - convex.facets[0] = new Plane(new float3(-1, 0, 0), 0); - convex.facets[1] = new Plane(new float3(1, 0, 0), -1); - convex.facets[2] = new Plane(new float3(0, -1, 0), 0); - convex.facets[3] = new Plane(new float3(0, 1, 0), -1); - convex.facets[4] = new Plane(new float3(0, 0, -1), 0); - convex.facets[5] = new Plane(new float3(0, 0, 1), -1); - - convex.edges[0] = new ConvexH.HalfEdge(11, 0, 0); - convex.edges[1] = new ConvexH.HalfEdge(23, 1, 0); - convex.edges[2] = new ConvexH.HalfEdge(15, 3, 0); - convex.edges[3] = new ConvexH.HalfEdge(16, 2, 0); - - convex.edges[4] = new ConvexH.HalfEdge(13, 6, 1); - convex.edges[5] = new ConvexH.HalfEdge(21, 7, 1); - convex.edges[6] = new ConvexH.HalfEdge(9, 5, 1); - convex.edges[7] = new ConvexH.HalfEdge(18, 4, 1); - - convex.edges[8] = new ConvexH.HalfEdge(19, 0, 2); - convex.edges[9] = new ConvexH.HalfEdge(6, 4, 2); - convex.edges[10] = new ConvexH.HalfEdge(20, 5, 2); - convex.edges[11] = new ConvexH.HalfEdge(0, 1, 2); - - convex.edges[12] = new ConvexH.HalfEdge(22, 3, 3); - convex.edges[13] = new ConvexH.HalfEdge(4, 7, 3); - convex.edges[14] = new ConvexH.HalfEdge(17, 6, 3); - convex.edges[15] = new ConvexH.HalfEdge(2, 2, 3); - - convex.edges[16] = new ConvexH.HalfEdge(3, 0, 4); - convex.edges[17] = new ConvexH.HalfEdge(14, 2, 4); - convex.edges[18] = new ConvexH.HalfEdge(7, 6, 4); - convex.edges[19] = new ConvexH.HalfEdge(8, 4, 4); - - convex.edges[20] = new ConvexH.HalfEdge(10, 1, 5); - convex.edges[21] = new ConvexH.HalfEdge(5, 5, 5); - convex.edges[22] = new ConvexH.HalfEdge(12, 7, 5); - convex.edges[23] = new ConvexH.HalfEdge(1, 3, 5); - - return convex; - } - - public static ConvexH ConvexHMakeCube(float3 bmin, float3 bmax) - { - ConvexH convex = test_cube(); - convex.vertices[0] = new float3(bmin.x, bmin.y, bmin.z); - convex.vertices[1] = new float3(bmin.x, bmin.y, bmax.z); - convex.vertices[2] = new float3(bmin.x, bmax.y, bmin.z); - convex.vertices[3] = new float3(bmin.x, bmax.y, bmax.z); - convex.vertices[4] = new float3(bmax.x, bmin.y, bmin.z); - convex.vertices[5] = new float3(bmax.x, bmin.y, bmax.z); - convex.vertices[6] = new float3(bmax.x, bmax.y, bmin.z); - convex.vertices[7] = new float3(bmax.x, bmax.y, bmax.z); - - convex.facets[0] = new Plane(new float3(-1, 0, 0), bmin.x); - convex.facets[1] = new Plane(new float3(1, 0, 0), -bmax.x); - convex.facets[2] = new Plane(new float3(0, -1, 0), bmin.y); - convex.facets[3] = new Plane(new float3(0, 1, 0), -bmax.y); - convex.facets[4] = new Plane(new float3(0, 0, -1), bmin.z); - convex.facets[5] = new Plane(new float3(0, 0, 1), -bmax.z); - return convex; - } - - public static ConvexH ConvexHCrop(ref ConvexH convex, Plane slice, float planetestepsilon) - { - int i; - int vertcountunder = 0; - int vertcountover = 0; - List vertscoplanar = new List(); // existing vertex members of convex that are coplanar - List edgesplit = new List(); // existing edges that members of convex that cross the splitplane - - Debug.Assert(convex.edges.Count < 480); - - EdgeFlag[] edgeflag = new EdgeFlag[512]; - VertFlag[] vertflag = new VertFlag[256]; - PlaneFlag[] planeflag = new PlaneFlag[128]; - ConvexH.HalfEdge[] tmpunderedges = new ConvexH.HalfEdge[512]; - Plane[] tmpunderplanes = new Plane[128]; - Coplanar[] coplanaredges = new Coplanar[512]; - int coplanaredges_num = 0; - - List createdverts = new List(); - - // do the side-of-plane tests - for (i = 0; i < convex.vertices.Count; i++) - { - vertflag[i].planetest = (byte)PlaneTest(slice, convex.vertices[i], planetestepsilon); - if (vertflag[i].planetest == (0)) - { - // ? vertscoplanar.Add(i); - vertflag[i].undermap = (byte)vertcountunder++; - vertflag[i].overmap = (byte)vertcountover++; - } - else if (vertflag[i].planetest == (1)) - { - vertflag[i].undermap = (byte)vertcountunder++; - } - else - { - Debug.Assert(vertflag[i].planetest == (2)); - vertflag[i].overmap = (byte)vertcountover++; - vertflag[i].undermap = 255; // for debugging purposes - } - } - int vertcountunderold = vertcountunder; // for debugging only - - int under_edge_count = 0; - int underplanescount = 0; - int e0 = 0; - - for (int currentplane = 0; currentplane < convex.facets.Count; currentplane++) - { - int estart = e0; - int enextface = 0; - int planeside = 0; - int e1 = e0 + 1; - int vout = -1; - int vin = -1; - int coplanaredge = -1; - do - { - - if (e1 >= convex.edges.Count || convex.edges[e1].p != currentplane) - { - enextface = e1; - e1 = estart; - } - ConvexH.HalfEdge edge0 = convex.edges[e0]; - ConvexH.HalfEdge edge1 = convex.edges[e1]; - ConvexH.HalfEdge edgea = convex.edges[edge0.ea]; - - planeside |= vertflag[edge0.v].planetest; - //if((vertflag[edge0.v].planetest & vertflag[edge1.v].planetest) == COPLANAR) { - // assert(ecop==-1); - // ecop=e; - //} - - if (vertflag[edge0.v].planetest == (2) && vertflag[edge1.v].planetest == (2)) - { - // both endpoints over plane - edgeflag[e0].undermap = -1; - } - else if ((vertflag[edge0.v].planetest | vertflag[edge1.v].planetest) == (1)) - { - // at least one endpoint under, the other coplanar or under - - edgeflag[e0].undermap = (short)under_edge_count; - tmpunderedges[under_edge_count].v = vertflag[edge0.v].undermap; - tmpunderedges[under_edge_count].p = (byte)underplanescount; - if (edge0.ea < e0) - { - // connect the neighbors - Debug.Assert(edgeflag[edge0.ea].undermap != -1); - tmpunderedges[under_edge_count].ea = edgeflag[edge0.ea].undermap; - tmpunderedges[edgeflag[edge0.ea].undermap].ea = (short)under_edge_count; - } - under_edge_count++; - } - else if ((vertflag[edge0.v].planetest | vertflag[edge1.v].planetest) == (0)) - { - // both endpoints coplanar - // must check a 3rd point to see if UNDER - int e2 = e1 + 1; - if (e2 >= convex.edges.Count || convex.edges[e2].p != currentplane) - { - e2 = estart; - } - Debug.Assert(convex.edges[e2].p == currentplane); - ConvexH.HalfEdge edge2 = convex.edges[e2]; - if (vertflag[edge2.v].planetest == (1)) - { - - edgeflag[e0].undermap = (short)under_edge_count; - tmpunderedges[under_edge_count].v = vertflag[edge0.v].undermap; - tmpunderedges[under_edge_count].p = (byte)underplanescount; - tmpunderedges[under_edge_count].ea = -1; - // make sure this edge is added to the "coplanar" list - coplanaredge = under_edge_count; - vout = vertflag[edge0.v].undermap; - vin = vertflag[edge1.v].undermap; - under_edge_count++; - } - else - { - edgeflag[e0].undermap = -1; - } - } - else if (vertflag[edge0.v].planetest == (1) && vertflag[edge1.v].planetest == (2)) - { - // first is under 2nd is over - - edgeflag[e0].undermap = (short)under_edge_count; - tmpunderedges[under_edge_count].v = vertflag[edge0.v].undermap; - tmpunderedges[under_edge_count].p = (byte)underplanescount; - if (edge0.ea < e0) - { - Debug.Assert(edgeflag[edge0.ea].undermap != -1); - // connect the neighbors - tmpunderedges[under_edge_count].ea = edgeflag[edge0.ea].undermap; - tmpunderedges[edgeflag[edge0.ea].undermap].ea = (short)under_edge_count; - vout = tmpunderedges[edgeflag[edge0.ea].undermap].v; - } - else - { - Plane p0 = convex.facets[edge0.p]; - Plane pa = convex.facets[edgea.p]; - createdverts.Add(ThreePlaneIntersection(p0, pa, slice)); - //createdverts.Add(PlaneProject(slice,PlaneLineIntersection(slice,convex.vertices[edge0.v],convex.vertices[edgea.v]))); - //createdverts.Add(PlaneLineIntersection(slice,convex.vertices[edge0.v],convex.vertices[edgea.v])); - vout = vertcountunder++; - } - under_edge_count++; - /// hmmm something to think about: i might be able to output this edge regarless of - // wheter or not we know v-in yet. ok i;ll try this now: - tmpunderedges[under_edge_count].v = (byte)vout; - tmpunderedges[under_edge_count].p = (byte)underplanescount; - tmpunderedges[under_edge_count].ea = -1; - coplanaredge = under_edge_count; - under_edge_count++; - - if (vin != -1) - { - // we previously processed an edge where we came under - // now we know about vout as well - - // ADD THIS EDGE TO THE LIST OF EDGES THAT NEED NEIGHBOR ON PARTITION PLANE!! - } - - } - else if (vertflag[edge0.v].planetest == (0) && vertflag[edge1.v].planetest == (2)) - { - // first is coplanar 2nd is over - - edgeflag[e0].undermap = -1; - vout = vertflag[edge0.v].undermap; - // I hate this but i have to make sure part of this face is UNDER before ouputting this vert - int k = estart; - Debug.Assert(edge0.p == currentplane); - while (!((planeside & 1) != 0) && k < convex.edges.Count && convex.edges[k].p == edge0.p) - { - planeside |= vertflag[convex.edges[k].v].planetest; - k++; - } - if ((planeside & 1) != 0) - { - tmpunderedges[under_edge_count].v = (byte)vout; - tmpunderedges[under_edge_count].p = (byte)underplanescount; - tmpunderedges[under_edge_count].ea = -1; - coplanaredge = under_edge_count; // hmmm should make a note of the edge # for later on - under_edge_count++; - - } - } - else if (vertflag[edge0.v].planetest == (2) && vertflag[edge1.v].planetest == (1)) - { - // first is over next is under - // new vertex!!! - Debug.Assert(vin == -1); - if (e0 < edge0.ea) - { - Plane p0 = convex.facets[edge0.p]; - Plane pa = convex.facets[edgea.p]; - createdverts.Add(ThreePlaneIntersection(p0, pa, slice)); - //createdverts.Add(PlaneLineIntersection(slice,convex.vertices[edge0.v],convex.vertices[edgea.v])); - //createdverts.Add(PlaneProject(slice,PlaneLineIntersection(slice,convex.vertices[edge0.v],convex.vertices[edgea.v]))); - vin = vertcountunder++; - } - else - { - // find the new vertex that was created by edge[edge0.ea] - int nea = edgeflag[edge0.ea].undermap; - Debug.Assert(tmpunderedges[nea].p == tmpunderedges[nea + 1].p); - vin = tmpunderedges[nea + 1].v; - Debug.Assert(vin < vertcountunder); - Debug.Assert(vin >= vertcountunderold); // for debugging only - } - if (vout != -1) - { - // we previously processed an edge where we went over - // now we know vin too - // ADD THIS EDGE TO THE LIST OF EDGES THAT NEED NEIGHBOR ON PARTITION PLANE!! - } - // output edge - tmpunderedges[under_edge_count].v = (byte)vin; - tmpunderedges[under_edge_count].p = (byte)underplanescount; - edgeflag[e0].undermap = (short)under_edge_count; - if (e0 > edge0.ea) - { - Debug.Assert(edgeflag[edge0.ea].undermap != -1); - // connect the neighbors - tmpunderedges[under_edge_count].ea = edgeflag[edge0.ea].undermap; - tmpunderedges[edgeflag[edge0.ea].undermap].ea = (short)under_edge_count; - } - Debug.Assert(edgeflag[e0].undermap == under_edge_count); - under_edge_count++; - } - else if (vertflag[edge0.v].planetest == (2) && vertflag[edge1.v].planetest == (0)) - { - // first is over next is coplanar - - edgeflag[e0].undermap = -1; - vin = vertflag[edge1.v].undermap; - Debug.Assert(vin != -1); - if (vout != -1) - { - // we previously processed an edge where we came under - // now we know both endpoints - // ADD THIS EDGE TO THE LIST OF EDGES THAT NEED NEIGHBOR ON PARTITION PLANE!! - } - - } - else - { - Debug.Assert(false); - } - - - e0 = e1; - e1++; // do the modulo at the beginning of the loop - - } while (e0 != estart); - e0 = enextface; - if ((planeside & 1) != 0) - { - planeflag[currentplane].undermap = (byte)underplanescount; - tmpunderplanes[underplanescount] = convex.facets[currentplane]; - underplanescount++; - } - else - { - planeflag[currentplane].undermap = 0; - } - if (vout >= 0 && (planeside & 1) != 0) - { - Debug.Assert(vin >= 0); - Debug.Assert(coplanaredge >= 0); - Debug.Assert(coplanaredge != 511); - coplanaredges[coplanaredges_num].ea = (ushort)coplanaredge; - coplanaredges[coplanaredges_num].v0 = (byte)vin; - coplanaredges[coplanaredges_num].v1 = (byte)vout; - coplanaredges_num++; - } - } - - // add the new plane to the mix: - if (coplanaredges_num > 0) - { - tmpunderplanes[underplanescount++] = slice; - } - for (i = 0; i < coplanaredges_num - 1; i++) - { - if (coplanaredges[i].v1 != coplanaredges[i + 1].v0) - { - int j = 0; - for (j = i + 2; j < coplanaredges_num; j++) - { - if (coplanaredges[i].v1 == coplanaredges[j].v0) - { - Coplanar tmp = coplanaredges[i + 1]; - coplanaredges[i + 1] = coplanaredges[j]; - coplanaredges[j] = tmp; - break; - } - } - if (j >= coplanaredges_num) - { - Debug.Assert(j < coplanaredges_num); - return null; - } - } - } - - ConvexH punder = new ConvexH(vertcountunder, under_edge_count + coplanaredges_num, underplanescount); - ConvexH under = punder; - - { - int k = 0; - for (i = 0; i < convex.vertices.Count; i++) - { - if (vertflag[i].planetest != (2)) - { - under.vertices[k++] = convex.vertices[i]; - } - } - i = 0; - while (k < vertcountunder) - { - under.vertices[k++] = createdverts[i++]; - } - Debug.Assert(i == createdverts.Count); - } - - for (i = 0; i < coplanaredges_num; i++) - { - ConvexH.HalfEdge edge = under.edges[under_edge_count + i]; - edge.p = (byte)(underplanescount - 1); - edge.ea = (short)coplanaredges[i].ea; - edge.v = (byte)coplanaredges[i].v0; - under.edges[under_edge_count + i] = edge; - - tmpunderedges[coplanaredges[i].ea].ea = (short)(under_edge_count + i); - } - - under.edges = new List(tmpunderedges); - under.facets = new List(tmpunderplanes); - return punder; - } - - public static ConvexH ConvexHDup(ConvexH src) - { - ConvexH dst = new ConvexH(src.vertices.Count, src.edges.Count, src.facets.Count); - dst.vertices = new List(src.vertices.Count); - foreach (float3 f in src.vertices) - dst.vertices.Add(new float3(f)); - dst.edges = new List(src.edges.Count); - foreach (ConvexH.HalfEdge e in src.edges) - dst.edges.Add(new ConvexH.HalfEdge(e)); - dst.facets = new List(src.facets.Count); - foreach (Plane p in src.facets) - dst.facets.Add(new Plane(p)); - return dst; - } - - public static int candidateplane(List planes, int planes_count, ConvexH convex, float epsilon) - { - int p = 0; - float md = 0; - int i; - for (i = 0; i < planes_count; i++) - { - float d = 0; - for (int j = 0; j < convex.vertices.Count; j++) - { - d = Math.Max(d, float3.dot(convex.vertices[j], planes[i].normal) + planes[i].dist); - } - if (i == 0 || d > md) - { - p = i; - md = d; - } - } - return (md > epsilon) ? p : -1; - } - - public static float3 orth(float3 v) - { - float3 a = float3.cross(v, new float3(0f, 0f, 1f)); - float3 b = float3.cross(v, new float3(0f, 1f, 0f)); - return float3.normalize((float3.magnitude(a) > float3.magnitude(b)) ? a : b); - } - - public static int maxdir(List p, int count, float3 dir) - { - Debug.Assert(count != 0); - int m = 0; - float currDotm = float3.dot(p[0], dir); - for (int i = 1; i < count; i++) - { - float currDoti = float3.dot(p[i], dir); - if (currDoti > currDotm) - { - currDotm = currDoti; - m = i; - } - } - return m; - } - - public static int maxdirfiltered(List p, int count, float3 dir, byte[] allow) - { - //Debug.Assert(count != 0); - int m = 0; - float currDotm = float3.dot(p[0], dir); - float currDoti; - - while (allow[m] == 0) - m++; - - for (int i = 1; i < count; i++) - { - if (allow[i] != 0) - { - currDoti = float3.dot(p[i], dir); - if (currDoti > currDotm) - { - currDotm = currDoti; - m = i; - } - } - } - //Debug.Assert(m != -1); - return m; - } - - public static int maxdirsterid(List p, int count, float3 dir, byte[] allow) - { - int m = -1; - while (m == -1) - { - m = maxdirfiltered(p, count, dir, allow); - if (allow[m] == 3) - return m; - float3 u = orth(dir); - float3 v = float3.cross(u, dir); - int ma = -1; - for (float x = 0.0f; x <= 360.0f; x += 45.0f) - { - int mb; - { - float s = (float)Math.Sin((3.14159264f / 180.0f) * (x)); - float c = (float)Math.Cos((3.14159264f / 180.0f) * (x)); - mb = maxdirfiltered(p, count, dir + (u * s + v * c) * 0.025f, allow); - } - if (ma == m && mb == m) - { - allow[m] = 3; - return m; - } - if (ma != -1 && ma != mb) // Yuck - this is really ugly - { - int mc = ma; - for (float xx = x - 40.0f; xx <= x; xx += 5.0f) - { - float s = (float)Math.Sin((3.14159264f / 180.0f) * (xx)); - float c = (float)Math.Cos((3.14159264f / 180.0f) * (xx)); - int md = maxdirfiltered(p, count, dir + (u * s + v * c) * 0.025f, allow); - if (mc == m && md == m) - { - allow[m] = 3; - return m; - } - mc = md; - } - } - ma = mb; - } - allow[m] = 0; - m = -1; - } - - Debug.Assert(false); - return m; - } - - public static int4 FindSimplex(List verts, byte[] allow) - { - float3[] basis = new float3[3]; - basis[0] = new float3(0.01f, 0.02f, 1.0f); - int p0 = maxdirsterid(verts, verts.Count, basis[0], allow); - int p1 = maxdirsterid(verts, verts.Count, -basis[0], allow); - basis[0] = verts[p0] - verts[p1]; - if (p0 == p1 || basis[0] == new float3(0, 0, 0)) - return new int4(-1, -1, -1, -1); - basis[1] = float3.cross(new float3(1, 0.02f, 0), basis[0]); - basis[2] = float3.cross(new float3(-0.02f, 1, 0), basis[0]); - basis[1] = float3.normalize((float3.magnitude(basis[1]) > float3.magnitude(basis[2])) ? basis[1] : basis[2]); - int p2 = maxdirsterid(verts, verts.Count, basis[1], allow); - if (p2 == p0 || p2 == p1) - { - p2 = maxdirsterid(verts, verts.Count, -basis[1], allow); - } - if (p2 == p0 || p2 == p1) - return new int4(-1, -1, -1, -1); - basis[1] = verts[p2] - verts[p0]; - basis[2] = float3.normalize(float3.cross(basis[1], basis[0])); - int p3 = maxdirsterid(verts, verts.Count, basis[2], allow); - if (p3 == p0 || p3 == p1 || p3 == p2) - p3 = maxdirsterid(verts, verts.Count, -basis[2], allow); - if (p3 == p0 || p3 == p1 || p3 == p2) - return new int4(-1, -1, -1, -1); - Debug.Assert(!(p0 == p1 || p0 == p2 || p0 == p3 || p1 == p2 || p1 == p3 || p2 == p3)); - if (float3.dot(verts[p3] - verts[p0], float3.cross(verts[p1] - verts[p0], verts[p2] - verts[p0])) < 0) - { - Swap(ref p2, ref p3); - } - return new int4(p0, p1, p2, p3); - } - - public static float GetDist(float px, float py, float pz, float3 p2) - { - float dx = px - p2.x; - float dy = py - p2.y; - float dz = pz - p2.z; - - return dx * dx + dy * dy + dz * dz; - } - - public static void ReleaseHull(PHullResult result) - { - if (result.Indices != null) - result.Indices = null; - if (result.Vertices != null) - result.Vertices = null; - } - - public static int calchullgen(List verts, int vlimit, List tris) - { - if (verts.Count < 4) - return 0; - if (vlimit == 0) - vlimit = 1000000000; - int j; - float3 bmin = new float3(verts[0]); - float3 bmax = new float3(verts[0]); - List isextreme = new List(verts.Count); - byte[] allow = new byte[verts.Count]; - for (j = 0; j < verts.Count; j++) - { - allow[j] = 1; - isextreme.Add(0); - bmin = float3.VectorMin(bmin, verts[j]); - bmax = float3.VectorMax(bmax, verts[j]); - } - float epsilon = float3.magnitude(bmax - bmin) * 0.001f; - - int4 p = FindSimplex(verts, allow); - if (p.x == -1) // simplex failed - return 0; - - float3 center = (verts[p[0]] + verts[p[1]] + verts[p[2]] + verts[p[3]]) / 4.0f; // a valid interior point - HullTriangle t0 = new HullTriangle(p[2], p[3], p[1], tris); - t0.n = new int3(2, 3, 1); - HullTriangle t1 = new HullTriangle(p[3], p[2], p[0], tris); - t1.n = new int3(3, 2, 0); - HullTriangle t2 = new HullTriangle(p[0], p[1], p[3], tris); - t2.n = new int3(0, 1, 3); - HullTriangle t3 = new HullTriangle(p[1], p[0], p[2], tris); - t3.n = new int3(1, 0, 2); - isextreme[p[0]] = isextreme[p[1]] = isextreme[p[2]] = isextreme[p[3]] = 1; - checkit(t0, tris); - checkit(t1, tris); - checkit(t2, tris); - checkit(t3, tris); - - for (j = 0; j < tris.Count; j++) - { - HullTriangle t = tris[j]; - Debug.Assert((object)t != null); - Debug.Assert(t.vmax < 0); - float3 n = TriNormal(verts[(t)[0]], verts[(t)[1]], verts[(t)[2]]); - t.vmax = maxdirsterid(verts, verts.Count, n, allow); - t.rise = float3.dot(n, verts[t.vmax] - verts[(t)[0]]); - } - HullTriangle te; - vlimit -= 4; - while (vlimit > 0 && (te = extrudable(epsilon, tris)) != null) - { - int3 ti = te; - int v = te.vmax; - Debug.Assert(isextreme[v] == 0); // wtf we've already done this vertex - isextreme[v] = 1; - //if(v==p0 || v==p1 || v==p2 || v==p3) continue; // done these already - j = tris.Count; - while (j-- != 0) - { - if (tris.Count <= j || (object)tris[j] == null) - continue; - int3 t = tris[j]; - if (above(verts, t, verts[v], 0.01f * epsilon)) - { - extrude(tris[j], v, tris); - } - } - // now check for those degenerate cases where we have a flipped triangle or a really skinny triangle - j = tris.Count; - while (j-- != 0) - { - if (tris.Count <= j || (object)tris[j] == null) - continue; - if (!hasvert(tris[j], v)) - break; - int3 nt = tris[j]; - if (above(verts, nt, center, 0.01f * epsilon) || float3.magnitude(float3.cross(verts[nt[1]] - verts[nt[0]], verts[nt[2]] - verts[nt[1]])) < epsilon * epsilon * 0.1f) - { - HullTriangle nb = tris[tris[j].n[0]]; - Debug.Assert(nb != null); - Debug.Assert(!hasvert(nb, v)); - Debug.Assert(nb.id < j); - extrude(nb, v, tris); - j = tris.Count; - } - } - j = tris.Count; - while (j-- != 0) - { - HullTriangle t = tris[j]; - if (t == null) - continue; - if (t.vmax >= 0) - break; - float3 n = TriNormal(verts[(t)[0]], verts[(t)[1]], verts[(t)[2]]); - t.vmax = maxdirsterid(verts, verts.Count, n, allow); - if (isextreme[t.vmax] != 0) - { - t.vmax = -1; // already done that vertex - algorithm needs to be able to terminate. - } - else - { - t.rise = float3.dot(n, verts[t.vmax] - verts[(t)[0]]); - } - } - vlimit--; - } - return 1; - } - - public static bool calchull(List verts, out List tris_out, int vlimit, List tris) - { - tris_out = null; - - int rc = calchullgen(verts, vlimit, tris); - if (rc == 0) - return false; - List ts = new List(); - for (int i = 0; i < tris.Count; i++) - { - if ((object)tris[i] != null) - { - for (int j = 0; j < 3; j++) - ts.Add((tris[i])[j]); - tris[i] = null; - } - } - - tris_out = ts; - tris.Clear(); - return true; - } - - public static int calchullpbev(List verts, int vlimit, out List planes, float bevangle, List tris) - { - int i; - int j; - planes = new List(); - int rc = calchullgen(verts, vlimit, tris); - if (rc == 0) - return 0; - for (i = 0; i < tris.Count; i++) - { - if (tris[i] != null) - { - Plane p = new Plane(); - HullTriangle t = tris[i]; - p.normal = TriNormal(verts[(t)[0]], verts[(t)[1]], verts[(t)[2]]); - p.dist = -float3.dot(p.normal, verts[(t)[0]]); - planes.Add(p); - for (j = 0; j < 3; j++) - { - if (t.n[j] < t.id) - continue; - HullTriangle s = tris[t.n[j]]; - float3 snormal = TriNormal(verts[(s)[0]], verts[(s)[1]], verts[(s)[2]]); - if (float3.dot(snormal, p.normal) >= Math.Cos(bevangle * (3.14159264f / 180.0f))) - continue; - float3 n = float3.normalize(snormal + p.normal); - planes.Add(new Plane(n, -float3.dot(n, verts[maxdir(verts, verts.Count, n)]))); - } - } - } - - tris.Clear(); - return 1; - } - - public static int overhull(List planes, List verts, int maxplanes, out List verts_out, out List faces_out, float inflate) - { - verts_out = null; - faces_out = null; - - int i; - int j; - if (verts.Count < 4) - return 0; - maxplanes = Math.Min(maxplanes, planes.Count); - float3 bmin = new float3(verts[0]); - float3 bmax = new float3(verts[0]); - for (i = 0; i < verts.Count; i++) - { - bmin = float3.VectorMin(bmin, verts[i]); - bmax = float3.VectorMax(bmax, verts[i]); - } - // float diameter = magnitude(bmax-bmin); - // inflate *=diameter; // RELATIVE INFLATION - bmin -= new float3(inflate, inflate, inflate); - bmax += new float3(inflate, inflate, inflate); - for (i = 0; i < planes.Count; i++) - { - planes[i].dist -= inflate; - } - float3 emin = new float3(bmin); - float3 emax = new float3(bmax); - float epsilon = float3.magnitude(emax - emin) * 0.025f; - float planetestepsilon = float3.magnitude(emax - emin) * (0.001f); - // todo: add bounding cube planes to force bevel. or try instead not adding the diameter expansion ??? must think. - // ConvexH *convex = ConvexHMakeCube(bmin - float3(diameter,diameter,diameter),bmax+float3(diameter,diameter,diameter)); - ConvexH c = ConvexHMakeCube(new float3(bmin), new float3(bmax)); - int k; - while (maxplanes-- != 0 && (k = candidateplane(planes, planes.Count, c, epsilon)) >= 0) - { - ConvexH tmp = c; - c = ConvexHCrop(ref tmp, planes[k], planetestepsilon); - if (c == null) // might want to debug this case better!!! - { - c = tmp; - break; - } - if (AssertIntact(c, planetestepsilon) == false) // might want to debug this case better too!!! - { - c = tmp; - break; - } - tmp.edges = null; - tmp.facets = null; - tmp.vertices = null; - } - - Debug.Assert(AssertIntact(c, planetestepsilon)); - //return c; - //C++ TO C# CONVERTER TODO TASK: The memory management function 'malloc' has no equivalent in C#: - faces_out = new List(); //(int)malloc(sizeof(int) * (1 + c.facets.Count + c.edges.Count)); // new int[1+c->facets.count+c->edges.count]; - int faces_count_out = 0; - i = 0; - faces_out[faces_count_out++] = -1; - k = 0; - while (i < c.edges.Count) - { - j = 1; - while (j + i < c.edges.Count && c.edges[i].p == c.edges[i + j].p) - { - j++; - } - faces_out[faces_count_out++] = j; - while (j-- != 0) - { - faces_out[faces_count_out++] = c.edges[i].v; - i++; - } - k++; - } - faces_out[0] = k; // number of faces. - Debug.Assert(k == c.facets.Count); - Debug.Assert(faces_count_out == 1 + c.facets.Count + c.edges.Count); - verts_out = c.vertices; // new float3[c->vertices.count]; - int verts_count_out = c.vertices.Count; - for (i = 0; i < c.vertices.Count; i++) - { - verts_out[i] = new float3(c.vertices[i]); - } - - c.edges = null; - c.facets = null; - c.vertices = null; - return 1; - } - - public static int overhullv(List verts, int maxplanes, out List verts_out, out List faces_out, float inflate, float bevangle, int vlimit, List tris) - { - verts_out = null; - faces_out = null; - - if (verts.Count == 0) - return 0; - List planes = new List(); - int rc = calchullpbev(verts, vlimit, out planes, bevangle, tris); - if (rc == 0) - return 0; - return overhull(planes, verts, maxplanes, out verts_out, out faces_out, inflate); - } - - public static void addPoint(ref uint vcount, List p, float x, float y, float z) - { - p.Add(new float3(x, y, z)); - vcount++; - } - - public static bool ComputeHull(List vertices, ref PHullResult result, int vlimit, float inflate) - { - List tris = new List(); - List faces; - List verts_out; - - if (inflate == 0.0f) - { - List tris_out; - bool ret = calchull(vertices, out tris_out, vlimit, tris); - if (ret == false) - return false; - - result.Indices = tris_out; - result.Vertices = vertices; - return true; - } - else - { - int ret = overhullv(vertices, 35, out verts_out, out faces, inflate, 120.0f, vlimit, tris); - if (ret == 0) - return false; - - List tris2 = new List(); - int n = faces[0]; - int k = 1; - for (int i = 0; i < n; i++) - { - int pn = faces[k++]; - for (int j = 2; j < pn; j++) - tris2.Add(new int3(faces[k], faces[k + j - 1], faces[k + j])); - k += pn; - } - Debug.Assert(tris2.Count == faces.Count - 1 - (n * 3)); - - result.Indices = new List(tris2.Count * 3); - for (int i = 0; i < tris2.Count; i++) - { - result.Indices.Add(tris2[i].x); - result.Indices.Add(tris2[i].y); - result.Indices.Add(tris2[i].z); - } - result.Vertices = verts_out; - - return true; - } - } - - private static bool CleanupVertices(List svertices, out List vertices, float normalepsilon, out float3 scale) - { - const float EPSILON = 0.000001f; - - vertices = new List(); - scale = new float3(1f, 1f, 1f); - - if (svertices.Count == 0) - return false; - - uint vcount = 0; - - float[] recip = new float[3]; - - float[] bmin = { Single.MaxValue, Single.MaxValue, Single.MaxValue }; - float[] bmax = { Single.MinValue, Single.MinValue, Single.MinValue }; - - for (int i = 0; i < svertices.Count; i++) - { - float3 p = svertices[i]; - - for (int j = 0; j < 3; j++) - { - if (p[j] < bmin[j]) - bmin[j] = p[j]; - if (p[j] > bmax[j]) - bmax[j] = p[j]; - } - } - - float dx = bmax[0] - bmin[0]; - float dy = bmax[1] - bmin[1]; - float dz = bmax[2] - bmin[2]; - - float3 center = new float3(); - - center.x = dx * 0.5f + bmin[0]; - center.y = dy * 0.5f + bmin[1]; - center.z = dz * 0.5f + bmin[2]; - - if (dx < EPSILON || dy < EPSILON || dz < EPSILON || svertices.Count < 3) - { - float len = Single.MaxValue; - - if (dx > EPSILON && dx < len) - len = dx; - if (dy > EPSILON && dy < len) - len = dy; - if (dz > EPSILON && dz < len) - len = dz; - - if (len == Single.MaxValue) - { - dx = dy = dz = 0.01f; // one centimeter - } - else - { - if (dx < EPSILON) // 1/5th the shortest non-zero edge. - dx = len * 0.05f; - if (dy < EPSILON) - dy = len * 0.05f; - if (dz < EPSILON) - dz = len * 0.05f; - } - - float x1 = center[0] - dx; - float x2 = center[0] + dx; - - float y1 = center[1] - dy; - float y2 = center[1] + dy; - - float z1 = center[2] - dz; - float z2 = center[2] + dz; - - addPoint(ref vcount, vertices, x1, y1, z1); - addPoint(ref vcount, vertices, x2, y1, z1); - addPoint(ref vcount, vertices, x2, y2, z1); - addPoint(ref vcount, vertices, x1, y2, z1); - addPoint(ref vcount, vertices, x1, y1, z2); - addPoint(ref vcount, vertices, x2, y1, z2); - addPoint(ref vcount, vertices, x2, y2, z2); - addPoint(ref vcount, vertices, x1, y2, z2); - - return true; // return cube - } - else - { - scale.x = dx; - scale.y = dy; - scale.z = dz; - - recip[0] = 1f / dx; - recip[1] = 1f / dy; - recip[2] = 1f / dz; - - center.x *= recip[0]; - center.y *= recip[1]; - center.z *= recip[2]; - } - - for (int i = 0; i < svertices.Count; i++) - { - float3 p = svertices[i]; - - float px = p[0]; - float py = p[1]; - float pz = p[2]; - - px = px * recip[0]; // normalize - py = py * recip[1]; // normalize - pz = pz * recip[2]; // normalize - - if (true) - { - int j; - - for (j = 0; j < vcount; j++) - { - float3 v = vertices[j]; - - float x = v[0]; - float y = v[1]; - float z = v[2]; - - float dx1 = Math.Abs(x - px); - float dy1 = Math.Abs(y - py); - float dz1 = Math.Abs(z - pz); - - if (dx1 < normalepsilon && dy1 < normalepsilon && dz1 < normalepsilon) - { - // ok, it is close enough to the old one - // now let us see if it is further from the center of the point cloud than the one we already recorded. - // in which case we keep this one instead. - float dist1 = GetDist(px, py, pz, center); - float dist2 = GetDist(v[0], v[1], v[2], center); - - if (dist1 > dist2) - { - v.x = px; - v.y = py; - v.z = pz; - } - - break; - } - } - - if (j == vcount) - { - float3 dest = new float3(px, py, pz); - vertices.Add(dest); - vcount++; - } - } - } - - // ok..now make sure we didn't prune so many vertices it is now invalid. - if (true) - { - float[] bmin2 = { Single.MaxValue, Single.MaxValue, Single.MaxValue }; - float[] bmax2 = { Single.MinValue, Single.MinValue, Single.MinValue }; - - for (int i = 0; i < vcount; i++) - { - float3 p = vertices[i]; - for (int j = 0; j < 3; j++) - { - if (p[j] < bmin2[j]) - bmin2[j] = p[j]; - if (p[j] > bmax2[j]) - bmax2[j] = p[j]; - } - } - - float dx2 = bmax2[0] - bmin2[0]; - float dy2 = bmax2[1] - bmin2[1]; - float dz2 = bmax2[2] - bmin2[2]; - - if (dx2 < EPSILON || dy2 < EPSILON || dz2 < EPSILON || vcount < 3) - { - float cx = dx2 * 0.5f + bmin2[0]; - float cy = dy2 * 0.5f + bmin2[1]; - float cz = dz2 * 0.5f + bmin2[2]; - - float len = Single.MaxValue; - - if (dx2 >= EPSILON && dx2 < len) - len = dx2; - if (dy2 >= EPSILON && dy2 < len) - len = dy2; - if (dz2 >= EPSILON && dz2 < len) - len = dz2; - - if (len == Single.MaxValue) - { - dx2 = dy2 = dz2 = 0.01f; // one centimeter - } - else - { - if (dx2 < EPSILON) // 1/5th the shortest non-zero edge. - dx2 = len * 0.05f; - if (dy2 < EPSILON) - dy2 = len * 0.05f; - if (dz2 < EPSILON) - dz2 = len * 0.05f; - } - - float x1 = cx - dx2; - float x2 = cx + dx2; - - float y1 = cy - dy2; - float y2 = cy + dy2; - - float z1 = cz - dz2; - float z2 = cz + dz2; - - vcount = 0; // add box - - addPoint(ref vcount, vertices, x1, y1, z1); - addPoint(ref vcount, vertices, x2, y1, z1); - addPoint(ref vcount, vertices, x2, y2, z1); - addPoint(ref vcount, vertices, x1, y2, z1); - addPoint(ref vcount, vertices, x1, y1, z2); - addPoint(ref vcount, vertices, x2, y1, z2); - addPoint(ref vcount, vertices, x2, y2, z2); - addPoint(ref vcount, vertices, x1, y2, z2); - - return true; - } - } - - return true; - } - - private static void BringOutYourDead(List verts, out List overts, List indices) - { - int[] used = new int[verts.Count]; - int ocount = 0; - - overts = new List(); - - for (int i = 0; i < indices.Count; i++) - { - int v = indices[i]; // original array index - - Debug.Assert(v >= 0 && v < verts.Count); - - if (used[v] != 0) // if already remapped - { - indices[i] = used[v] - 1; // index to new array - } - else - { - indices[i] = ocount; // new index mapping - - overts.Add(verts[v]); // copy old vert to new vert array - - ocount++; // increment output vert count - - Debug.Assert(ocount >= 0 && ocount <= verts.Count); - - used[v] = ocount; // assign new index remapping - } - } - } - - public static HullError CreateConvexHull(HullDesc desc, ref HullResult result) - { - HullError ret = HullError.QE_FAIL; - - PHullResult hr = new PHullResult(); - - uint vcount = (uint)desc.Vertices.Count; - if (vcount < 8) - vcount = 8; - - List vsource; - float3 scale = new float3(); - - bool ok = CleanupVertices(desc.Vertices, out vsource, desc.NormalEpsilon, out scale); // normalize point cloud, remove duplicates! - - if (ok) - { - if (true) // scale vertices back to their original size. - { - for (int i = 0; i < vsource.Count; i++) - { - float3 v = vsource[i]; - v.x *= scale[0]; - v.y *= scale[1]; - v.z *= scale[2]; - } - } - - float skinwidth = 0; - if (desc.HasHullFlag(HullFlag.QF_SKIN_WIDTH)) - skinwidth = desc.SkinWidth; - - ok = ComputeHull(vsource, ref hr, (int)desc.MaxVertices, skinwidth); - - if (ok) - { - List vscratch; - BringOutYourDead(hr.Vertices, out vscratch, hr.Indices); - - ret = HullError.QE_OK; - - if (desc.HasHullFlag(HullFlag.QF_TRIANGLES)) // if he wants the results as triangle! - { - result.Polygons = false; - result.Indices = hr.Indices; - result.OutputVertices = vscratch; - } - else - { - result.Polygons = true; - result.OutputVertices = vscratch; - - if (true) - { - List source = hr.Indices; - List dest = new List(); - for (int i = 0; i < hr.Indices.Count / 3; i++) - { - dest.Add(3); - dest.Add(source[i * 3 + 0]); - dest.Add(source[i * 3 + 1]); - dest.Add(source[i * 3 + 2]); - } - - result.Indices = dest; - } - } - } - } - - return ret; - } - } -} diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/LICENSE.txt b/OpenSim/Region/Physics/ConvexDecompositionDotNet/LICENSE.txt deleted file mode 100644 index 714ae89..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/LICENSE.txt +++ /dev/null @@ -1,28 +0,0 @@ -ConvexDecompositionDotNet -------------------------- - -The MIT License - -Copyright (c) 2010 Intel Corporation. -All rights reserved. - -Based on the convexdecomposition library from - 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. diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/Plane.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/Plane.cs deleted file mode 100644 index d099676..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/Plane.cs +++ /dev/null @@ -1,99 +0,0 @@ -/* The MIT License - * - * Copyright (c) 2010 Intel Corporation. - * All rights reserved. - * - * Based on the convexdecomposition library from - * 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)); - } - } -} diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/PlaneTri.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/PlaneTri.cs deleted file mode 100644 index 31f0182..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/PlaneTri.cs +++ /dev/null @@ -1,211 +0,0 @@ -/* The MIT License - * - * Copyright (c) 2010 Intel Corporation. - * All rights reserved. - * - * Based on the convexdecomposition library from - * 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; - } - } -} diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs deleted file mode 100644 index 5ff945d..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("ConvexDecompositionDotNet")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Intel Corporation")] -[assembly: AssemblyProduct("ConvexDecompositionDotNet")] -[assembly: AssemblyCopyright("Copyright © Intel Corporation 2010")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("2a1c9467-1a17-4c8d-bf9f-4b4d86dd0cbb")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.7.5.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/Quaternion.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/Quaternion.cs deleted file mode 100644 index 0ba8f17..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/Quaternion.cs +++ /dev/null @@ -1,209 +0,0 @@ -/* The MIT License - * - * Copyright (c) 2010 Intel Corporation. - * All rights reserved. - * - * Based on the convexdecomposition library from - * 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); - } - } -} diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/README.txt b/OpenSim/Region/Physics/ConvexDecompositionDotNet/README.txt deleted file mode 100644 index fc53ae7..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/README.txt +++ /dev/null @@ -1,7 +0,0 @@ -ConvexDecompositionDotNet -========================= - -A C# port of the ConvexDecomposition library by John W. Ratcliff and Stan Melax. -The original C++ version is available at . -See the blog post at -for a thorough explanation of generating convex hulls from concave meshes. diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/SplitPlane.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/SplitPlane.cs deleted file mode 100644 index 9f06a9a..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/SplitPlane.cs +++ /dev/null @@ -1,265 +0,0 @@ -/* The MIT License - * - * Copyright (c) 2010 Intel Corporation. - * All rights reserved. - * - * Based on the convexdecomposition library from - * 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 vertices, List 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; - } - } - } -} diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/VertexLookup.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/VertexLookup.cs deleted file mode 100644 index 6f17c9f..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/VertexLookup.cs +++ /dev/null @@ -1,70 +0,0 @@ -/* The MIT License - * - * Copyright (c) 2010 Intel Corporation. - * All rights reserved. - * - * Based on the convexdecomposition library from - * 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 mVertices = new List(); - private Dictionary mIndices = new Dictionary(); - - 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 GetVertices() - { - return mVertices; - } - - public void Clear() - { - mVertices.Clear(); - } - } -} diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/float2.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/float2.cs deleted file mode 100644 index ce88fc8..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/float2.cs +++ /dev/null @@ -1,70 +0,0 @@ -/* The MIT License - * - * Copyright (c) 2010 Intel Corporation. - * All rights reserved. - * - * Based on the convexdecomposition library from - * 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); - } - } -} diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/float3.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/float3.cs deleted file mode 100644 index 4389114..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/float3.cs +++ /dev/null @@ -1,444 +0,0 @@ -/* The MIT License - * - * Copyright (c) 2010 Intel Corporation. - * All rights reserved. - * - * Based on the convexdecomposition library from - * 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 - { - 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(); - } -} diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/float3x3.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/float3x3.cs deleted file mode 100644 index 76cf063..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/float3x3.cs +++ /dev/null @@ -1,195 +0,0 @@ -/* The MIT License - * - * Copyright (c) 2010 Intel Corporation. - * All rights reserved. - * - * Based on the convexdecomposition library from - * 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; - } - } -} diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/float4.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/float4.cs deleted file mode 100644 index fa60876..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/float4.cs +++ /dev/null @@ -1,170 +0,0 @@ -/* The MIT License - * - * Copyright (c) 2010 Intel Corporation. - * All rights reserved. - * - * Based on the convexdecomposition library from - * 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); - } - } -} diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/float4x4.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/float4x4.cs deleted file mode 100644 index 7d1592f..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/float4x4.cs +++ /dev/null @@ -1,284 +0,0 @@ -/* The MIT License - * - * Copyright (c) 2010 Intel Corporation. - * All rights reserved. - * - * Based on the convexdecomposition library from - * 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); - } - } -} diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/int3.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/int3.cs deleted file mode 100644 index 9c5760d..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/int3.cs +++ /dev/null @@ -1,128 +0,0 @@ -/* The MIT License - * - * Copyright (c) 2010 Intel Corporation. - * All rights reserved. - * - * Based on the convexdecomposition library from - * 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])); - } - } -} diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/int4.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/int4.cs deleted file mode 100644 index c2b32e5..0000000 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/int4.cs +++ /dev/null @@ -1,66 +0,0 @@ -/* The MIT License - * - * Copyright (c) 2010 Intel Corporation. - * All rights reserved. - * - * Based on the convexdecomposition library from - * 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(); - } - } - } -} diff --git a/OpenSim/Region/Physics/Manager/AssemblyInfo.cs b/OpenSim/Region/Physics/Manager/AssemblyInfo.cs deleted file mode 100644 index 36b4235..0000000 --- a/OpenSim/Region/Physics/Manager/AssemblyInfo.cs +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Reflection; -using System.Runtime.InteropServices; - -// Information about this assembly is defined by the following -// attributes. -// -// change them to the information which is associated with the assembly -// you compile. - -[assembly : AssemblyTitle("PhysicsManager")] -[assembly : AssemblyDescription("")] -[assembly : AssemblyConfiguration("")] -[assembly : AssemblyCompany("http://opensimulator.org")] -[assembly : AssemblyProduct("PhysicsManager")] -[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers")] -[assembly : AssemblyTrademark("")] -[assembly : AssemblyCulture("")] - -// This sets the default COM visibility of types in the assembly to invisible. -// If you need to expose a type to COM, use [ComVisible(true)] on that type. - -[assembly : ComVisible(false)] - -// The assembly version has following format : -// -// Major.Minor.Build.Revision -// -// You can specify all values by your own or you can build default build and revision -// numbers with the '*' character (the default): - -[assembly : AssemblyVersion("0.7.5.*")] diff --git a/OpenSim/Region/Physics/Manager/CollisionLocker.cs b/OpenSim/Region/Physics/Manager/CollisionLocker.cs deleted file mode 100644 index cace4e4..0000000 --- a/OpenSim/Region/Physics/Manager/CollisionLocker.cs +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; - -namespace OpenSim.Region.Physics.Manager -{ - public class CollisionLocker - { - private List worldlock = new List(); - - public CollisionLocker() - { - - } - - public void dlock(IntPtr world) - { - lock (worldlock) - { - worldlock.Add(world); - } - - } - - public void dunlock(IntPtr world) - { - lock (worldlock) - { - worldlock.Remove(world); - } - } - - public bool lockquery() - { - return (worldlock.Count > 0); - } - - public void drelease(IntPtr world) - { - lock (worldlock) - { - if (worldlock.Contains(world)) - worldlock.Remove(world); - } - } - } -} diff --git a/OpenSim/Region/Physics/Manager/IMesher.cs b/OpenSim/Region/Physics/Manager/IMesher.cs deleted file mode 100644 index 10c4bd3..0000000 --- a/OpenSim/Region/Physics/Manager/IMesher.cs +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using OpenSim.Framework; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.Manager -{ - public interface IMesher - { - IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod); - IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical); - IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache); - } - - // Values for level of detail to be passed to the mesher. - // Values origionally chosen for the LOD of sculpties (the sqrt(width*heigth) of sculpt texture) - // Lower level of detail reduces the number of vertices used to represent the meshed shape. - public enum LevelOfDetail - { - High = 32, - Medium = 16, - Low = 8, - VeryLow = 4 - } - - public interface IVertex - { - } - - public interface IMesh - { - List getVertexList(); - int[] getIndexListAsInt(); - int[] getIndexListAsIntLocked(); - float[] getVertexListAsFloatLocked(); - void getIndexListAsPtrToIntArray(out IntPtr indices, out int triStride, out int indexCount); - void getVertexListAsPtrToFloatArray(out IntPtr vertexList, out int vertexStride, out int vertexCount); - void releaseSourceMeshData(); - void releasePinned(); - void Append(IMesh newMesh); - void TransformLinear(float[,] matrix, float[] offset); - } -} diff --git a/OpenSim/Region/Physics/Manager/IPhysicsParameters.cs b/OpenSim/Region/Physics/Manager/IPhysicsParameters.cs deleted file mode 100755 index b8676ba..0000000 --- a/OpenSim/Region/Physics/Manager/IPhysicsParameters.cs +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using OpenSim.Framework; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.Manager -{ - public struct PhysParameterEntry - { - // flags to say to apply to all or no instances (I wish one could put consts into interfaces) - public const uint APPLY_TO_ALL = 0xfffffff3; - public const uint APPLY_TO_NONE = 0xfffffff4; - - // values that denote true and false values - public const float NUMERIC_TRUE = 1f; - public const float NUMERIC_FALSE = 0f; - - public string name; - public string desc; - - public PhysParameterEntry(string n, string d) - { - name = n; - desc = d; - } - } - - // Interface for a physics scene that implements the runtime setting and getting of physics parameters - public interface IPhysicsParameters - { - // Get the list of parameters this physics engine supports - PhysParameterEntry[] GetParameterList(); - - // Set parameter on a specific or all instances. - // Return 'false' if not able to set the parameter. - bool SetPhysicsParameter(string parm, float value, uint localID); - - // Get parameter. - // Return 'false' if not able to get the parameter. - bool GetPhysicsParameter(string parm, out float value); - - // Get parameter from a particular object - // TODO: - // bool GetPhysicsParameter(string parm, out float value, uint localID); - } -} diff --git a/OpenSim/Region/Physics/Manager/NullPhysicsScene.cs b/OpenSim/Region/Physics/Manager/NullPhysicsScene.cs deleted file mode 100644 index 1ccf46d..0000000 --- a/OpenSim/Region/Physics/Manager/NullPhysicsScene.cs +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using System.Reflection; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.Manager -{ - class NullPhysicsScene : PhysicsScene - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private static int m_workIndicator; - - public override void Initialise(IMesher meshmerizer, IConfigSource config) - { - // Does nothing right now - } - - public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) - { - m_log.InfoFormat("[PHYSICS]: NullPhysicsScene : AddAvatar({0})", position); - return PhysicsActor.Null; - } - - public override void RemoveAvatar(PhysicsActor actor) - { - } - - public override void RemovePrim(PhysicsActor prim) - { - } - public override void SetWaterLevel(float baseheight) - { - - } - -/* - public override PhysicsActor AddPrim(Vector3 position, Vector3 size, Quaternion rotation) - { - m_log.InfoFormat("NullPhysicsScene : AddPrim({0},{1})", position, size); - return PhysicsActor.Null; - } -*/ - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, - Vector3 size, Quaternion rotation, bool isPhysical, uint localid) - { - m_log.InfoFormat("[PHYSICS]: NullPhysicsScene : AddPrim({0},{1})", position, size); - return PhysicsActor.Null; - } - - public override void AddPhysicsActorTaint(PhysicsActor prim) - { - } - - public override float Simulate(float timeStep) - { - m_workIndicator = (m_workIndicator + 1) % 10; - - return 0f; - } - - public override void GetResults() - { - m_log.Info("[PHYSICS]: NullPhysicsScene : GetResults()"); - } - - public override void SetTerrain(float[] heightMap) - { - m_log.InfoFormat("[PHYSICS]: NullPhysicsScene : SetTerrain({0} items)", heightMap.Length); - } - - public override void DeleteTerrain() - { - } - - public override bool IsThreaded - { - get { return false; } - } - - public override void Dispose() - { - } - - public override Dictionary GetTopColliders() - { - Dictionary returncolliders = new Dictionary(); - return returncolliders; - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs deleted file mode 100644 index d119791..0000000 --- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs +++ /dev/null @@ -1,567 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using log4net; -using System; -using System.Collections.Generic; -using System.Reflection; -using OpenSim.Framework; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.Manager -{ - public delegate void PositionUpdate(Vector3 position); - public delegate void VelocityUpdate(Vector3 velocity); - public delegate void OrientationUpdate(Quaternion orientation); - - public enum ActorTypes : int - { - Unknown = 0, - Agent = 1, - Prim = 2, - Ground = 3 - } - - public enum PIDHoverType - { - Ground, - GroundAndWater, - Water, - Absolute - } - - public struct ContactPoint - { - public Vector3 Position; - public Vector3 SurfaceNormal; - public float PenetrationDepth; - - public ContactPoint(Vector3 position, Vector3 surfaceNormal, float penetrationDepth) - { - Position = position; - SurfaceNormal = surfaceNormal; - PenetrationDepth = penetrationDepth; - } - } - - /// - /// Used to pass collision information to OnCollisionUpdate listeners. - /// - public class CollisionEventUpdate : EventArgs - { - /// - /// Number of collision events in this update. - /// - public int Count { get { return m_objCollisionList.Count; } } - - public bool CollisionsOnPreviousFrame { get; private set; } - - public Dictionary m_objCollisionList; - - public CollisionEventUpdate(Dictionary objCollisionList) - { - m_objCollisionList = objCollisionList; - } - - public CollisionEventUpdate() - { - m_objCollisionList = new Dictionary(); - } - - public void AddCollider(uint localID, ContactPoint contact) - { - if (!m_objCollisionList.ContainsKey(localID)) - { - m_objCollisionList.Add(localID, contact); - } - else - { - if (m_objCollisionList[localID].PenetrationDepth < contact.PenetrationDepth) - m_objCollisionList[localID] = contact; - } - } - - /// - /// Clear added collision events. - /// - public void Clear() - { - m_objCollisionList.Clear(); - } - } - - public abstract class PhysicsActor - { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - public delegate void RequestTerseUpdate(); - public delegate void CollisionUpdate(EventArgs e); - public delegate void OutOfBounds(Vector3 pos); - -// disable warning: public events -#pragma warning disable 67 - public event PositionUpdate OnPositionUpdate; - public event VelocityUpdate OnVelocityUpdate; - public event OrientationUpdate OnOrientationUpdate; - public event RequestTerseUpdate OnRequestTerseUpdate; - - /// - /// Subscribers to this event must synchronously handle the dictionary of collisions received, since the event - /// object is reused in subsequent physics frames. - /// - public event CollisionUpdate OnCollisionUpdate; - - public event OutOfBounds OnOutOfBounds; -#pragma warning restore 67 - - public static PhysicsActor Null - { - get { return new NullPhysicsActor(); } - } - - public abstract bool Stopped { get; } - - public abstract Vector3 Size { get; set; } - - public abstract PrimitiveBaseShape Shape { set; } - - uint m_baseLocalID; - public virtual uint LocalID - { - set { m_baseLocalID = value; } - get { return m_baseLocalID; } - } - - public abstract bool Grabbed { set; } - - public abstract bool Selected { set; } - - /// - /// Name of this actor. - /// - /// - /// XXX: Bizarrely, this cannot be "Terrain" or "Water" right now unless it really is simulating terrain or - /// water. This is not a problem due to the formatting of names given by prims and avatars. - /// - public string Name { get; protected set; } - - /// - /// This is being used by ODE joint code. - /// - public string SOPName; - - public abstract void CrossingFailure(); - - public abstract void link(PhysicsActor obj); - - public abstract void delink(); - - public abstract void LockAngularMotion(Vector3 axis); - - public virtual void RequestPhysicsterseUpdate() - { - // Make a temporary copy of the event to avoid possibility of - // a race condition if the last subscriber unsubscribes - // immediately after the null check and before the event is raised. - RequestTerseUpdate handler = OnRequestTerseUpdate; - - if (handler != null) - { - handler(); - } - } - - public virtual void RaiseOutOfBounds(Vector3 pos) - { - // Make a temporary copy of the event to avoid possibility of - // a race condition if the last subscriber unsubscribes - // immediately after the null check and before the event is raised. - OutOfBounds handler = OnOutOfBounds; - - if (handler != null) - { - handler(pos); - } - } - - public virtual void SendCollisionUpdate(EventArgs e) - { - CollisionUpdate handler = OnCollisionUpdate; - -// m_log.DebugFormat("[PHYSICS ACTOR]: Sending collision for {0}", LocalID); - - if (handler != null) - handler(e); - } - - public virtual void SetMaterial (int material) - { - } - - /// - /// Position of this actor. - /// - /// - /// Setting this directly moves the actor to a given position. - /// Getting this retrieves the position calculated by physics scene updates, using factors such as velocity and - /// collisions. - /// - public abstract Vector3 Position { get; set; } - - public abstract float Mass { get; } - public abstract Vector3 Force { get; set; } - - public abstract int VehicleType { get; set; } - public abstract void VehicleFloatParam(int param, float value); - public abstract void VehicleVectorParam(int param, Vector3 value); - public abstract void VehicleRotationParam(int param, Quaternion rotation); - public abstract void VehicleFlags(int param, bool remove); - - /// - /// Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more - /// - public abstract void SetVolumeDetect(int param); - - public abstract Vector3 GeometricCenter { get; } - public abstract Vector3 CenterOfMass { get; } - - /// - /// The desired velocity of this actor. - /// - /// - /// Setting this provides a target velocity for physics scene updates. - /// Getting this returns the last set target. Fetch Velocity to get the current velocity. - /// - protected Vector3 m_targetVelocity; - public virtual Vector3 TargetVelocity - { - get { return m_targetVelocity; } - set { - m_targetVelocity = value; - Velocity = m_targetVelocity; - } - } - - public abstract Vector3 Velocity { get; set; } - - public abstract Vector3 Torque { get; set; } - public abstract float CollisionScore { get; set;} - public abstract Vector3 Acceleration { get; set; } - public abstract Quaternion Orientation { get; set; } - public abstract int PhysicsActorType { get; set; } - public abstract bool IsPhysical { get; set; } - public abstract bool Flying { get; set; } - public abstract bool SetAlwaysRun { get; set; } - public abstract bool ThrottleUpdates { get; set; } - public abstract bool IsColliding { get; set; } - public abstract bool CollidingGround { get; set; } - public abstract bool CollidingObj { get; set; } - public abstract bool FloatOnWater { set; } - public abstract Vector3 RotationalVelocity { get; set; } - public abstract bool Kinematic { get; set; } - public abstract float Buoyancy { get; set; } - - // Used for MoveTo - public abstract Vector3 PIDTarget { set; } - public abstract bool PIDActive { set;} - public abstract float PIDTau { set; } - - // Used for llSetHoverHeight and maybe vehicle height - // Hover Height will override MoveTo target's Z - public abstract bool PIDHoverActive { set;} - public abstract float PIDHoverHeight { set;} - public abstract PIDHoverType PIDHoverType { set;} - public abstract float PIDHoverTau { set;} - - // For RotLookAt - public abstract Quaternion APIDTarget { set;} - public abstract bool APIDActive { set;} - public abstract float APIDStrength { set;} - public abstract float APIDDamping { set;} - - public abstract void AddForce(Vector3 force, bool pushforce); - public abstract void AddAngularForce(Vector3 force, bool pushforce); - public abstract void SetMomentum(Vector3 momentum); - public abstract void SubscribeEvents(int ms); - public abstract void UnSubscribeEvents(); - public abstract bool SubscribedEvents(); - } - - public class NullPhysicsActor : PhysicsActor - { - public override bool Stopped - { - get{ return false; } - } - - public override Vector3 Position - { - get { return Vector3.Zero; } - set { return; } - } - - public override bool SetAlwaysRun - { - get { return false; } - set { return; } - } - - public override uint LocalID - { - set { return; } - } - - public override bool Grabbed - { - set { return; } - } - - public override bool Selected - { - set { return; } - } - - public override float Buoyancy - { - get { return 0f; } - set { return; } - } - - public override bool FloatOnWater - { - set { return; } - } - - public override bool CollidingGround - { - get { return false; } - set { return; } - } - - public override bool CollidingObj - { - get { return false; } - set { return; } - } - - public override Vector3 Size - { - get { return Vector3.Zero; } - set { return; } - } - - public override float Mass - { - get { return 0f; } - } - - public override Vector3 Force - { - get { return Vector3.Zero; } - set { return; } - } - - 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) - { - - } - - public override void SetVolumeDetect(int param) - { - - } - - public override void SetMaterial(int material) - { - - } - - public override Vector3 CenterOfMass - { - get { return Vector3.Zero; } - } - - public override Vector3 GeometricCenter - { - get { return Vector3.Zero; } - } - - public override PrimitiveBaseShape Shape - { - set { return; } - } - - public override Vector3 Velocity - { - get { return Vector3.Zero; } - set { return; } - } - - public override Vector3 Torque - { - get { return Vector3.Zero; } - set { return; } - } - - public override float CollisionScore - { - get { return 0f; } - set { } - } - - public override void CrossingFailure() - { - } - - public override Quaternion Orientation - { - get { return Quaternion.Identity; } - set { } - } - - public override Vector3 Acceleration - { - get { return Vector3.Zero; } - set { } - } - - public override bool IsPhysical - { - get { return false; } - set { return; } - } - - public override bool Flying - { - get { return false; } - set { return; } - } - - public override bool ThrottleUpdates - { - get { return false; } - set { return; } - } - - public override bool IsColliding - { - get { return false; } - set { return; } - } - - public override int PhysicsActorType - { - get { return (int) ActorTypes.Unknown; } - set { return; } - } - - public override bool Kinematic - { - get { return true; } - set { return; } - } - - public override void link(PhysicsActor obj) - { - } - - public override void delink() - { - } - - public override void LockAngularMotion(Vector3 axis) - { - } - - public override void AddForce(Vector3 force, bool pushforce) - { - } - - public override void AddAngularForce(Vector3 force, bool pushforce) - { - - } - - public override Vector3 RotationalVelocity - { - get { return Vector3.Zero; } - set { return; } - } - - public override Vector3 PIDTarget { set { return; } } - public override bool PIDActive { set { return; } } - public override float PIDTau { set { return; } } - - public override float PIDHoverHeight { set { return; } } - public override bool PIDHoverActive { set { return; } } - public override PIDHoverType PIDHoverType { set { return; } } - public override float PIDHoverTau { set { return; } } - - 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 SetMomentum(Vector3 momentum) - { - } - - public override void SubscribeEvents(int ms) - { - - } - public override void UnSubscribeEvents() - { - - } - public override bool SubscribedEvents() - { - return false; - } - } -} diff --git a/OpenSim/Region/Physics/Manager/PhysicsJoint.cs b/OpenSim/Region/Physics/Manager/PhysicsJoint.cs deleted file mode 100644 index b685d04..0000000 --- a/OpenSim/Region/Physics/Manager/PhysicsJoint.cs +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using OpenSim.Framework; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.Manager -{ - public enum PhysicsJointType : int - { - Ball = 0, - Hinge = 1 - } - - public class PhysicsJoint - { - public virtual bool IsInPhysicsEngine { get { return false; } } // set internally to indicate if this joint has already been passed to the physics engine or is still pending - public PhysicsJointType Type; - public string RawParams; - public List BodyNames = new List(); - public Vector3 Position; // global coords - public Quaternion Rotation; // global coords - public string ObjectNameInScene; // proxy object in scene that represents the joint position/orientation - public string TrackedBodyName; // body name that this joint is attached to (ObjectNameInScene will follow TrackedBodyName) - public Quaternion LocalRotation; // joint orientation relative to one of the involved bodies, the tracked body - public int ErrorMessageCount; // total # of error messages printed for this joint since its creation. if too many, further error messages are suppressed to prevent flooding. - public const int maxErrorMessages = 100; // no more than this # of error messages will be printed for each joint - } -} diff --git a/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs b/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs deleted file mode 100644 index 8ccfda5..0000000 --- a/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using Nini.Config; -using log4net; -using OpenSim.Framework; - -namespace OpenSim.Region.Physics.Manager -{ - /// - /// Description of MyClass. - /// - public class PhysicsPluginManager - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private Dictionary _PhysPlugins = new Dictionary(); - private Dictionary _MeshPlugins = new Dictionary(); - - /// - /// Constructor. - /// - public PhysicsPluginManager() - { - // Load "plugins", that are hard coded and not existing in form of an external lib, and hence always - // available - IMeshingPlugin plugHard; - plugHard = new ZeroMesherPlugin(); - _MeshPlugins.Add(plugHard.GetName(), plugHard); - - m_log.Info("[PHYSICS]: Added meshing engine: " + plugHard.GetName()); - } - - /// - /// Get a physics scene for the given physics engine and mesher. - /// - /// - /// - /// - /// - public PhysicsScene GetPhysicsScene(string physEngineName, string meshEngineName, IConfigSource config, string regionName) - { - if (String.IsNullOrEmpty(physEngineName)) - { - return PhysicsScene.Null; - } - - if (String.IsNullOrEmpty(meshEngineName)) - { - return PhysicsScene.Null; - } - - IMesher meshEngine = null; - if (_MeshPlugins.ContainsKey(meshEngineName)) - { - m_log.Info("[PHYSICS]: creating meshing engine " + meshEngineName); - meshEngine = _MeshPlugins[meshEngineName].GetMesher(config); - } - else - { - m_log.WarnFormat("[PHYSICS]: couldn't find meshingEngine: {0}", meshEngineName); - throw new ArgumentException(String.Format("couldn't find meshingEngine: {0}", meshEngineName)); - } - - if (_PhysPlugins.ContainsKey(physEngineName)) - { - m_log.Info("[PHYSICS]: creating " + physEngineName); - PhysicsScene result = _PhysPlugins[physEngineName].GetScene(regionName); - result.Initialise(meshEngine, config); - return result; - } - else - { - m_log.WarnFormat("[PHYSICS]: couldn't find physicsEngine: {0}", physEngineName); - throw new ArgumentException(String.Format("couldn't find physicsEngine: {0}", physEngineName)); - } - } - - /// - /// Load all plugins in assemblies at the given path - /// - /// - public void LoadPluginsFromAssemblies(string assembliesPath) - { - // Walk all assemblies (DLLs effectively) and see if they are home - // of a plugin that is of interest for us - string[] pluginFiles = Directory.GetFiles(assembliesPath, "*.dll"); - - for (int i = 0; i < pluginFiles.Length; i++) - { - LoadPluginsFromAssembly(pluginFiles[i]); - } - } - - /// - /// Load plugins from an assembly at the given path - /// - /// - public void LoadPluginsFromAssembly(string assemblyPath) - { - // TODO / NOTE - // The assembly named 'OpenSim.Region.Physics.BasicPhysicsPlugin' was loaded from - // 'file:///C:/OpenSim/trunk2/bin/Physics/OpenSim.Region.Physics.BasicPhysicsPlugin.dll' - // using the LoadFrom context. The use of this context can result in unexpected behavior - // for serialization, casting and dependency resolution. In almost all cases, it is recommended - // that the LoadFrom context be avoided. This can be done by installing assemblies in the - // Global Assembly Cache or in the ApplicationBase directory and using Assembly. - // Load when explicitly loading assemblies. - Assembly pluginAssembly = null; - Type[] types = null; - - try - { - pluginAssembly = Assembly.LoadFrom(assemblyPath); - } - catch (Exception ex) - { - m_log.Error("[PHYSICS]: Failed to load plugin from " + assemblyPath, ex); - } - - if (pluginAssembly != null) - { - try - { - types = pluginAssembly.GetTypes(); - } - catch (ReflectionTypeLoadException ex) - { - m_log.Error("[PHYSICS]: Failed to enumerate types in plugin from " + assemblyPath + ": " + - ex.LoaderExceptions[0].Message, ex); - } - catch (Exception ex) - { - m_log.Error("[PHYSICS]: Failed to enumerate types in plugin from " + assemblyPath, ex); - } - - if (types != null) - { - foreach (Type pluginType in types) - { - if (pluginType.IsPublic) - { - if (!pluginType.IsAbstract) - { - Type physTypeInterface = pluginType.GetInterface("IPhysicsPlugin", true); - - if (physTypeInterface != null) - { - IPhysicsPlugin plug = - (IPhysicsPlugin)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); - plug.Init(); - if (!_PhysPlugins.ContainsKey(plug.GetName())) - { - _PhysPlugins.Add(plug.GetName(), plug); - m_log.Info("[PHYSICS]: Added physics engine: " + plug.GetName()); - } - } - - Type meshTypeInterface = pluginType.GetInterface("IMeshingPlugin", true); - - if (meshTypeInterface != null) - { - IMeshingPlugin plug = - (IMeshingPlugin)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); - if (!_MeshPlugins.ContainsKey(plug.GetName())) - { - _MeshPlugins.Add(plug.GetName(), plug); - m_log.Info("[PHYSICS]: Added meshing engine: " + plug.GetName()); - } - } - - physTypeInterface = null; - meshTypeInterface = null; - } - } - } - } - } - - pluginAssembly = null; - } - - //--- - public static void PhysicsPluginMessage(string message, bool isWarning) - { - if (isWarning) - { - m_log.Warn("[PHYSICS]: " + message); - } - else - { - m_log.Info("[PHYSICS]: " + message); - } - } - - //--- - } - - public interface IPhysicsPlugin - { - bool Init(); - PhysicsScene GetScene(String sceneIdentifier); - string GetName(); - void Dispose(); - } - - public interface IMeshingPlugin - { - string GetName(); - IMesher GetMesher(IConfigSource config); - } -} diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs deleted file mode 100644 index 488900e..0000000 --- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using System.Reflection; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.Manager -{ - public delegate void physicsCrash(); - - public delegate void RaycastCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal); - public delegate void RayCallback(List list); - - public delegate void JointMoved(PhysicsJoint joint); - public delegate void JointDeactivated(PhysicsJoint joint); - public delegate void JointErrorMessage(PhysicsJoint joint, string message); // this refers to an "error message due to a problem", not "amount of joint constraint violation" - - public delegate void RequestAssetDelegate(UUID assetID, AssetReceivedDelegate callback); - public delegate void AssetReceivedDelegate(AssetBase asset); - - /// - /// Contact result from a raycast. - /// - public struct ContactResult - { - public Vector3 Pos; - public float Depth; - public uint ConsumerID; - public Vector3 Normal; - } - - public abstract class PhysicsScene - { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Name of this scene. Useful in debug messages to distinguish one OdeScene instance from another. - /// - public string Name { get; protected set; } - - // The only thing that should register for this event is the SceneGraph - // Anything else could cause problems. - - public event physicsCrash OnPhysicsCrash; - - public static PhysicsScene Null - { - get { return new NullPhysicsScene(); } - } - - public RequestAssetDelegate RequestAssetMethod { get; set; } - - public virtual void TriggerPhysicsBasedRestart() - { - physicsCrash handler = OnPhysicsCrash; - if (handler != null) - { - OnPhysicsCrash(); - } - } - - public abstract void Initialise(IMesher meshmerizer, IConfigSource config); - - /// - /// Add an avatar - /// - /// - /// - /// - /// - /// - public abstract PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying); - - /// - /// Add an avatar - /// - /// - /// - /// - /// - /// - /// - public virtual PhysicsActor AddAvatar(uint localID, string avName, Vector3 position, Vector3 size, bool isFlying) - { - PhysicsActor ret = AddAvatar(avName, position, size, isFlying); - if (ret != null) ret.LocalID = localID; - return ret; - } - - /// - /// Remove an avatar. - /// - /// - public abstract void RemoveAvatar(PhysicsActor actor); - - /// - /// Remove a prim. - /// - /// - public abstract void RemovePrim(PhysicsActor prim); - - public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, - Vector3 size, Quaternion rotation, bool isPhysical, uint localid); - - public virtual float TimeDilation - { - get { return 1.0f; } - } - - public virtual bool SupportsNINJAJoints - { - get { return false; } - } - - public virtual PhysicsJoint RequestJointCreation(string objectNameInScene, PhysicsJointType jointType, Vector3 position, - Quaternion rotation, string parms, List bodyNames, string trackedBodyName, Quaternion localRotation) - { return null; } - - public virtual void RequestJointDeletion(string objectNameInScene) - { return; } - - public virtual void RemoveAllJointsConnectedToActorThreadLocked(PhysicsActor actor) - { return; } - - public virtual void DumpJointInfo() - { return; } - - public event JointMoved OnJointMoved; - - protected virtual void DoJointMoved(PhysicsJoint joint) - { - // We need this to allow subclasses (but not other classes) to invoke the event; C# does - // not allow subclasses to invoke the parent class event. - if (OnJointMoved != null) - { - OnJointMoved(joint); - } - } - - public event JointDeactivated OnJointDeactivated; - - protected virtual void DoJointDeactivated(PhysicsJoint joint) - { - // We need this to allow subclasses (but not other classes) to invoke the event; C# does - // not allow subclasses to invoke the parent class event. - if (OnJointDeactivated != null) - { - OnJointDeactivated(joint); - } - } - - public event JointErrorMessage OnJointErrorMessage; - - protected virtual void DoJointErrorMessage(PhysicsJoint joint, string message) - { - // We need this to allow subclasses (but not other classes) to invoke the event; C# does - // not allow subclasses to invoke the parent class event. - if (OnJointErrorMessage != null) - { - OnJointErrorMessage(joint, message); - } - } - - public virtual Vector3 GetJointAnchor(PhysicsJoint joint) - { return Vector3.Zero; } - - public virtual Vector3 GetJointAxis(PhysicsJoint joint) - { return Vector3.Zero; } - - public abstract void AddPhysicsActorTaint(PhysicsActor prim); - - /// - /// Perform a simulation of the current physics scene over the given timestep. - /// - /// - /// The number of frames simulated over that period. - public abstract float Simulate(float timeStep); - - /// - /// Get statistics about this scene. - /// - /// This facility is currently experimental and subject to change. - /// - /// A dictionary where the key is the statistic name. If no statistics are supplied then returns null. - /// - public virtual Dictionary GetStats() { return null; } - - public abstract void GetResults(); - - public abstract void SetTerrain(float[] heightMap); - - public abstract void SetWaterLevel(float baseheight); - - public abstract void DeleteTerrain(); - - public abstract void Dispose(); - - public abstract Dictionary GetTopColliders(); - - public abstract bool IsThreaded { get; } - - /// - /// True if the physics plugin supports raycasting against the physics scene - /// - public virtual bool SupportsRayCast() - { - return false; - } - - public virtual bool SupportsCombining() - { - return false; - } - - public virtual void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) {} - - public virtual void UnCombine(PhysicsScene pScene) {} - - /// - /// Queue a raycast against the physics scene. - /// The provided callback method will be called when the raycast is complete - /// - /// Many physics engines don't support collision testing at the same time as - /// manipulating the physics scene, so we queue the request up and callback - /// a custom method when the raycast is complete. - /// This allows physics engines that give an immediate result to callback immediately - /// and ones that don't, to callback when it gets a result back. - /// - /// ODE for example will not allow you to change the scene while collision testing or - /// it asserts, 'opteration not valid for locked space'. This includes adding a ray to the scene. - /// - /// This is named RayCastWorld to not conflict with modrex's Raycast method. - /// - /// Origin of the ray - /// Direction of the ray - /// Length of ray in meters - /// Method to call when the raycast is complete - public virtual void RaycastWorld(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod) - { - if (retMethod != null) - retMethod(false, Vector3.Zero, 0, 999999999999f, Vector3.Zero); - } - - public virtual void RaycastWorld(Vector3 position, Vector3 direction, float length, int Count, RayCallback retMethod) - { - if (retMethod != null) - retMethod(new List()); - } - - public virtual List RaycastWorld(Vector3 position, Vector3 direction, float length, int Count) - { - return new List(); - } - } -} diff --git a/OpenSim/Region/Physics/Manager/PhysicsSensor.cs b/OpenSim/Region/Physics/Manager/PhysicsSensor.cs deleted file mode 100644 index f480d71..0000000 --- a/OpenSim/Region/Physics/Manager/PhysicsSensor.cs +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Timers; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.Manager -{ - [Flags] - public enum SenseType : uint - { - NONE = 0, - AGENT = 1, - ACTIVE = 2, - PASSIVE = 3, - SCRIPTED = 4 - } - - public abstract class PhysicsSensor - { - public static PhysicsSensor Null - { - get { return new NullPhysicsSensor(); } - } - public abstract Vector3 Position { get; set; } - public abstract void TimerCallback (object obj, ElapsedEventArgs eea); - public abstract float radianarc {get; set;} - public abstract string targetname {get; set;} - public abstract Guid targetKey{get;set;} - public abstract SenseType sensetype { get;set;} - public abstract float range { get;set;} - public abstract float rateSeconds { get;set;} - } - - public class NullPhysicsSensor : PhysicsSensor - { - public override Vector3 Position - { - get { return Vector3.Zero; } - set { return; } - } - public override void TimerCallback(object obj, ElapsedEventArgs eea) - { - // don't do squat - } - public override float radianarc { get { return 0f; } set { } } - public override string targetname { get { return ""; } set { } } - public override Guid targetKey { get { return Guid.Empty; } set { } } - public override SenseType sensetype { get { return SenseType.NONE; } set { } } - public override float range { get { return 0; } set { } } - public override float rateSeconds { get { return 0; } set { } } - } -} diff --git a/OpenSim/Region/Physics/Manager/PhysicsVector.cs b/OpenSim/Region/Physics/Manager/PhysicsVector.cs deleted file mode 100644 index f60a636..0000000 --- a/OpenSim/Region/Physics/Manager/PhysicsVector.cs +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; - -namespace OpenSim.Region.Physics.Manager -{ - /*public class PhysicsVector - { - public float X; - public float Y; - public float Z; - - public Vector3() - { - } - - public Vector3(float x, float y, float z) - { - X = x; - Y = y; - Z = z; - } - - public Vector3(Vector3 pv) : this(pv.X, pv.Y, pv.Z) - { - } - - public void setValues(float x, float y, float z) - { - X = x; - Y = y; - Z = z; - } - - public static readonly PhysicsVector Zero = new PhysicsVector(0f, 0f, 0f); - - public override string ToString() - { - return "<" + X + "," + Y + "," + Z + ">"; - } - - /// - /// These routines are the easiest way to store XYZ values in an Vector3 without requiring 3 calls. - /// - /// - public byte[] GetBytes() - { - byte[] byteArray = new byte[12]; - - Buffer.BlockCopy(BitConverter.GetBytes(X), 0, byteArray, 0, 4); - Buffer.BlockCopy(BitConverter.GetBytes(Y), 0, byteArray, 4, 4); - Buffer.BlockCopy(BitConverter.GetBytes(Z), 0, byteArray, 8, 4); - - if (!BitConverter.IsLittleEndian) - { - Array.Reverse(byteArray, 0, 4); - Array.Reverse(byteArray, 4, 4); - Array.Reverse(byteArray, 8, 4); - } - - return byteArray; - } - - public void FromBytes(byte[] byteArray, int pos) - { - byte[] conversionBuffer = null; - if (!BitConverter.IsLittleEndian) - { - // Big endian architecture - if (conversionBuffer == null) - conversionBuffer = new byte[12]; - - Buffer.BlockCopy(byteArray, pos, conversionBuffer, 0, 12); - - Array.Reverse(conversionBuffer, 0, 4); - Array.Reverse(conversionBuffer, 4, 4); - Array.Reverse(conversionBuffer, 8, 4); - - X = BitConverter.ToSingle(conversionBuffer, 0); - Y = BitConverter.ToSingle(conversionBuffer, 4); - Z = BitConverter.ToSingle(conversionBuffer, 8); - } - else - { - // Little endian architecture - X = BitConverter.ToSingle(byteArray, pos); - Y = BitConverter.ToSingle(byteArray, pos + 4); - Z = BitConverter.ToSingle(byteArray, pos + 8); - } - } - - // Operations - public static PhysicsVector operator +(Vector3 a, Vector3 b) - { - return new PhysicsVector(a.X + b.X, a.Y + b.Y, a.Z + b.Z); - } - - public static PhysicsVector operator -(Vector3 a, Vector3 b) - { - return new PhysicsVector(a.X - b.X, a.Y - b.Y, a.Z - b.Z); - } - - public static PhysicsVector cross(Vector3 a, Vector3 b) - { - return new PhysicsVector(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 float length() - { - return (float) Math.Sqrt(X*X + Y*Y + Z*Z); - } - - public static float GetDistanceTo(Vector3 a, Vector3 b) - { - float dx = a.X - b.X; - float dy = a.Y - b.Y; - float dz = a.Z - b.Z; - return (float) Math.Sqrt(dx * dx + dy * dy + dz * dz); - } - - public static PhysicsVector operator /(Vector3 v, float f) - { - return new PhysicsVector(v.X/f, v.Y/f, v.Z/f); - } - - public static PhysicsVector operator *(Vector3 v, float f) - { - return new PhysicsVector(v.X*f, v.Y*f, v.Z*f); - } - - public static PhysicsVector operator *(float f, Vector3 v) - { - return v*f; - } - - public static bool isFinite(Vector3 v) - { - if (v == null) - return false; - if (Single.IsInfinity(v.X) || Single.IsNaN(v.X)) - return false; - if (Single.IsInfinity(v.Y) || Single.IsNaN(v.Y)) - return false; - if (Single.IsInfinity(v.Z) || Single.IsNaN(v.Z)) - return false; - - return true; - } - - public virtual bool IsIdentical(Vector3 v, float tolerance) - { - PhysicsVector diff = this - v; - float d = diff.length(); - if (d <= tolerance) - return true; - - return false; - } - - }*/ -} diff --git a/OpenSim/Region/Physics/Manager/VehicleConstants.cs b/OpenSim/Region/Physics/Manager/VehicleConstants.cs deleted file mode 100644 index f0775c1..0000000 --- a/OpenSim/Region/Physics/Manager/VehicleConstants.cs +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; - -namespace OpenSim.Region.Physics.Manager -{ - public enum Vehicle : int - { - /// - /// Turns off Vehicle Support - /// - TYPE_NONE = 0, - - /// - /// No Angular motor, High Left right friction, No Hover, Linear Deflection 1, no angular deflection - /// no vertical attractor, No banking, Identity rotation frame - /// - TYPE_SLED = 1, - - /// - /// Needs Motors to be driven by timer or control events High left/right friction, No angular friction - /// Linear Motor wins in a second, decays in 60 seconds. Angular motor wins in a second, decays in 8/10ths of a second - /// linear deflection 2 seconds - /// Vertical Attractor locked UP - /// - TYPE_CAR = 2, - TYPE_BOAT = 3, - TYPE_AIRPLANE = 4, - TYPE_BALLOON = 5, - LINEAR_FRICTION_TIMESCALE = 16, - /// - /// vector of timescales for exponential decay of angular velocity about three axis - /// - ANGULAR_FRICTION_TIMESCALE = 17, - /// - /// linear velocity vehicle will try for - /// - LINEAR_MOTOR_DIRECTION = 18, - - /// - /// Offset from center of mass where linear motor forces are added - /// - LINEAR_MOTOR_OFFSET = 20, - /// - /// angular velocity that vehicle will try for - /// - ANGULAR_MOTOR_DIRECTION = 19, - HOVER_HEIGHT = 24, - HOVER_EFFICIENCY = 25, - HOVER_TIMESCALE = 26, - BUOYANCY = 27, - LINEAR_DEFLECTION_EFFICIENCY = 28, - LINEAR_DEFLECTION_TIMESCALE = 29, - LINEAR_MOTOR_TIMESCALE = 30, - LINEAR_MOTOR_DECAY_TIMESCALE = 31, - - /// - /// slide between 0 and 1 - /// - ANGULAR_DEFLECTION_EFFICIENCY = 32, - ANGULAR_DEFLECTION_TIMESCALE = 33, - ANGULAR_MOTOR_TIMESCALE = 34, - ANGULAR_MOTOR_DECAY_TIMESCALE = 35, - VERTICAL_ATTRACTION_EFFICIENCY = 36, - VERTICAL_ATTRACTION_TIMESCALE = 37, - BANKING_EFFICIENCY = 38, - BANKING_MIX = 39, - BANKING_TIMESCALE = 40, - REFERENCE_FRAME = 44, - BLOCK_EXIT = 45, - ROLL_FRAME = 46 - - } - - [Flags] - public enum VehicleFlag - { - NO_DEFLECTION_UP = 1, - LIMIT_ROLL_ONLY = 2, - HOVER_WATER_ONLY = 4, - HOVER_TERRAIN_ONLY = 8, - HOVER_GLOBAL_HEIGHT = 16, - HOVER_UP_ONLY = 32, - LIMIT_MOTOR_UP = 64, - MOUSELOOK_STEER = 128, - MOUSELOOK_BANK = 256, - CAMERA_DECOUPLED = 512, - NO_X = 1024, - NO_Y = 2048, - NO_Z = 4096, - LOCK_HOVER_HEIGHT = 8192, - NO_DEFLECTION = 16392, - LOCK_ROTATION = 32784 - } - -} diff --git a/OpenSim/Region/Physics/Manager/ZeroMesher.cs b/OpenSim/Region/Physics/Manager/ZeroMesher.cs deleted file mode 100644 index 270d2ec..0000000 --- a/OpenSim/Region/Physics/Manager/ZeroMesher.cs +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using OpenSim.Framework; -using OpenMetaverse; -using Nini.Config; - -/* - * This is the zero mesher. - * Whatever you want him to mesh, he can't, telling you that by responding with a null pointer. - * Effectivly this is for switching off meshing and for testing as each physics machine should deal - * with the null pointer situation. - * But it's also a convenience thing, as physics machines can rely on having a mesher in any situation, even - * if it's a dump one like this. - * Note, that this mesher is *not* living in a module but in the manager itself, so - * it's always availabe and thus the default in case of configuration errors -*/ - -namespace OpenSim.Region.Physics.Manager -{ - public class ZeroMesherPlugin : IMeshingPlugin - { - public ZeroMesherPlugin() - { - } - - public string GetName() - { - return "ZeroMesher"; - } - - public IMesher GetMesher(IConfigSource config) - { - return new ZeroMesher(); - } - } - - public class ZeroMesher : IMesher - { - public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) - { - return CreateMesh(primName, primShape, size, lod, false, false); - } - - public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) - { - return CreateMesh(primName, primShape, size, lod, false, false); - } - - public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache) - { - // Remove the reference to the encoded JPEG2000 data so it can be GCed - primShape.SculptData = OpenMetaverse.Utils.EmptyBytes; - - return null; - } - } -} diff --git a/OpenSim/Region/Physics/Meshing/HelperTypes.cs b/OpenSim/Region/Physics/Meshing/HelperTypes.cs deleted file mode 100644 index 8cd8dcf..0000000 --- a/OpenSim/Region/Physics/Meshing/HelperTypes.cs +++ /dev/null @@ -1,436 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using OpenMetaverse; -using OpenSim.Region.Physics.Manager; -using OpenSim.Region.Physics.Meshing; - -public class Vertex : IComparable -{ - Vector3 vector; - - public float X - { - get { return vector.X; } - set { vector.X = value; } - } - - public float Y - { - get { return vector.Y; } - set { vector.Y = value; } - } - - public float Z - { - get { return vector.Z; } - set { vector.Z = value; } - } - - public Vertex(float x, float y, float z) - { - vector.X = x; - vector.Y = y; - vector.Z = z; - } - - public Vertex normalize() - { - float tlength = vector.Length(); - if (tlength != 0f) - { - float mul = 1.0f / tlength; - return new Vertex(vector.X * mul, vector.Y * mul, vector.Z * mul); - } - else - { - return new Vertex(0f, 0f, 0f); - } - } - - public Vertex cross(Vertex v) - { - return new Vertex(vector.Y * v.Z - vector.Z * v.Y, vector.Z * v.X - vector.X * v.Z, vector.X * v.Y - vector.Y * v.X); - } - - // disable warning: mono compiler moans about overloading - // operators hiding base operator but should not according to C# - // language spec -#pragma warning disable 0108 - public static Vertex operator *(Vertex v, Quaternion q) - { - // From http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/ - - Vertex v2 = new Vertex(0f, 0f, 0f); - - v2.X = q.W * q.W * v.X + - 2f * q.Y * q.W * v.Z - - 2f * q.Z * q.W * v.Y + - q.X * q.X * v.X + - 2f * q.Y * q.X * v.Y + - 2f * q.Z * q.X * v.Z - - q.Z * q.Z * v.X - - q.Y * q.Y * v.X; - - v2.Y = - 2f * q.X * q.Y * v.X + - q.Y * q.Y * v.Y + - 2f * q.Z * q.Y * v.Z + - 2f * q.W * q.Z * v.X - - q.Z * q.Z * v.Y + - q.W * q.W * v.Y - - 2f * q.X * q.W * v.Z - - q.X * q.X * v.Y; - - v2.Z = - 2f * q.X * q.Z * v.X + - 2f * q.Y * q.Z * v.Y + - q.Z * q.Z * v.Z - - 2f * q.W * q.Y * v.X - - q.Y * q.Y * v.Z + - 2f * q.W * q.X * v.Y - - q.X * q.X * v.Z + - q.W * q.W * v.Z; - - return v2; - } - - public static Vertex operator +(Vertex v1, Vertex v2) - { - return new Vertex(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z); - } - - public static Vertex operator -(Vertex v1, Vertex v2) - { - return new Vertex(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z); - } - - public static Vertex operator *(Vertex v1, Vertex v2) - { - return new Vertex(v1.X * v2.X, v1.Y * v2.Y, v1.Z * v2.Z); - } - - public static Vertex operator +(Vertex v1, float am) - { - v1.X += am; - v1.Y += am; - v1.Z += am; - return v1; - } - - public static Vertex operator -(Vertex v1, float am) - { - v1.X -= am; - v1.Y -= am; - v1.Z -= am; - return v1; - } - - public static Vertex operator *(Vertex v1, float am) - { - v1.X *= am; - v1.Y *= am; - v1.Z *= am; - return v1; - } - - public static Vertex operator /(Vertex v1, float am) - { - if (am == 0f) - { - return new Vertex(0f,0f,0f); - } - float mul = 1.0f / am; - v1.X *= mul; - v1.Y *= mul; - v1.Z *= mul; - return v1; - } -#pragma warning restore 0108 - - - public float dot(Vertex v) - { - return X * v.X + Y * v.Y + Z * v.Z; - } - - public Vertex(Vector3 v) - { - vector = v; - } - - public Vertex Clone() - { - return new Vertex(X, Y, Z); - } - - public static Vertex FromAngle(double angle) - { - return new Vertex((float) Math.Cos(angle), (float) Math.Sin(angle), 0.0f); - } - - public float Length() - { - return vector.Length(); - } - - public virtual bool Equals(Vertex v, float tolerance) - { - Vertex diff = this - v; - float d = diff.Length(); - if (d < tolerance) - return true; - - return false; - } - - - public int CompareTo(Vertex other) - { - if (X < other.X) - return -1; - - if (X > other.X) - return 1; - - if (Y < other.Y) - return -1; - - if (Y > other.Y) - return 1; - - if (Z < other.Z) - return -1; - - if (Z > other.Z) - return 1; - - return 0; - } - - public static bool operator >(Vertex me, Vertex other) - { - return me.CompareTo(other) > 0; - } - - public static bool operator <(Vertex me, Vertex other) - { - return me.CompareTo(other) < 0; - } - - public String ToRaw() - { - // Why this stuff with the number formatter? - // Well, the raw format uses the english/US notation of numbers - // where the "," separates groups of 1000 while the "." marks the border between 1 and 10E-1. - // The german notation uses these characters exactly vice versa! - // The Float.ToString() routine is a localized one, giving different results depending on the country - // settings your machine works with. Unusable for a machine readable file format :-( - NumberFormatInfo nfi = new NumberFormatInfo(); - nfi.NumberDecimalSeparator = "."; - nfi.NumberDecimalDigits = 3; - - String s1 = X.ToString("N2", nfi) + " " + Y.ToString("N2", nfi) + " " + Z.ToString("N2", nfi); - - return s1; - } -} - -public class Triangle -{ - public Vertex v1; - public Vertex v2; - public Vertex v3; - - private float radius_square; - private float cx; - private float cy; - - public Triangle(Vertex _v1, Vertex _v2, Vertex _v3) - { - v1 = _v1; - v2 = _v2; - v3 = _v3; - - CalcCircle(); - } - - public bool isInCircle(float x, float y) - { - float dx, dy; - float dd; - - dx = x - cx; - dy = y - cy; - - dd = dx*dx + dy*dy; - if (dd < radius_square) - return true; - else - return false; - } - - public bool isDegraded() - { - // This means, the vertices of this triangle are somewhat strange. - // They either line up or at least two of them are identical - return (radius_square == 0.0); - } - - private void CalcCircle() - { - // Calculate the center and the radius of a circle given by three points p1, p2, p3 - // It is assumed, that the triangles vertices are already set correctly - double p1x, p2x, p1y, p2y, p3x, p3y; - - // Deviation of this routine: - // A circle has the general equation (M-p)^2=r^2, where M and p are vectors - // this gives us three equations f(p)=r^2, each for one point p1, p2, p3 - // putting respectively two equations together gives two equations - // f(p1)=f(p2) and f(p1)=f(p3) - // bringing all constant terms to one side brings them to the form - // M*v1=c1 resp.M*v2=c2 where v1=(p1-p2) and v2=(p1-p3) (still vectors) - // and c1, c2 are scalars (Naming conventions like the variables below) - // Now using the equations that are formed by the components of the vectors - // and isolate Mx lets you make one equation that only holds My - // The rest is straight forward and eaasy :-) - // - - /* helping variables for temporary results */ - double c1, c2; - double v1x, v1y, v2x, v2y; - - double z, n; - - double rx, ry; - - // Readout the three points, the triangle consists of - p1x = v1.X; - p1y = v1.Y; - - p2x = v2.X; - p2y = v2.Y; - - p3x = v3.X; - p3y = v3.Y; - - /* calc helping values first */ - c1 = (p1x*p1x + p1y*p1y - p2x*p2x - p2y*p2y)/2; - c2 = (p1x*p1x + p1y*p1y - p3x*p3x - p3y*p3y)/2; - - v1x = p1x - p2x; - v1y = p1y - p2y; - - v2x = p1x - p3x; - v2y = p1y - p3y; - - z = (c1*v2x - c2*v1x); - n = (v1y*v2x - v2y*v1x); - - if (n == 0.0) // This is no triangle, i.e there are (at least) two points at the same location - { - radius_square = 0.0f; - return; - } - - cy = (float) (z/n); - - if (v2x != 0.0) - { - cx = (float) ((c2 - v2y*cy)/v2x); - } - else if (v1x != 0.0) - { - cx = (float) ((c1 - v1y*cy)/v1x); - } - else - { - Debug.Assert(false, "Malformed triangle"); /* Both terms zero means nothing good */ - } - - rx = (p1x - cx); - ry = (p1y - cy); - - radius_square = (float) (rx*rx + ry*ry); - } - - public override String ToString() - { - NumberFormatInfo nfi = new NumberFormatInfo(); - nfi.CurrencyDecimalDigits = 2; - nfi.CurrencyDecimalSeparator = "."; - - String s1 = "<" + v1.X.ToString(nfi) + "," + v1.Y.ToString(nfi) + "," + v1.Z.ToString(nfi) + ">"; - String s2 = "<" + v2.X.ToString(nfi) + "," + v2.Y.ToString(nfi) + "," + v2.Z.ToString(nfi) + ">"; - String s3 = "<" + v3.X.ToString(nfi) + "," + v3.Y.ToString(nfi) + "," + v3.Z.ToString(nfi) + ">"; - - return s1 + ";" + s2 + ";" + s3; - } - - public Vector3 getNormal() - { - // Vertices - - // Vectors for edges - Vector3 e1; - Vector3 e2; - - e1 = new Vector3(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z); - e2 = new Vector3(v1.X - v3.X, v1.Y - v3.Y, v1.Z - v3.Z); - - // Cross product for normal - Vector3 n = Vector3.Cross(e1, e2); - - // Length - float l = n.Length(); - - // Normalized "normal" - n = n/l; - - return n; - } - - public void invertNormal() - { - Vertex vt; - vt = v1; - v1 = v2; - v2 = vt; - } - - // Dumps a triangle in the "raw faces" format, blender can import. This is for visualisation and - // debugging purposes - public String ToStringRaw() - { - String output = v1.ToRaw() + " " + v2.ToRaw() + " " + v3.ToRaw(); - return output; - } -} diff --git a/OpenSim/Region/Physics/Meshing/Mesh.cs b/OpenSim/Region/Physics/Meshing/Mesh.cs deleted file mode 100644 index f781ff9..0000000 --- a/OpenSim/Region/Physics/Meshing/Mesh.cs +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Runtime.InteropServices; -using OpenSim.Region.Physics.Manager; -using PrimMesher; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.Meshing -{ - public class Mesh : IMesh - { - private Dictionary m_vertices; - private List m_triangles; - GCHandle m_pinnedVertexes; - GCHandle m_pinnedIndex; - IntPtr m_verticesPtr = IntPtr.Zero; - int m_vertexCount = 0; - IntPtr m_indicesPtr = IntPtr.Zero; - int m_indexCount = 0; - public float[] m_normals; - - public Mesh() - { - m_vertices = new Dictionary(); - m_triangles = new List(); - } - - public Mesh Clone() - { - Mesh result = new Mesh(); - - foreach (Triangle t in m_triangles) - { - result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone())); - } - - return result; - } - - public void Add(Triangle triangle) - { - if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero) - throw new NotSupportedException("Attempt to Add to a pinned Mesh"); - // If a vertex of the triangle is not yet in the vertices list, - // add it and set its index to the current index count - if (!m_vertices.ContainsKey(triangle.v1)) - m_vertices[triangle.v1] = m_vertices.Count; - if (!m_vertices.ContainsKey(triangle.v2)) - m_vertices[triangle.v2] = m_vertices.Count; - if (!m_vertices.ContainsKey(triangle.v3)) - m_vertices[triangle.v3] = m_vertices.Count; - m_triangles.Add(triangle); - } - - public void CalcNormals() - { - int iTriangles = m_triangles.Count; - - this.m_normals = new float[iTriangles * 3]; - - int i = 0; - foreach (Triangle t in m_triangles) - { - float ux, uy, uz; - float vx, vy, vz; - float wx, wy, wz; - - ux = t.v1.X; - uy = t.v1.Y; - uz = t.v1.Z; - - vx = t.v2.X; - vy = t.v2.Y; - vz = t.v2.Z; - - wx = t.v3.X; - wy = t.v3.Y; - wz = t.v3.Z; - - - // Vectors for edges - float e1x, e1y, e1z; - float e2x, e2y, e2z; - - e1x = ux - vx; - e1y = uy - vy; - e1z = uz - vz; - - e2x = ux - wx; - e2y = uy - wy; - e2z = uz - wz; - - - // Cross product for normal - float nx, ny, nz; - nx = e1y * e2z - e1z * e2y; - ny = e1z * e2x - e1x * e2z; - nz = e1x * e2y - e1y * e2x; - - // Length - float l = (float)Math.Sqrt(nx * nx + ny * ny + nz * nz); - float lReciprocal = 1.0f / l; - - // Normalized "normal" - //nx /= l; - //ny /= l; - //nz /= l; - - m_normals[i] = nx * lReciprocal; - m_normals[i + 1] = ny * lReciprocal; - m_normals[i + 2] = nz * lReciprocal; - - i += 3; - } - } - - public List getVertexList() - { - List result = new List(); - foreach (Vertex v in m_vertices.Keys) - { - result.Add(new Vector3(v.X, v.Y, v.Z)); - } - return result; - } - - private float[] getVertexListAsFloat() - { - if (m_vertices == null) - throw new NotSupportedException(); - float[] result = new float[m_vertices.Count * 3]; - foreach (KeyValuePair kvp in m_vertices) - { - Vertex v = kvp.Key; - int i = kvp.Value; - result[3 * i + 0] = v.X; - result[3 * i + 1] = v.Y; - result[3 * i + 2] = v.Z; - } - return result; - } - - public float[] getVertexListAsFloatLocked() - { - if (m_pinnedVertexes.IsAllocated) - return (float[])(m_pinnedVertexes.Target); - - float[] result = getVertexListAsFloat(); - m_pinnedVertexes = GCHandle.Alloc(result, GCHandleType.Pinned); - // Inform the garbage collector of this unmanaged allocation so it can schedule - // the next GC round more intelligently - GC.AddMemoryPressure(Buffer.ByteLength(result)); - - return result; - } - - public void getVertexListAsPtrToFloatArray(out IntPtr vertices, out int vertexStride, out int vertexCount) - { - // A vertex is 3 floats - vertexStride = 3 * sizeof(float); - - // If there isn't an unmanaged array allocated yet, do it now - if (m_verticesPtr == IntPtr.Zero) - { - float[] vertexList = getVertexListAsFloat(); - // Each vertex is 3 elements (floats) - m_vertexCount = vertexList.Length / 3; - int byteCount = m_vertexCount * vertexStride; - m_verticesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount); - System.Runtime.InteropServices.Marshal.Copy(vertexList, 0, m_verticesPtr, m_vertexCount * 3); - } - vertices = m_verticesPtr; - vertexCount = m_vertexCount; - } - - public int[] getIndexListAsInt() - { - if (m_triangles == null) - throw new NotSupportedException(); - int[] result = new int[m_triangles.Count * 3]; - for (int i = 0; i < m_triangles.Count; i++) - { - Triangle t = m_triangles[i]; - result[3 * i + 0] = m_vertices[t.v1]; - result[3 * i + 1] = m_vertices[t.v2]; - result[3 * i + 2] = m_vertices[t.v3]; - } - return result; - } - - /// - /// creates a list of index values that defines triangle faces. THIS METHOD FREES ALL NON-PINNED MESH DATA - /// - /// - public int[] getIndexListAsIntLocked() - { - if (m_pinnedIndex.IsAllocated) - return (int[])(m_pinnedIndex.Target); - - int[] result = getIndexListAsInt(); - m_pinnedIndex = GCHandle.Alloc(result, GCHandleType.Pinned); - // Inform the garbage collector of this unmanaged allocation so it can schedule - // the next GC round more intelligently - GC.AddMemoryPressure(Buffer.ByteLength(result)); - - return result; - } - - public void getIndexListAsPtrToIntArray(out IntPtr indices, out int triStride, out int indexCount) - { - // If there isn't an unmanaged array allocated yet, do it now - if (m_indicesPtr == IntPtr.Zero) - { - int[] indexList = getIndexListAsInt(); - m_indexCount = indexList.Length; - int byteCount = m_indexCount * sizeof(int); - m_indicesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount); - System.Runtime.InteropServices.Marshal.Copy(indexList, 0, m_indicesPtr, m_indexCount); - } - // A triangle is 3 ints (indices) - triStride = 3 * sizeof(int); - indices = m_indicesPtr; - indexCount = m_indexCount; - } - - public void releasePinned() - { - if (m_pinnedVertexes.IsAllocated) - m_pinnedVertexes.Free(); - if (m_pinnedIndex.IsAllocated) - m_pinnedIndex.Free(); - if (m_verticesPtr != IntPtr.Zero) - { - System.Runtime.InteropServices.Marshal.FreeHGlobal(m_verticesPtr); - m_verticesPtr = IntPtr.Zero; - } - if (m_indicesPtr != IntPtr.Zero) - { - System.Runtime.InteropServices.Marshal.FreeHGlobal(m_indicesPtr); - m_indicesPtr = IntPtr.Zero; - } - } - - /// - /// frees up the source mesh data to minimize memory - call this method after calling get*Locked() functions - /// - public void releaseSourceMeshData() - { - m_triangles = null; - m_vertices = null; - } - - public void Append(IMesh newMesh) - { - if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero) - throw new NotSupportedException("Attempt to Append to a pinned Mesh"); - - if (!(newMesh is Mesh)) - return; - - foreach (Triangle t in ((Mesh)newMesh).m_triangles) - Add(t); - } - - // Do a linear transformation of mesh. - public void TransformLinear(float[,] matrix, float[] offset) - { - if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero) - throw new NotSupportedException("Attempt to TransformLinear a pinned Mesh"); - - foreach (Vertex v in m_vertices.Keys) - { - if (v == null) - continue; - float x, y, z; - x = v.X*matrix[0, 0] + v.Y*matrix[1, 0] + v.Z*matrix[2, 0]; - y = v.X*matrix[0, 1] + v.Y*matrix[1, 1] + v.Z*matrix[2, 1]; - z = v.X*matrix[0, 2] + v.Y*matrix[1, 2] + v.Z*matrix[2, 2]; - v.X = x + offset[0]; - v.Y = y + offset[1]; - v.Z = z + offset[2]; - } - } - - public void DumpRaw(String path, String name, String title) - { - if (path == null) - return; - String fileName = name + "_" + title + ".raw"; - String completePath = System.IO.Path.Combine(path, fileName); - StreamWriter sw = new StreamWriter(completePath); - foreach (Triangle t in m_triangles) - { - String s = t.ToStringRaw(); - sw.WriteLine(s); - } - sw.Close(); - } - - public void TrimExcess() - { - m_triangles.TrimExcess(); - } - } -} diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs deleted file mode 100644 index 8145d61..0000000 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ /dev/null @@ -1,761 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -//#define SPAM - -using System; -using System.Collections.Generic; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; -using OpenMetaverse; -using OpenMetaverse.StructuredData; -using System.Drawing; -using System.Drawing.Imaging; -using System.IO.Compression; -using PrimMesher; -using log4net; -using Nini.Config; -using System.Reflection; -using System.IO; -using ComponentAce.Compression.Libs.zlib; - -namespace OpenSim.Region.Physics.Meshing -{ - public class MeshmerizerPlugin : IMeshingPlugin - { - public MeshmerizerPlugin() - { - } - - public string GetName() - { - return "Meshmerizer"; - } - - public IMesher GetMesher(IConfigSource config) - { - return new Meshmerizer(config); - } - } - - public class Meshmerizer : IMesher - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - // Setting baseDir to a path will enable the dumping of raw files - // raw files can be imported by blender so a visual inspection of the results can be done -#if SPAM - const string baseDir = "rawFiles"; -#else - private const string baseDir = null; //"rawFiles"; -#endif - - private bool cacheSculptMaps = true; - private string decodedSculptMapPath = null; - private bool useMeshiesPhysicsMesh = false; - - private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh - - private Dictionary m_uniqueMeshes = new Dictionary(); - - public Meshmerizer(IConfigSource config) - { - IConfig start_config = config.Configs["Startup"]; - IConfig mesh_config = config.Configs["Mesh"]; - - decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); - cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); - if(mesh_config != null) - useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); - - try - { - if (!Directory.Exists(decodedSculptMapPath)) - Directory.CreateDirectory(decodedSculptMapPath); - } - catch (Exception e) - { - m_log.WarnFormat("[SCULPT]: Unable to create {0} directory: ", decodedSculptMapPath, e.Message); - } - } - - /// - /// creates a simple box mesh of the specified size. This mesh is of very low vertex count and may - /// be useful as a backup proxy when level of detail is not needed or when more complex meshes fail - /// for some reason - /// - /// - /// - /// - /// - /// - /// - /// - private static Mesh CreateSimpleBoxMesh(float minX, float maxX, float minY, float maxY, float minZ, float maxZ) - { - Mesh box = new Mesh(); - List vertices = new List(); - // bottom - - vertices.Add(new Vertex(minX, maxY, minZ)); - vertices.Add(new Vertex(maxX, maxY, minZ)); - vertices.Add(new Vertex(maxX, minY, minZ)); - vertices.Add(new Vertex(minX, minY, minZ)); - - box.Add(new Triangle(vertices[0], vertices[1], vertices[2])); - box.Add(new Triangle(vertices[0], vertices[2], vertices[3])); - - // top - - vertices.Add(new Vertex(maxX, maxY, maxZ)); - vertices.Add(new Vertex(minX, maxY, maxZ)); - vertices.Add(new Vertex(minX, minY, maxZ)); - vertices.Add(new Vertex(maxX, minY, maxZ)); - - box.Add(new Triangle(vertices[4], vertices[5], vertices[6])); - box.Add(new Triangle(vertices[4], vertices[6], vertices[7])); - - // sides - - box.Add(new Triangle(vertices[5], vertices[0], vertices[3])); - box.Add(new Triangle(vertices[5], vertices[3], vertices[6])); - - box.Add(new Triangle(vertices[1], vertices[0], vertices[5])); - box.Add(new Triangle(vertices[1], vertices[5], vertices[4])); - - box.Add(new Triangle(vertices[7], vertices[1], vertices[4])); - box.Add(new Triangle(vertices[7], vertices[2], vertices[1])); - - box.Add(new Triangle(vertices[3], vertices[2], vertices[7])); - box.Add(new Triangle(vertices[3], vertices[7], vertices[6])); - - return box; - } - - /// - /// Creates a simple bounding box mesh for a complex input mesh - /// - /// - /// - private static Mesh CreateBoundingBoxMesh(Mesh meshIn) - { - float minX = float.MaxValue; - float maxX = float.MinValue; - float minY = float.MaxValue; - float maxY = float.MinValue; - float minZ = float.MaxValue; - float maxZ = float.MinValue; - - foreach (Vector3 v in meshIn.getVertexList()) - { - if (v.X < minX) minX = v.X; - if (v.Y < minY) minY = v.Y; - if (v.Z < minZ) minZ = v.Z; - - if (v.X > maxX) maxX = v.X; - if (v.Y > maxY) maxY = v.Y; - if (v.Z > maxZ) maxZ = v.Z; - } - - return CreateSimpleBoxMesh(minX, maxX, minY, maxY, minZ, maxZ); - } - - private void ReportPrimError(string message, string primName, PrimMesh primMesh) - { - m_log.Error(message); - m_log.Error("\nPrim Name: " + primName); - m_log.Error("****** PrimMesh Parameters ******\n" + primMesh.ParamsToDisplayString()); - } - - /// - /// Add a submesh to an existing list of coords and faces. - /// - /// - /// Size of entire object - /// - /// - private void AddSubMesh(OSDMap subMeshData, Vector3 size, List coords, List faces) - { - // Console.WriteLine("subMeshMap for {0} - {1}", primName, Util.GetFormattedXml((OSD)subMeshMap)); - - // As per http://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format, some Mesh Level - // of Detail Blocks (maps) contain just a NoGeometry key to signal there is no - // geometry for this submesh. - if (subMeshData.ContainsKey("NoGeometry") && ((OSDBoolean)subMeshData["NoGeometry"])) - return; - - OpenMetaverse.Vector3 posMax = ((OSDMap)subMeshData["PositionDomain"])["Max"].AsVector3(); - OpenMetaverse.Vector3 posMin = ((OSDMap)subMeshData["PositionDomain"])["Min"].AsVector3(); - ushort faceIndexOffset = (ushort)coords.Count; - - byte[] posBytes = subMeshData["Position"].AsBinary(); - for (int i = 0; i < posBytes.Length; i += 6) - { - ushort uX = Utils.BytesToUInt16(posBytes, i); - ushort uY = Utils.BytesToUInt16(posBytes, i + 2); - ushort uZ = Utils.BytesToUInt16(posBytes, i + 4); - - Coord c = new Coord( - Utils.UInt16ToFloat(uX, posMin.X, posMax.X) * size.X, - Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y) * size.Y, - Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z) * size.Z); - - coords.Add(c); - } - - byte[] triangleBytes = subMeshData["TriangleList"].AsBinary(); - for (int i = 0; i < triangleBytes.Length; i += 6) - { - ushort v1 = (ushort)(Utils.BytesToUInt16(triangleBytes, i) + faceIndexOffset); - ushort v2 = (ushort)(Utils.BytesToUInt16(triangleBytes, i + 2) + faceIndexOffset); - ushort v3 = (ushort)(Utils.BytesToUInt16(triangleBytes, i + 4) + faceIndexOffset); - Face f = new Face(v1, v2, v3); - faces.Add(f); - } - } - - /// - /// Create a physics mesh from data that comes with the prim. The actual data used depends on the prim type. - /// - /// - /// - /// - /// - /// - private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, Vector3 size, float lod) - { -// m_log.DebugFormat( -// "[MESH]: Creating physics proxy for {0}, shape {1}", -// primName, (OpenMetaverse.SculptType)primShape.SculptType); - - List coords; - List faces; - - if (primShape.SculptEntry) - { - if (((OpenMetaverse.SculptType)primShape.SculptType) == SculptType.Mesh) - { - if (!useMeshiesPhysicsMesh) - return null; - - if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, size, out coords, out faces)) - return null; - } - else - { - if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, out coords, out faces)) - return null; - } - } - else - { - if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces)) - return null; - } - - // Remove the reference to any JPEG2000 sculpt data so it can be GCed - primShape.SculptData = Utils.EmptyBytes; - - int numCoords = coords.Count; - int numFaces = faces.Count; - - // Create the list of vertices - List vertices = new List(); - for (int i = 0; i < numCoords; i++) - { - Coord c = coords[i]; - vertices.Add(new Vertex(c.X, c.Y, c.Z)); - } - - Mesh mesh = new Mesh(); - // Add the corresponding triangles to the mesh - for (int i = 0; i < numFaces; i++) - { - Face f = faces[i]; - mesh.Add(new Triangle(vertices[f.v1], vertices[f.v2], vertices[f.v3])); - } - - return mesh; - } - - /// - /// Generate the co-ords and faces necessary to construct a mesh from the mesh data the accompanies a prim. - /// - /// - /// - /// - /// Coords are added to this list by the method. - /// Faces are added to this list by the method. - /// true if coords and faces were successfully generated, false if not - private bool GenerateCoordsAndFacesFromPrimMeshData( - string primName, PrimitiveBaseShape primShape, Vector3 size, out List coords, out List faces) - { -// m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName); - - coords = new List(); - faces = new List(); - OSD meshOsd = null; - - if (primShape.SculptData.Length <= 0) - { - // XXX: At the moment we can not log here since ODEPrim, for instance, ends up triggering this - // method twice - once before it has loaded sculpt data from the asset service and once afterwards. - // The first time will always call with unloaded SculptData if this needs to be uploaded. -// m_log.ErrorFormat("[MESH]: asset data for {0} is zero length", primName); - return false; - } - - long start = 0; - using (MemoryStream data = new MemoryStream(primShape.SculptData)) - { - try - { - OSD osd = OSDParser.DeserializeLLSDBinary(data); - if (osd is OSDMap) - meshOsd = (OSDMap)osd; - else - { - m_log.Warn("[Mesh}: unable to cast mesh asset to OSDMap"); - return false; - } - } - catch (Exception e) - { - m_log.Error("[MESH]: Exception deserializing mesh asset header:" + e.ToString()); - } - - start = data.Position; - } - - if (meshOsd is OSDMap) - { - OSDMap physicsParms = null; - OSDMap map = (OSDMap)meshOsd; - if (map.ContainsKey("physics_shape")) - physicsParms = (OSDMap)map["physics_shape"]; // old asset format - else if (map.ContainsKey("physics_mesh")) - physicsParms = (OSDMap)map["physics_mesh"]; // new asset format - - if (physicsParms == null) - { - m_log.WarnFormat("[MESH]: No recognized physics mesh found in mesh asset for {0}", primName); - return false; - } - - int physOffset = physicsParms["offset"].AsInteger() + (int)start; - int physSize = physicsParms["size"].AsInteger(); - - if (physOffset < 0 || physSize == 0) - return false; // no mesh data in asset - - OSD decodedMeshOsd = new OSD(); - byte[] meshBytes = new byte[physSize]; - System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize); -// byte[] decompressed = new byte[physSize * 5]; - try - { - using (MemoryStream inMs = new MemoryStream(meshBytes)) - { - using (MemoryStream outMs = new MemoryStream()) - { - using (ZOutputStream zOut = new ZOutputStream(outMs)) - { - byte[] readBuffer = new byte[2048]; - int readLen = 0; - while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0) - { - zOut.Write(readBuffer, 0, readLen); - } - zOut.Flush(); - outMs.Seek(0, SeekOrigin.Begin); - - byte[] decompressedBuf = outMs.GetBuffer(); - - decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf); - } - } - } - } - catch (Exception e) - { - m_log.Error("[MESH]: exception decoding physical mesh: " + e.ToString()); - return false; - } - - OSDArray decodedMeshOsdArray = null; - - // physics_shape is an array of OSDMaps, one for each submesh - if (decodedMeshOsd is OSDArray) - { -// Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd)); - - decodedMeshOsdArray = (OSDArray)decodedMeshOsd; - foreach (OSD subMeshOsd in decodedMeshOsdArray) - { - if (subMeshOsd is OSDMap) - AddSubMesh(subMeshOsd as OSDMap, size, coords, faces); - } - } - } - - return true; - } - - /// - /// Generate the co-ords and faces necessary to construct a mesh from the sculpt data the accompanies a prim. - /// - /// - /// - /// - /// - /// Coords are added to this list by the method. - /// Faces are added to this list by the method. - /// true if coords and faces were successfully generated, false if not - private bool GenerateCoordsAndFacesFromPrimSculptData( - string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, out List coords, out List faces) - { - coords = new List(); - faces = new List(); - PrimMesher.SculptMesh sculptMesh; - Image idata = null; - string decodedSculptFileName = ""; - - if (cacheSculptMaps && primShape.SculptTexture != UUID.Zero) - { - decodedSculptFileName = System.IO.Path.Combine(decodedSculptMapPath, "smap_" + primShape.SculptTexture.ToString()); - try - { - if (File.Exists(decodedSculptFileName)) - { - idata = Image.FromFile(decodedSculptFileName); - } - } - catch (Exception e) - { - m_log.Error("[SCULPT]: unable to load cached sculpt map " + decodedSculptFileName + " " + e.Message); - - } - //if (idata != null) - // m_log.Debug("[SCULPT]: loaded cached map asset for map ID: " + primShape.SculptTexture.ToString()); - } - - if (idata == null) - { - if (primShape.SculptData == null || primShape.SculptData.Length == 0) - return false; - - try - { - OpenMetaverse.Imaging.ManagedImage unusedData; - OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata); - - if (idata == null) - { - // In some cases it seems that the decode can return a null bitmap without throwing - // an exception - m_log.WarnFormat("[PHYSICS]: OpenJPEG decoded sculpt data for {0} to a null bitmap. Ignoring.", primName); - - return false; - } - - unusedData = null; - - //idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData); - - if (cacheSculptMaps) - { - try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); } - catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); } - } - } - catch (DllNotFoundException) - { - m_log.Error("[PHYSICS]: OpenJpeg is not installed correctly on this system. Physics Proxy generation failed. Often times this is because of an old version of GLIBC. You must have version 2.4 or above!"); - return false; - } - catch (IndexOutOfRangeException) - { - m_log.Error("[PHYSICS]: OpenJpeg was unable to decode this. Physics Proxy generation failed"); - return false; - } - catch (Exception ex) - { - m_log.Error("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed: " + ex.Message); - return false; - } - } - - PrimMesher.SculptMesh.SculptType sculptType; - switch ((OpenMetaverse.SculptType)primShape.SculptType) - { - case OpenMetaverse.SculptType.Cylinder: - sculptType = PrimMesher.SculptMesh.SculptType.cylinder; - break; - case OpenMetaverse.SculptType.Plane: - sculptType = PrimMesher.SculptMesh.SculptType.plane; - break; - case OpenMetaverse.SculptType.Torus: - sculptType = PrimMesher.SculptMesh.SculptType.torus; - break; - case OpenMetaverse.SculptType.Sphere: - sculptType = PrimMesher.SculptMesh.SculptType.sphere; - break; - default: - sculptType = PrimMesher.SculptMesh.SculptType.plane; - break; - } - - bool mirror = ((primShape.SculptType & 128) != 0); - bool invert = ((primShape.SculptType & 64) != 0); - - sculptMesh = new PrimMesher.SculptMesh((Bitmap)idata, sculptType, (int)lod, false, mirror, invert); - - idata.Dispose(); - - sculptMesh.DumpRaw(baseDir, primName, "primMesh"); - - sculptMesh.Scale(size.X, size.Y, size.Z); - - coords = sculptMesh.coords; - faces = sculptMesh.faces; - - return true; - } - - /// - /// Generate the co-ords and faces necessary to construct a mesh from the shape data the accompanies a prim. - /// - /// - /// - /// - /// Coords are added to this list by the method. - /// Faces are added to this list by the method. - /// true if coords and faces were successfully generated, false if not - private bool GenerateCoordsAndFacesFromPrimShapeData( - string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, out List coords, out List faces) - { - PrimMesh primMesh; - coords = new List(); - faces = new List(); - - float pathShearX = primShape.PathShearX < 128 ? (float)primShape.PathShearX * 0.01f : (float)(primShape.PathShearX - 256) * 0.01f; - float pathShearY = primShape.PathShearY < 128 ? (float)primShape.PathShearY * 0.01f : (float)(primShape.PathShearY - 256) * 0.01f; - float pathBegin = (float)primShape.PathBegin * 2.0e-5f; - float pathEnd = 1.0f - (float)primShape.PathEnd * 2.0e-5f; - float pathScaleX = (float)(primShape.PathScaleX - 100) * 0.01f; - float pathScaleY = (float)(primShape.PathScaleY - 100) * 0.01f; - - float profileBegin = (float)primShape.ProfileBegin * 2.0e-5f; - float profileEnd = 1.0f - (float)primShape.ProfileEnd * 2.0e-5f; - float profileHollow = (float)primShape.ProfileHollow * 2.0e-5f; - if (profileHollow > 0.95f) - profileHollow = 0.95f; - - int sides = 4; - LevelOfDetail iLOD = (LevelOfDetail)lod; - if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) - sides = 3; - else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) - { - switch (iLOD) - { - case LevelOfDetail.High: sides = 24; break; - case LevelOfDetail.Medium: sides = 12; break; - case LevelOfDetail.Low: sides = 6; break; - case LevelOfDetail.VeryLow: sides = 3; break; - default: sides = 24; break; - } - } - else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) - { // half circle, prim is a sphere - switch (iLOD) - { - case LevelOfDetail.High: sides = 24; break; - case LevelOfDetail.Medium: sides = 12; break; - case LevelOfDetail.Low: sides = 6; break; - case LevelOfDetail.VeryLow: sides = 3; break; - default: sides = 24; break; - } - - profileBegin = 0.5f * profileBegin + 0.5f; - profileEnd = 0.5f * profileEnd + 0.5f; - } - - int hollowSides = sides; - if (primShape.HollowShape == HollowShape.Circle) - { - switch (iLOD) - { - case LevelOfDetail.High: hollowSides = 24; break; - case LevelOfDetail.Medium: hollowSides = 12; break; - case LevelOfDetail.Low: hollowSides = 6; break; - case LevelOfDetail.VeryLow: hollowSides = 3; break; - default: hollowSides = 24; break; - } - } - else if (primShape.HollowShape == HollowShape.Square) - hollowSides = 4; - else if (primShape.HollowShape == HollowShape.Triangle) - hollowSides = 3; - - primMesh = new PrimMesh(sides, profileBegin, profileEnd, profileHollow, hollowSides); - - if (primMesh.errorMessage != null) - if (primMesh.errorMessage.Length > 0) - m_log.Error("[ERROR] " + primMesh.errorMessage); - - primMesh.topShearX = pathShearX; - primMesh.topShearY = pathShearY; - primMesh.pathCutBegin = pathBegin; - primMesh.pathCutEnd = pathEnd; - - if (primShape.PathCurve == (byte)Extrusion.Straight || primShape.PathCurve == (byte) Extrusion.Flexible) - { - primMesh.twistBegin = primShape.PathTwistBegin * 18 / 10; - primMesh.twistEnd = primShape.PathTwist * 18 / 10; - primMesh.taperX = pathScaleX; - primMesh.taperY = pathScaleY; - - if (profileBegin < 0.0f || profileBegin >= profileEnd || profileEnd > 1.0f) - { - ReportPrimError("*** CORRUPT PRIM!! ***", primName, primMesh); - if (profileBegin < 0.0f) profileBegin = 0.0f; - if (profileEnd > 1.0f) profileEnd = 1.0f; - } -#if SPAM - m_log.Debug("****** PrimMesh Parameters (Linear) ******\n" + primMesh.ParamsToDisplayString()); -#endif - try - { - primMesh.ExtrudeLinear(); - } - catch (Exception ex) - { - ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh); - return false; - } - } - else - { - primMesh.holeSizeX = (200 - primShape.PathScaleX) * 0.01f; - primMesh.holeSizeY = (200 - primShape.PathScaleY) * 0.01f; - primMesh.radius = 0.01f * primShape.PathRadiusOffset; - primMesh.revolutions = 1.0f + 0.015f * primShape.PathRevolutions; - primMesh.skew = 0.01f * primShape.PathSkew; - primMesh.twistBegin = primShape.PathTwistBegin * 36 / 10; - primMesh.twistEnd = primShape.PathTwist * 36 / 10; - primMesh.taperX = primShape.PathTaperX * 0.01f; - primMesh.taperY = primShape.PathTaperY * 0.01f; - - if (profileBegin < 0.0f || profileBegin >= profileEnd || profileEnd > 1.0f) - { - ReportPrimError("*** CORRUPT PRIM!! ***", primName, primMesh); - if (profileBegin < 0.0f) profileBegin = 0.0f; - if (profileEnd > 1.0f) profileEnd = 1.0f; - } -#if SPAM - m_log.Debug("****** PrimMesh Parameters (Circular) ******\n" + primMesh.ParamsToDisplayString()); -#endif - try - { - primMesh.ExtrudeCircular(); - } - catch (Exception ex) - { - ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh); - return false; - } - } - - primMesh.DumpRaw(baseDir, primName, "primMesh"); - - primMesh.Scale(size.X, size.Y, size.Z); - - coords = primMesh.coords; - faces = primMesh.faces; - - return true; - } - - public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) - { - return CreateMesh(primName, primShape, size, lod, false, true); - } - - public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) - { - return CreateMesh(primName, primShape, size, lod, isPhysical, true); - } - - public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache) - { -#if SPAM - m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName); -#endif - - Mesh mesh = null; - ulong key = 0; - - // If this mesh has been created already, return it instead of creating another copy - // For large regions with 100k+ prims and hundreds of copies of each, this can save a GB or more of memory - if (shouldCache) - { - key = primShape.GetMeshKey(size, lod); - if (m_uniqueMeshes.TryGetValue(key, out mesh)) - return mesh; - } - - if (size.X < 0.01f) size.X = 0.01f; - if (size.Y < 0.01f) size.Y = 0.01f; - if (size.Z < 0.01f) size.Z = 0.01f; - - mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod); - - if (mesh != null) - { - if ((!isPhysical) && size.X < minSizeForComplexMesh && size.Y < minSizeForComplexMesh && size.Z < minSizeForComplexMesh) - { -#if SPAM - m_log.Debug("Meshmerizer: prim " + primName + " has a size of " + size.ToString() + " which is below threshold of " + - minSizeForComplexMesh.ToString() + " - creating simple bounding box"); -#endif - mesh = CreateBoundingBoxMesh(mesh); - mesh.DumpRaw(baseDir, primName, "Z extruded"); - } - - // trim the vertex and triangle lists to free up memory - mesh.TrimExcess(); - - if (shouldCache) - { - m_uniqueMeshes.Add(key, mesh); - } - } - - return mesh; - } - } -} diff --git a/OpenSim/Region/Physics/Meshing/PrimMesher.cs b/OpenSim/Region/Physics/Meshing/PrimMesher.cs deleted file mode 100644 index 4049ee1..0000000 --- a/OpenSim/Region/Physics/Meshing/PrimMesher.cs +++ /dev/null @@ -1,2324 +0,0 @@ -/* - * Copyright (c) Contributors - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using System.IO; - -namespace PrimMesher -{ - public struct Quat - { - /// X value - public float X; - /// Y value - public float Y; - /// Z value - public float Z; - /// W value - public float W; - - public Quat(float x, float y, float z, float w) - { - X = x; - Y = y; - Z = z; - W = w; - } - - public Quat(Coord axis, float angle) - { - axis = axis.Normalize(); - - angle *= 0.5f; - float c = (float)Math.Cos(angle); - float s = (float)Math.Sin(angle); - - X = axis.X * s; - Y = axis.Y * s; - Z = axis.Z * s; - W = c; - - Normalize(); - } - - public float Length() - { - return (float)Math.Sqrt(X * X + Y * Y + Z * Z + W * W); - } - - public Quat Normalize() - { - const float MAG_THRESHOLD = 0.0000001f; - float mag = Length(); - - // Catch very small rounding errors when normalizing - if (mag > MAG_THRESHOLD) - { - float oomag = 1f / mag; - X *= oomag; - Y *= oomag; - Z *= oomag; - W *= oomag; - } - else - { - X = 0f; - Y = 0f; - Z = 0f; - W = 1f; - } - - return this; - } - - public static Quat operator *(Quat q1, Quat q2) - { - float x = q1.W * q2.X + q1.X * q2.W + q1.Y * q2.Z - q1.Z * q2.Y; - float y = q1.W * q2.Y - q1.X * q2.Z + q1.Y * q2.W + q1.Z * q2.X; - float z = q1.W * q2.Z + q1.X * q2.Y - q1.Y * q2.X + q1.Z * q2.W; - float w = q1.W * q2.W - q1.X * q2.X - q1.Y * q2.Y - q1.Z * q2.Z; - return new Quat(x, y, z, w); - } - - public override string ToString() - { - return "< X: " + this.X.ToString() + ", Y: " + this.Y.ToString() + ", Z: " + this.Z.ToString() + ", W: " + this.W.ToString() + ">"; - } - } - - public struct Coord - { - public float X; - public float Y; - public float Z; - - public Coord(float x, float y, float z) - { - this.X = x; - this.Y = y; - this.Z = z; - } - - public float Length() - { - return (float)Math.Sqrt(this.X * this.X + this.Y * this.Y + this.Z * this.Z); - } - - public Coord Invert() - { - this.X = -this.X; - this.Y = -this.Y; - this.Z = -this.Z; - - return this; - } - - public Coord Normalize() - { - const float MAG_THRESHOLD = 0.0000001f; - float mag = Length(); - - // Catch very small rounding errors when normalizing - if (mag > MAG_THRESHOLD) - { - float oomag = 1.0f / mag; - this.X *= oomag; - this.Y *= oomag; - this.Z *= oomag; - } - else - { - this.X = 0.0f; - this.Y = 0.0f; - this.Z = 0.0f; - } - - return this; - } - - public override string ToString() - { - return this.X.ToString() + " " + this.Y.ToString() + " " + this.Z.ToString(); - } - - public static Coord Cross(Coord c1, Coord c2) - { - return new Coord( - c1.Y * c2.Z - c2.Y * c1.Z, - c1.Z * c2.X - c2.Z * c1.X, - c1.X * c2.Y - c2.X * c1.Y - ); - } - - public static Coord operator +(Coord v, Coord a) - { - return new Coord(v.X + a.X, v.Y + a.Y, v.Z + a.Z); - } - - public static Coord operator *(Coord v, Coord m) - { - return new Coord(v.X * m.X, v.Y * m.Y, v.Z * m.Z); - } - - public static Coord operator *(Coord v, Quat q) - { - // From http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/ - - Coord c2 = new Coord(0.0f, 0.0f, 0.0f); - - c2.X = q.W * q.W * v.X + - 2f * q.Y * q.W * v.Z - - 2f * q.Z * q.W * v.Y + - q.X * q.X * v.X + - 2f * q.Y * q.X * v.Y + - 2f * q.Z * q.X * v.Z - - q.Z * q.Z * v.X - - q.Y * q.Y * v.X; - - c2.Y = - 2f * q.X * q.Y * v.X + - q.Y * q.Y * v.Y + - 2f * q.Z * q.Y * v.Z + - 2f * q.W * q.Z * v.X - - q.Z * q.Z * v.Y + - q.W * q.W * v.Y - - 2f * q.X * q.W * v.Z - - q.X * q.X * v.Y; - - c2.Z = - 2f * q.X * q.Z * v.X + - 2f * q.Y * q.Z * v.Y + - q.Z * q.Z * v.Z - - 2f * q.W * q.Y * v.X - - q.Y * q.Y * v.Z + - 2f * q.W * q.X * v.Y - - q.X * q.X * v.Z + - q.W * q.W * v.Z; - - return c2; - } - } - - public struct UVCoord - { - public float U; - public float V; - - - public UVCoord(float u, float v) - { - this.U = u; - this.V = v; - } - - public UVCoord Flip() - { - this.U = 1.0f - this.U; - this.V = 1.0f - this.V; - return this; - } - } - - public struct Face - { - public int primFace; - - // vertices - public int v1; - public int v2; - public int v3; - - //normals - public int n1; - public int n2; - public int n3; - - // uvs - public int uv1; - public int uv2; - public int uv3; - - public Face(int v1, int v2, int v3) - { - primFace = 0; - - this.v1 = v1; - this.v2 = v2; - this.v3 = v3; - - this.n1 = 0; - this.n2 = 0; - this.n3 = 0; - - this.uv1 = 0; - this.uv2 = 0; - this.uv3 = 0; - - } - - public Face(int v1, int v2, int v3, int n1, int n2, int n3) - { - primFace = 0; - - this.v1 = v1; - this.v2 = v2; - this.v3 = v3; - - this.n1 = n1; - this.n2 = n2; - this.n3 = n3; - - this.uv1 = 0; - this.uv2 = 0; - this.uv3 = 0; - } - - public Coord SurfaceNormal(List coordList) - { - Coord c1 = coordList[this.v1]; - Coord c2 = coordList[this.v2]; - Coord c3 = coordList[this.v3]; - - Coord edge1 = new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z); - Coord edge2 = new Coord(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z); - - return Coord.Cross(edge1, edge2).Normalize(); - } - } - - public struct ViewerFace - { - public int primFaceNumber; - - public Coord v1; - public Coord v2; - public Coord v3; - - public int coordIndex1; - public int coordIndex2; - public int coordIndex3; - - public Coord n1; - public Coord n2; - public Coord n3; - - public UVCoord uv1; - public UVCoord uv2; - public UVCoord uv3; - - public ViewerFace(int primFaceNumber) - { - this.primFaceNumber = primFaceNumber; - - this.v1 = new Coord(); - this.v2 = new Coord(); - this.v3 = new Coord(); - - this.coordIndex1 = this.coordIndex2 = this.coordIndex3 = -1; // -1 means not assigned yet - - this.n1 = new Coord(); - this.n2 = new Coord(); - this.n3 = new Coord(); - - this.uv1 = new UVCoord(); - this.uv2 = new UVCoord(); - this.uv3 = new UVCoord(); - } - - public void Scale(float x, float y, float z) - { - this.v1.X *= x; - this.v1.Y *= y; - this.v1.Z *= z; - - this.v2.X *= x; - this.v2.Y *= y; - this.v2.Z *= z; - - this.v3.X *= x; - this.v3.Y *= y; - this.v3.Z *= z; - } - - public void AddPos(float x, float y, float z) - { - this.v1.X += x; - this.v2.X += x; - this.v3.X += x; - - this.v1.Y += y; - this.v2.Y += y; - this.v3.Y += y; - - this.v1.Z += z; - this.v2.Z += z; - this.v3.Z += z; - } - - public void AddRot(Quat q) - { - this.v1 *= q; - this.v2 *= q; - this.v3 *= q; - - this.n1 *= q; - this.n2 *= q; - this.n3 *= q; - } - - public void CalcSurfaceNormal() - { - - Coord edge1 = new Coord(this.v2.X - this.v1.X, this.v2.Y - this.v1.Y, this.v2.Z - this.v1.Z); - Coord edge2 = new Coord(this.v3.X - this.v1.X, this.v3.Y - this.v1.Y, this.v3.Z - this.v1.Z); - - this.n1 = this.n2 = this.n3 = Coord.Cross(edge1, edge2).Normalize(); - } - } - - internal struct Angle - { - internal float angle; - internal float X; - internal float Y; - - internal Angle(float angle, float x, float y) - { - this.angle = angle; - this.X = x; - this.Y = y; - } - } - - internal class AngleList - { - private float iX, iY; // intersection point - - private static Angle[] angles3 = - { - new Angle(0.0f, 1.0f, 0.0f), - new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f), - new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f), - new Angle(1.0f, 1.0f, 0.0f) - }; - - private static Coord[] normals3 = - { - new Coord(0.25f, 0.4330127019f, 0.0f).Normalize(), - new Coord(-0.5f, 0.0f, 0.0f).Normalize(), - new Coord(0.25f, -0.4330127019f, 0.0f).Normalize(), - new Coord(0.25f, 0.4330127019f, 0.0f).Normalize() - }; - - private static Angle[] angles4 = - { - new Angle(0.0f, 1.0f, 0.0f), - new Angle(0.25f, 0.0f, 1.0f), - new Angle(0.5f, -1.0f, 0.0f), - new Angle(0.75f, 0.0f, -1.0f), - new Angle(1.0f, 1.0f, 0.0f) - }; - - private static Coord[] normals4 = - { - new Coord(0.5f, 0.5f, 0.0f).Normalize(), - new Coord(-0.5f, 0.5f, 0.0f).Normalize(), - new Coord(-0.5f, -0.5f, 0.0f).Normalize(), - new Coord(0.5f, -0.5f, 0.0f).Normalize(), - new Coord(0.5f, 0.5f, 0.0f).Normalize() - }; - - private static Angle[] angles24 = - { - new Angle(0.0f, 1.0f, 0.0f), - new Angle(0.041666666666666664f, 0.96592582628906831f, 0.25881904510252074f), - new Angle(0.083333333333333329f, 0.86602540378443871f, 0.5f), - new Angle(0.125f, 0.70710678118654757f, 0.70710678118654746f), - new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f), - new Angle(0.20833333333333331f, 0.25881904510252096f, 0.9659258262890682f), - new Angle(0.25f, 0.0f, 1.0f), - new Angle(0.29166666666666663f, -0.25881904510252063f, 0.96592582628906831f), - new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f), - new Angle(0.375f, -0.70710678118654746f, 0.70710678118654757f), - new Angle(0.41666666666666663f, -0.86602540378443849f, 0.5f), - new Angle(0.45833333333333331f, -0.9659258262890682f, 0.25881904510252102f), - new Angle(0.5f, -1.0f, 0.0f), - new Angle(0.54166666666666663f, -0.96592582628906842f, -0.25881904510252035f), - new Angle(0.58333333333333326f, -0.86602540378443882f, -0.5f), - new Angle(0.62499999999999989f, -0.70710678118654791f, -0.70710678118654713f), - new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f), - new Angle(0.70833333333333326f, -0.25881904510252152f, -0.96592582628906809f), - new Angle(0.75f, 0.0f, -1.0f), - new Angle(0.79166666666666663f, 0.2588190451025203f, -0.96592582628906842f), - new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f), - new Angle(0.875f, 0.70710678118654735f, -0.70710678118654768f), - new Angle(0.91666666666666663f, 0.86602540378443837f, -0.5f), - new Angle(0.95833333333333326f, 0.96592582628906809f, -0.25881904510252157f), - new Angle(1.0f, 1.0f, 0.0f) - }; - - private Angle interpolatePoints(float newPoint, Angle p1, Angle p2) - { - float m = (newPoint - p1.angle) / (p2.angle - p1.angle); - return new Angle(newPoint, p1.X + m * (p2.X - p1.X), p1.Y + m * (p2.Y - p1.Y)); - } - - private void intersection(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) - { // ref: http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/ - double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1); - double uaNumerator = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3); - - if (denom != 0.0) - { - double ua = uaNumerator / denom; - iX = (float)(x1 + ua * (x2 - x1)); - iY = (float)(y1 + ua * (y2 - y1)); - } - } - - internal List angles; - internal List normals; - - internal void makeAngles(int sides, float startAngle, float stopAngle) - { - angles = new List(); - normals = new List(); - - double twoPi = System.Math.PI * 2.0; - float twoPiInv = 1.0f / (float)twoPi; - - if (sides < 1) - throw new Exception("number of sides not greater than zero"); - if (stopAngle <= startAngle) - throw new Exception("stopAngle not greater than startAngle"); - - if ((sides == 3 || sides == 4 || sides == 24)) - { - startAngle *= twoPiInv; - stopAngle *= twoPiInv; - - Angle[] sourceAngles; - if (sides == 3) - sourceAngles = angles3; - else if (sides == 4) - sourceAngles = angles4; - else sourceAngles = angles24; - - int startAngleIndex = (int)(startAngle * sides); - int endAngleIndex = sourceAngles.Length - 1; - if (stopAngle < 1.0f) - endAngleIndex = (int)(stopAngle * sides) + 1; - if (endAngleIndex == startAngleIndex) - endAngleIndex++; - - for (int angleIndex = startAngleIndex; angleIndex < endAngleIndex + 1; angleIndex++) - { - angles.Add(sourceAngles[angleIndex]); - if (sides == 3) - normals.Add(normals3[angleIndex]); - else if (sides == 4) - normals.Add(normals4[angleIndex]); - } - - if (startAngle > 0.0f) - angles[0] = interpolatePoints(startAngle, angles[0], angles[1]); - - if (stopAngle < 1.0f) - { - int lastAngleIndex = angles.Count - 1; - angles[lastAngleIndex] = interpolatePoints(stopAngle, angles[lastAngleIndex - 1], angles[lastAngleIndex]); - } - } - else - { - double stepSize = twoPi / sides; - - int startStep = (int)(startAngle / stepSize); - double angle = stepSize * startStep; - int step = startStep; - double stopAngleTest = stopAngle; - if (stopAngle < twoPi) - { - stopAngleTest = stepSize * ((int)(stopAngle / stepSize) + 1); - if (stopAngleTest < stopAngle) - stopAngleTest += stepSize; - if (stopAngleTest > twoPi) - stopAngleTest = twoPi; - } - - while (angle <= stopAngleTest) - { - Angle newAngle; - newAngle.angle = (float)angle; - newAngle.X = (float)System.Math.Cos(angle); - newAngle.Y = (float)System.Math.Sin(angle); - angles.Add(newAngle); - step += 1; - angle = stepSize * step; - } - - if (startAngle > angles[0].angle) - { - Angle newAngle; - intersection(angles[0].X, angles[0].Y, angles[1].X, angles[1].Y, 0.0f, 0.0f, (float)Math.Cos(startAngle), (float)Math.Sin(startAngle)); - newAngle.angle = startAngle; - newAngle.X = iX; - newAngle.Y = iY; - angles[0] = newAngle; - } - - int index = angles.Count - 1; - if (stopAngle < angles[index].angle) - { - Angle newAngle; - intersection(angles[index - 1].X, angles[index - 1].Y, angles[index].X, angles[index].Y, 0.0f, 0.0f, (float)Math.Cos(stopAngle), (float)Math.Sin(stopAngle)); - newAngle.angle = stopAngle; - newAngle.X = iX; - newAngle.Y = iY; - angles[index] = newAngle; - } - } - } - } - - /// - /// generates a profile for extrusion - /// - public class Profile - { - private const float twoPi = 2.0f * (float)Math.PI; - - public string errorMessage = null; - - public List coords; - public List faces; - public List vertexNormals; - public List us; - public List faceUVs; - public List faceNumbers; - - // use these for making individual meshes for each prim face - public List outerCoordIndices = null; - public List hollowCoordIndices = null; - public List cut1CoordIndices = null; - public List cut2CoordIndices = null; - - public Coord faceNormal = new Coord(0.0f, 0.0f, 1.0f); - public Coord cutNormal1 = new Coord(); - public Coord cutNormal2 = new Coord(); - - public int numOuterVerts = 0; - public int numHollowVerts = 0; - - public int outerFaceNumber = -1; - public int hollowFaceNumber = -1; - - public bool calcVertexNormals = false; - public int bottomFaceNumber = 0; - public int numPrimFaces = 0; - - public Profile() - { - this.coords = new List(); - this.faces = new List(); - this.vertexNormals = new List(); - this.us = new List(); - this.faceUVs = new List(); - this.faceNumbers = new List(); - } - - public Profile(int sides, float profileStart, float profileEnd, float hollow, int hollowSides, bool createFaces, bool calcVertexNormals) - { - this.calcVertexNormals = calcVertexNormals; - this.coords = new List(); - this.faces = new List(); - this.vertexNormals = new List(); - this.us = new List(); - this.faceUVs = new List(); - this.faceNumbers = new List(); - - Coord center = new Coord(0.0f, 0.0f, 0.0f); - - List hollowCoords = new List(); - List hollowNormals = new List(); - List hollowUs = new List(); - - if (calcVertexNormals) - { - this.outerCoordIndices = new List(); - this.hollowCoordIndices = new List(); - this.cut1CoordIndices = new List(); - this.cut2CoordIndices = new List(); - } - - bool hasHollow = (hollow > 0.0f); - - bool hasProfileCut = (profileStart > 0.0f || profileEnd < 1.0f); - - AngleList angles = new AngleList(); - AngleList hollowAngles = new AngleList(); - - float xScale = 0.5f; - float yScale = 0.5f; - if (sides == 4) // corners of a square are sqrt(2) from center - { - xScale = 0.707107f; - yScale = 0.707107f; - } - - float startAngle = profileStart * twoPi; - float stopAngle = profileEnd * twoPi; - - try { angles.makeAngles(sides, startAngle, stopAngle); } - catch (Exception ex) - { - - errorMessage = "makeAngles failed: Exception: " + ex.ToString() - + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString(); - - return; - } - - this.numOuterVerts = angles.angles.Count; - - // flag to create as few triangles as possible for 3 or 4 side profile - bool simpleFace = (sides < 5 && !hasHollow && !hasProfileCut); - - if (hasHollow) - { - if (sides == hollowSides) - hollowAngles = angles; - else - { - try { hollowAngles.makeAngles(hollowSides, startAngle, stopAngle); } - catch (Exception ex) - { - errorMessage = "makeAngles failed: Exception: " + ex.ToString() - + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString(); - - return; - } - } - this.numHollowVerts = hollowAngles.angles.Count; - } - else if (!simpleFace) - { - this.coords.Add(center); - if (this.calcVertexNormals) - this.vertexNormals.Add(new Coord(0.0f, 0.0f, 1.0f)); - this.us.Add(0.0f); - } - - float z = 0.0f; - - Angle angle; - Coord newVert = new Coord(); - if (hasHollow && hollowSides != sides) - { - int numHollowAngles = hollowAngles.angles.Count; - for (int i = 0; i < numHollowAngles; i++) - { - angle = hollowAngles.angles[i]; - newVert.X = hollow * xScale * angle.X; - newVert.Y = hollow * yScale * angle.Y; - newVert.Z = z; - - hollowCoords.Add(newVert); - if (this.calcVertexNormals) - { - if (hollowSides < 5) - hollowNormals.Add(hollowAngles.normals[i].Invert()); - else - hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f)); - - if (hollowSides == 4) - hollowUs.Add(angle.angle * hollow * 0.707107f); - else - hollowUs.Add(angle.angle * hollow); - } - } - } - - int index = 0; - int numAngles = angles.angles.Count; - - for (int i = 0; i < numAngles; i++) - { - angle = angles.angles[i]; - newVert.X = angle.X * xScale; - newVert.Y = angle.Y * yScale; - newVert.Z = z; - this.coords.Add(newVert); - if (this.calcVertexNormals) - { - this.outerCoordIndices.Add(this.coords.Count - 1); - - if (sides < 5) - { - this.vertexNormals.Add(angles.normals[i]); - float u = angle.angle; - this.us.Add(u); - } - else - { - this.vertexNormals.Add(new Coord(angle.X, angle.Y, 0.0f)); - this.us.Add(angle.angle); - } - } - - if (hasHollow) - { - if (hollowSides == sides) - { - newVert.X *= hollow; - newVert.Y *= hollow; - newVert.Z = z; - hollowCoords.Add(newVert); - if (this.calcVertexNormals) - { - if (sides < 5) - { - hollowNormals.Add(angles.normals[i].Invert()); - } - - else - hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f)); - - hollowUs.Add(angle.angle * hollow); - } - } - } - else if (!simpleFace && createFaces && angle.angle > 0.0001f) - { - Face newFace = new Face(); - newFace.v1 = 0; - newFace.v2 = index; - newFace.v3 = index + 1; - - this.faces.Add(newFace); - } - index += 1; - } - - if (hasHollow) - { - hollowCoords.Reverse(); - if (this.calcVertexNormals) - { - hollowNormals.Reverse(); - hollowUs.Reverse(); - } - - if (createFaces) - { - int numTotalVerts = this.numOuterVerts + this.numHollowVerts; - - if (this.numOuterVerts == this.numHollowVerts) - { - Face newFace = new Face(); - - for (int coordIndex = 0; coordIndex < this.numOuterVerts - 1; coordIndex++) - { - newFace.v1 = coordIndex; - newFace.v2 = coordIndex + 1; - newFace.v3 = numTotalVerts - coordIndex - 1; - this.faces.Add(newFace); - - newFace.v1 = coordIndex + 1; - newFace.v2 = numTotalVerts - coordIndex - 2; - newFace.v3 = numTotalVerts - coordIndex - 1; - this.faces.Add(newFace); - } - } - else - { - if (this.numOuterVerts < this.numHollowVerts) - { - Face newFace = new Face(); - int j = 0; // j is the index for outer vertices - int maxJ = this.numOuterVerts - 1; - for (int i = 0; i < this.numHollowVerts; i++) // i is the index for inner vertices - { - if (j < maxJ) - if (angles.angles[j + 1].angle - hollowAngles.angles[i].angle < hollowAngles.angles[i].angle - angles.angles[j].angle + 0.000001f) - { - newFace.v1 = numTotalVerts - i - 1; - newFace.v2 = j; - newFace.v3 = j + 1; - - this.faces.Add(newFace); - j += 1; - } - - newFace.v1 = j; - newFace.v2 = numTotalVerts - i - 2; - newFace.v3 = numTotalVerts - i - 1; - - this.faces.Add(newFace); - } - } - else // numHollowVerts < numOuterVerts - { - Face newFace = new Face(); - int j = 0; // j is the index for inner vertices - int maxJ = this.numHollowVerts - 1; - for (int i = 0; i < this.numOuterVerts; i++) - { - if (j < maxJ) - if (hollowAngles.angles[j + 1].angle - angles.angles[i].angle < angles.angles[i].angle - hollowAngles.angles[j].angle + 0.000001f) - { - newFace.v1 = i; - newFace.v2 = numTotalVerts - j - 2; - newFace.v3 = numTotalVerts - j - 1; - - this.faces.Add(newFace); - j += 1; - } - - newFace.v1 = numTotalVerts - j - 1; - newFace.v2 = i; - newFace.v3 = i + 1; - - this.faces.Add(newFace); - } - } - } - } - - if (calcVertexNormals) - { - foreach (Coord hc in hollowCoords) - { - this.coords.Add(hc); - hollowCoordIndices.Add(this.coords.Count - 1); - } - } - else - this.coords.AddRange(hollowCoords); - - if (this.calcVertexNormals) - { - this.vertexNormals.AddRange(hollowNormals); - this.us.AddRange(hollowUs); - - } - } - - if (simpleFace && createFaces) - { - if (sides == 3) - this.faces.Add(new Face(0, 1, 2)); - else if (sides == 4) - { - this.faces.Add(new Face(0, 1, 2)); - this.faces.Add(new Face(0, 2, 3)); - } - } - - if (calcVertexNormals && hasProfileCut) - { - int lastOuterVertIndex = this.numOuterVerts - 1; - - if (hasHollow) - { - this.cut1CoordIndices.Add(0); - this.cut1CoordIndices.Add(this.coords.Count - 1); - - this.cut2CoordIndices.Add(lastOuterVertIndex + 1); - this.cut2CoordIndices.Add(lastOuterVertIndex); - - this.cutNormal1.X = this.coords[0].Y - this.coords[this.coords.Count - 1].Y; - this.cutNormal1.Y = -(this.coords[0].X - this.coords[this.coords.Count - 1].X); - - this.cutNormal2.X = this.coords[lastOuterVertIndex + 1].Y - this.coords[lastOuterVertIndex].Y; - this.cutNormal2.Y = -(this.coords[lastOuterVertIndex + 1].X - this.coords[lastOuterVertIndex].X); - } - - else - { - this.cut1CoordIndices.Add(0); - this.cut1CoordIndices.Add(1); - - this.cut2CoordIndices.Add(lastOuterVertIndex); - this.cut2CoordIndices.Add(0); - - this.cutNormal1.X = this.vertexNormals[1].Y; - this.cutNormal1.Y = -this.vertexNormals[1].X; - - this.cutNormal2.X = -this.vertexNormals[this.vertexNormals.Count - 2].Y; - this.cutNormal2.Y = this.vertexNormals[this.vertexNormals.Count - 2].X; - - } - this.cutNormal1.Normalize(); - this.cutNormal2.Normalize(); - } - - this.MakeFaceUVs(); - - hollowCoords = null; - hollowNormals = null; - hollowUs = null; - - if (calcVertexNormals) - { // calculate prim face numbers - - // face number order is top, outer, hollow, bottom, start cut, end cut - // I know it's ugly but so is the whole concept of prim face numbers - - int faceNum = 1; // start with outer faces - this.outerFaceNumber = faceNum; - - int startVert = hasProfileCut && !hasHollow ? 1 : 0; - if (startVert > 0) - this.faceNumbers.Add(-1); - for (int i = 0; i < this.numOuterVerts - 1; i++) - this.faceNumbers.Add(sides < 5 && i <= sides ? faceNum++ : faceNum); - - this.faceNumbers.Add(hasProfileCut ? -1 : faceNum++); - - if (sides > 4 && (hasHollow || hasProfileCut)) - faceNum++; - - if (sides < 5 && (hasHollow || hasProfileCut) && this.numOuterVerts < sides) - faceNum++; - - if (hasHollow) - { - for (int i = 0; i < this.numHollowVerts; i++) - this.faceNumbers.Add(faceNum); - - this.hollowFaceNumber = faceNum++; - } - - this.bottomFaceNumber = faceNum++; - - if (hasHollow && hasProfileCut) - this.faceNumbers.Add(faceNum++); - - for (int i = 0; i < this.faceNumbers.Count; i++) - if (this.faceNumbers[i] == -1) - this.faceNumbers[i] = faceNum++; - - this.numPrimFaces = faceNum; - } - - } - - public void MakeFaceUVs() - { - this.faceUVs = new List(); - foreach (Coord c in this.coords) - this.faceUVs.Add(new UVCoord(1.0f - (0.5f + c.X), 1.0f - (0.5f - c.Y))); - } - - public Profile Copy() - { - return this.Copy(true); - } - - public Profile Copy(bool needFaces) - { - Profile copy = new Profile(); - - copy.coords.AddRange(this.coords); - copy.faceUVs.AddRange(this.faceUVs); - - if (needFaces) - copy.faces.AddRange(this.faces); - if ((copy.calcVertexNormals = this.calcVertexNormals) == true) - { - copy.vertexNormals.AddRange(this.vertexNormals); - copy.faceNormal = this.faceNormal; - copy.cutNormal1 = this.cutNormal1; - copy.cutNormal2 = this.cutNormal2; - copy.us.AddRange(this.us); - copy.faceNumbers.AddRange(this.faceNumbers); - - copy.cut1CoordIndices = new List(this.cut1CoordIndices); - copy.cut2CoordIndices = new List(this.cut2CoordIndices); - copy.hollowCoordIndices = new List(this.hollowCoordIndices); - copy.outerCoordIndices = new List(this.outerCoordIndices); - } - copy.numOuterVerts = this.numOuterVerts; - copy.numHollowVerts = this.numHollowVerts; - - return copy; - } - - public void AddPos(Coord v) - { - this.AddPos(v.X, v.Y, v.Z); - } - - public void AddPos(float x, float y, float z) - { - int i; - int numVerts = this.coords.Count; - Coord vert; - - for (i = 0; i < numVerts; i++) - { - vert = this.coords[i]; - vert.X += x; - vert.Y += y; - vert.Z += z; - this.coords[i] = vert; - } - } - - public void AddRot(Quat q) - { - int i; - int numVerts = this.coords.Count; - - for (i = 0; i < numVerts; i++) - this.coords[i] *= q; - - if (this.calcVertexNormals) - { - int numNormals = this.vertexNormals.Count; - for (i = 0; i < numNormals; i++) - this.vertexNormals[i] *= q; - - this.faceNormal *= q; - this.cutNormal1 *= q; - this.cutNormal2 *= q; - - } - } - - public void Scale(float x, float y) - { - int i; - int numVerts = this.coords.Count; - Coord vert; - - for (i = 0; i < numVerts; i++) - { - vert = this.coords[i]; - vert.X *= x; - vert.Y *= y; - this.coords[i] = vert; - } - } - - /// - /// Changes order of the vertex indices and negates the center vertex normal. Does not alter vertex normals of radial vertices - /// - public void FlipNormals() - { - int i; - int numFaces = this.faces.Count; - Face tmpFace; - int tmp; - - for (i = 0; i < numFaces; i++) - { - tmpFace = this.faces[i]; - tmp = tmpFace.v3; - tmpFace.v3 = tmpFace.v1; - tmpFace.v1 = tmp; - this.faces[i] = tmpFace; - } - - if (this.calcVertexNormals) - { - int normalCount = this.vertexNormals.Count; - if (normalCount > 0) - { - Coord n = this.vertexNormals[normalCount - 1]; - n.Z = -n.Z; - this.vertexNormals[normalCount - 1] = n; - } - } - - this.faceNormal.X = -this.faceNormal.X; - this.faceNormal.Y = -this.faceNormal.Y; - this.faceNormal.Z = -this.faceNormal.Z; - - int numfaceUVs = this.faceUVs.Count; - for (i = 0; i < numfaceUVs; i++) - { - UVCoord uv = this.faceUVs[i]; - uv.V = 1.0f - uv.V; - this.faceUVs[i] = uv; - } - } - - public void AddValue2FaceVertexIndices(int num) - { - int numFaces = this.faces.Count; - Face tmpFace; - for (int i = 0; i < numFaces; i++) - { - tmpFace = this.faces[i]; - tmpFace.v1 += num; - tmpFace.v2 += num; - tmpFace.v3 += num; - - this.faces[i] = tmpFace; - } - } - - public void AddValue2FaceNormalIndices(int num) - { - if (this.calcVertexNormals) - { - int numFaces = this.faces.Count; - Face tmpFace; - for (int i = 0; i < numFaces; i++) - { - tmpFace = this.faces[i]; - tmpFace.n1 += num; - tmpFace.n2 += num; - tmpFace.n3 += num; - - this.faces[i] = tmpFace; - } - } - } - - public void DumpRaw(String path, String name, String title) - { - if (path == null) - return; - String fileName = name + "_" + title + ".raw"; - String completePath = System.IO.Path.Combine(path, fileName); - StreamWriter sw = new StreamWriter(completePath); - - for (int i = 0; i < this.faces.Count; i++) - { - string s = this.coords[this.faces[i].v1].ToString(); - s += " " + this.coords[this.faces[i].v2].ToString(); - s += " " + this.coords[this.faces[i].v3].ToString(); - - sw.WriteLine(s); - } - - sw.Close(); - } - } - - public struct PathNode - { - public Coord position; - public Quat rotation; - public float xScale; - public float yScale; - public float percentOfPath; - } - - public enum PathType { Linear = 0, Circular = 1, Flexible = 2 } - - public class Path - { - public List pathNodes = new List(); - - public float twistBegin = 0.0f; - public float twistEnd = 0.0f; - public float topShearX = 0.0f; - public float topShearY = 0.0f; - public float pathCutBegin = 0.0f; - public float pathCutEnd = 1.0f; - public float dimpleBegin = 0.0f; - public float dimpleEnd = 1.0f; - public float skew = 0.0f; - public float holeSizeX = 1.0f; // called pathScaleX in pbs - public float holeSizeY = 0.25f; - public float taperX = 0.0f; - public float taperY = 0.0f; - public float radius = 0.0f; - public float revolutions = 1.0f; - public int stepsPerRevolution = 24; - - private const float twoPi = 2.0f * (float)Math.PI; - - public void Create(PathType pathType, int steps) - { - if (this.taperX > 0.999f) - this.taperX = 0.999f; - if (this.taperX < -0.999f) - this.taperX = -0.999f; - if (this.taperY > 0.999f) - this.taperY = 0.999f; - if (this.taperY < -0.999f) - this.taperY = -0.999f; - - if (pathType == PathType.Linear || pathType == PathType.Flexible) - { - int step = 0; - - float length = this.pathCutEnd - this.pathCutBegin; - float twistTotal = twistEnd - twistBegin; - float twistTotalAbs = Math.Abs(twistTotal); - if (twistTotalAbs > 0.01f) - steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number - - float start = -0.5f; - float stepSize = length / (float)steps; - float percentOfPathMultiplier = stepSize * 0.999999f; - float xOffset = this.topShearX * this.pathCutBegin; - float yOffset = this.topShearY * this.pathCutBegin; - float zOffset = start; - float xOffsetStepIncrement = this.topShearX * length / steps; - float yOffsetStepIncrement = this.topShearY * length / steps; - - float percentOfPath = this.pathCutBegin; - zOffset += percentOfPath; - - // sanity checks - - bool done = false; - - while (!done) - { - PathNode newNode = new PathNode(); - - newNode.xScale = 1.0f; - if (this.taperX == 0.0f) - newNode.xScale = 1.0f; - else if (this.taperX > 0.0f) - newNode.xScale = 1.0f - percentOfPath * this.taperX; - else newNode.xScale = 1.0f + (1.0f - percentOfPath) * this.taperX; - - newNode.yScale = 1.0f; - if (this.taperY == 0.0f) - newNode.yScale = 1.0f; - else if (this.taperY > 0.0f) - newNode.yScale = 1.0f - percentOfPath * this.taperY; - else newNode.yScale = 1.0f + (1.0f - percentOfPath) * this.taperY; - - float twist = twistBegin + twistTotal * percentOfPath; - - newNode.rotation = new Quat(new Coord(0.0f, 0.0f, 1.0f), twist); - newNode.position = new Coord(xOffset, yOffset, zOffset); - newNode.percentOfPath = percentOfPath; - - pathNodes.Add(newNode); - - if (step < steps) - { - step += 1; - percentOfPath += percentOfPathMultiplier; - xOffset += xOffsetStepIncrement; - yOffset += yOffsetStepIncrement; - zOffset += stepSize; - if (percentOfPath > this.pathCutEnd) - done = true; - } - else done = true; - } - } // end of linear path code - - else // pathType == Circular - { - float twistTotal = twistEnd - twistBegin; - - // if the profile has a lot of twist, add more layers otherwise the layers may overlap - // and the resulting mesh may be quite inaccurate. This method is arbitrary and doesn't - // accurately match the viewer - float twistTotalAbs = Math.Abs(twistTotal); - if (twistTotalAbs > 0.01f) - { - if (twistTotalAbs > Math.PI * 1.5f) - steps *= 2; - if (twistTotalAbs > Math.PI * 3.0f) - steps *= 2; - } - - float yPathScale = this.holeSizeY * 0.5f; - float pathLength = this.pathCutEnd - this.pathCutBegin; - float totalSkew = this.skew * 2.0f * pathLength; - float skewStart = this.pathCutBegin * 2.0f * this.skew - this.skew; - float xOffsetTopShearXFactor = this.topShearX * (0.25f + 0.5f * (0.5f - this.holeSizeY)); - float yShearCompensation = 1.0f + Math.Abs(this.topShearY) * 0.25f; - - // It's not quite clear what pushY (Y top shear) does, but subtracting it from the start and end - // angles appears to approximate it's effects on path cut. Likewise, adding it to the angle used - // to calculate the sine for generating the path radius appears to approximate it's effects there - // too, but there are some subtle differences in the radius which are noticeable as the prim size - // increases and it may affect megaprims quite a bit. The effect of the Y top shear parameter on - // the meshes generated with this technique appear nearly identical in shape to the same prims when - // displayed by the viewer. - - float startAngle = (twoPi * this.pathCutBegin * this.revolutions) - this.topShearY * 0.9f; - float endAngle = (twoPi * this.pathCutEnd * this.revolutions) - this.topShearY * 0.9f; - float stepSize = twoPi / this.stepsPerRevolution; - - int step = (int)(startAngle / stepSize); - float angle = startAngle; - - bool done = false; - while (!done) // loop through the length of the path and add the layers - { - PathNode newNode = new PathNode(); - - float xProfileScale = (1.0f - Math.Abs(this.skew)) * this.holeSizeX; - float yProfileScale = this.holeSizeY; - - float percentOfPath = angle / (twoPi * this.revolutions); - float percentOfAngles = (angle - startAngle) / (endAngle - startAngle); - - if (this.taperX > 0.01f) - xProfileScale *= 1.0f - percentOfPath * this.taperX; - else if (this.taperX < -0.01f) - xProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperX; - - if (this.taperY > 0.01f) - yProfileScale *= 1.0f - percentOfPath * this.taperY; - else if (this.taperY < -0.01f) - yProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperY; - - newNode.xScale = xProfileScale; - newNode.yScale = yProfileScale; - - float radiusScale = 1.0f; - if (this.radius > 0.001f) - radiusScale = 1.0f - this.radius * percentOfPath; - else if (this.radius < 0.001f) - radiusScale = 1.0f + this.radius * (1.0f - percentOfPath); - - float twist = twistBegin + twistTotal * percentOfPath; - - float xOffset = 0.5f * (skewStart + totalSkew * percentOfAngles); - xOffset += (float)Math.Sin(angle) * xOffsetTopShearXFactor; - - float yOffset = yShearCompensation * (float)Math.Cos(angle) * (0.5f - yPathScale) * radiusScale; - - float zOffset = (float)Math.Sin(angle + this.topShearY) * (0.5f - yPathScale) * radiusScale; - - newNode.position = new Coord(xOffset, yOffset, zOffset); - - // now orient the rotation of the profile layer relative to it's position on the path - // adding taperY to the angle used to generate the quat appears to approximate the viewer - - newNode.rotation = new Quat(new Coord(1.0f, 0.0f, 0.0f), angle + this.topShearY); - - // next apply twist rotation to the profile layer - if (twistTotal != 0.0f || twistBegin != 0.0f) - newNode.rotation *= new Quat(new Coord(0.0f, 0.0f, 1.0f), twist); - - newNode.percentOfPath = percentOfPath; - - pathNodes.Add(newNode); - - // calculate terms for next iteration - // calculate the angle for the next iteration of the loop - - if (angle >= endAngle - 0.01) - done = true; - else - { - step += 1; - angle = stepSize * step; - if (angle > endAngle) - angle = endAngle; - } - } - } - } - } - - public class PrimMesh - { - public string errorMessage = ""; - private const float twoPi = 2.0f * (float)Math.PI; - - public List coords; - public List normals; - public List faces; - - public List viewerFaces; - - private int sides = 4; - private int hollowSides = 4; - private float profileStart = 0.0f; - private float profileEnd = 1.0f; - private float hollow = 0.0f; - public int twistBegin = 0; - public int twistEnd = 0; - public float topShearX = 0.0f; - public float topShearY = 0.0f; - public float pathCutBegin = 0.0f; - public float pathCutEnd = 1.0f; - public float dimpleBegin = 0.0f; - public float dimpleEnd = 1.0f; - public float skew = 0.0f; - public float holeSizeX = 1.0f; // called pathScaleX in pbs - public float holeSizeY = 0.25f; - public float taperX = 0.0f; - public float taperY = 0.0f; - public float radius = 0.0f; - public float revolutions = 1.0f; - public int stepsPerRevolution = 24; - - private int profileOuterFaceNumber = -1; - private int profileHollowFaceNumber = -1; - - private bool hasProfileCut = false; - private bool hasHollow = false; - public bool calcVertexNormals = false; - private bool normalsProcessed = false; - public bool viewerMode = false; - public bool sphereMode = false; - - public int numPrimFaces = 0; - - /// - /// Human readable string representation of the parameters used to create a mesh. - /// - /// - public string ParamsToDisplayString() - { - string s = ""; - s += "sides..................: " + this.sides.ToString(); - s += "\nhollowSides..........: " + this.hollowSides.ToString(); - s += "\nprofileStart.........: " + this.profileStart.ToString(); - s += "\nprofileEnd...........: " + this.profileEnd.ToString(); - s += "\nhollow...............: " + this.hollow.ToString(); - s += "\ntwistBegin...........: " + this.twistBegin.ToString(); - s += "\ntwistEnd.............: " + this.twistEnd.ToString(); - s += "\ntopShearX............: " + this.topShearX.ToString(); - s += "\ntopShearY............: " + this.topShearY.ToString(); - s += "\npathCutBegin.........: " + this.pathCutBegin.ToString(); - s += "\npathCutEnd...........: " + this.pathCutEnd.ToString(); - s += "\ndimpleBegin..........: " + this.dimpleBegin.ToString(); - s += "\ndimpleEnd............: " + this.dimpleEnd.ToString(); - s += "\nskew.................: " + this.skew.ToString(); - s += "\nholeSizeX............: " + this.holeSizeX.ToString(); - s += "\nholeSizeY............: " + this.holeSizeY.ToString(); - s += "\ntaperX...............: " + this.taperX.ToString(); - s += "\ntaperY...............: " + this.taperY.ToString(); - s += "\nradius...............: " + this.radius.ToString(); - s += "\nrevolutions..........: " + this.revolutions.ToString(); - s += "\nstepsPerRevolution...: " + this.stepsPerRevolution.ToString(); - s += "\nsphereMode...........: " + this.sphereMode.ToString(); - s += "\nhasProfileCut........: " + this.hasProfileCut.ToString(); - s += "\nhasHollow............: " + this.hasHollow.ToString(); - s += "\nviewerMode...........: " + this.viewerMode.ToString(); - - return s; - } - - public int ProfileOuterFaceNumber - { - get { return profileOuterFaceNumber; } - } - - public int ProfileHollowFaceNumber - { - get { return profileHollowFaceNumber; } - } - - public bool HasProfileCut - { - get { return hasProfileCut; } - } - - public bool HasHollow - { - get { return hasHollow; } - } - - - /// - /// Constructs a PrimMesh object and creates the profile for extrusion. - /// - /// - /// - /// - /// - /// - public PrimMesh(int sides, float profileStart, float profileEnd, float hollow, int hollowSides) - { - this.coords = new List(); - this.faces = new List(); - - this.sides = sides; - this.profileStart = profileStart; - this.profileEnd = profileEnd; - this.hollow = hollow; - this.hollowSides = hollowSides; - - if (sides < 3) - this.sides = 3; - if (hollowSides < 3) - this.hollowSides = 3; - if (profileStart < 0.0f) - this.profileStart = 0.0f; - if (profileEnd > 1.0f) - this.profileEnd = 1.0f; - if (profileEnd < 0.02f) - this.profileEnd = 0.02f; - if (profileStart >= profileEnd) - this.profileStart = profileEnd - 0.02f; - if (hollow > 0.99f) - this.hollow = 0.99f; - if (hollow < 0.0f) - this.hollow = 0.0f; - } - - /// - /// Extrudes a profile along a path. - /// - public void Extrude(PathType pathType) - { - bool needEndFaces = false; - - this.coords = new List(); - this.faces = new List(); - - if (this.viewerMode) - { - this.viewerFaces = new List(); - this.calcVertexNormals = true; - } - - if (this.calcVertexNormals) - this.normals = new List(); - - int steps = 1; - - float length = this.pathCutEnd - this.pathCutBegin; - normalsProcessed = false; - - if (this.viewerMode && this.sides == 3) - { - // prisms don't taper well so add some vertical resolution - // other prims may benefit from this but just do prisms for now - if (Math.Abs(this.taperX) > 0.01 || Math.Abs(this.taperY) > 0.01) - steps = (int)(steps * 4.5 * length); - } - - if (this.sphereMode) - this.hasProfileCut = this.profileEnd - this.profileStart < 0.4999f; - else - this.hasProfileCut = this.profileEnd - this.profileStart < 0.9999f; - this.hasHollow = (this.hollow > 0.001f); - - float twistBegin = this.twistBegin / 360.0f * twoPi; - float twistEnd = this.twistEnd / 360.0f * twoPi; - float twistTotal = twistEnd - twistBegin; - float twistTotalAbs = Math.Abs(twistTotal); - if (twistTotalAbs > 0.01f) - steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number - - float hollow = this.hollow; - - if (pathType == PathType.Circular) - { - needEndFaces = false; - if (this.pathCutBegin != 0.0f || this.pathCutEnd != 1.0f) - needEndFaces = true; - else if (this.taperX != 0.0f || this.taperY != 0.0f) - needEndFaces = true; - else if (this.skew != 0.0f) - needEndFaces = true; - else if (twistTotal != 0.0f) - needEndFaces = true; - else if (this.radius != 0.0f) - needEndFaces = true; - } - else needEndFaces = true; - - // sanity checks - float initialProfileRot = 0.0f; - if (pathType == PathType.Circular) - { - if (this.sides == 3) - { - initialProfileRot = (float)Math.PI; - if (this.hollowSides == 4) - { - if (hollow > 0.7f) - hollow = 0.7f; - hollow *= 0.707f; - } - else hollow *= 0.5f; - } - else if (this.sides == 4) - { - initialProfileRot = 0.25f * (float)Math.PI; - if (this.hollowSides != 4) - hollow *= 0.707f; - } - else if (this.sides > 4) - { - initialProfileRot = (float)Math.PI; - if (this.hollowSides == 4) - { - if (hollow > 0.7f) - hollow = 0.7f; - hollow /= 0.7f; - } - } - } - else - { - if (this.sides == 3) - { - if (this.hollowSides == 4) - { - if (hollow > 0.7f) - hollow = 0.7f; - hollow *= 0.707f; - } - else hollow *= 0.5f; - } - else if (this.sides == 4) - { - initialProfileRot = 1.25f * (float)Math.PI; - if (this.hollowSides != 4) - hollow *= 0.707f; - } - else if (this.sides == 24 && this.hollowSides == 4) - hollow *= 1.414f; - } - - Profile profile = new Profile(this.sides, this.profileStart, this.profileEnd, hollow, this.hollowSides, true, calcVertexNormals); - this.errorMessage = profile.errorMessage; - - this.numPrimFaces = profile.numPrimFaces; - - int cut1FaceNumber = profile.bottomFaceNumber + 1; - int cut2FaceNumber = cut1FaceNumber + 1; - if (!needEndFaces) - { - cut1FaceNumber -= 2; - cut2FaceNumber -= 2; - } - - profileOuterFaceNumber = profile.outerFaceNumber; - if (!needEndFaces) - profileOuterFaceNumber--; - - if (hasHollow) - { - profileHollowFaceNumber = profile.hollowFaceNumber; - if (!needEndFaces) - profileHollowFaceNumber--; - } - - int cut1Vert = -1; - int cut2Vert = -1; - if (hasProfileCut) - { - cut1Vert = hasHollow ? profile.coords.Count - 1 : 0; - cut2Vert = hasHollow ? profile.numOuterVerts - 1 : profile.numOuterVerts; - } - - if (initialProfileRot != 0.0f) - { - profile.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), initialProfileRot)); - if (viewerMode) - profile.MakeFaceUVs(); - } - - Coord lastCutNormal1 = new Coord(); - Coord lastCutNormal2 = new Coord(); - float thisV = 0.0f; - float lastV = 0.0f; - - Path path = new Path(); - path.twistBegin = twistBegin; - path.twistEnd = twistEnd; - path.topShearX = topShearX; - path.topShearY = topShearY; - path.pathCutBegin = pathCutBegin; - path.pathCutEnd = pathCutEnd; - path.dimpleBegin = dimpleBegin; - path.dimpleEnd = dimpleEnd; - path.skew = skew; - path.holeSizeX = holeSizeX; - path.holeSizeY = holeSizeY; - path.taperX = taperX; - path.taperY = taperY; - path.radius = radius; - path.revolutions = revolutions; - path.stepsPerRevolution = stepsPerRevolution; - - path.Create(pathType, steps); - - for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++) - { - PathNode node = path.pathNodes[nodeIndex]; - Profile newLayer = profile.Copy(); - newLayer.Scale(node.xScale, node.yScale); - - newLayer.AddRot(node.rotation); - newLayer.AddPos(node.position); - - if (needEndFaces && nodeIndex == 0) - { - newLayer.FlipNormals(); - - // add the bottom faces to the viewerFaces list - if (this.viewerMode) - { - Coord faceNormal = newLayer.faceNormal; - ViewerFace newViewerFace = new ViewerFace(profile.bottomFaceNumber); - int numFaces = newLayer.faces.Count; - List faces = newLayer.faces; - - for (int i = 0; i < numFaces; i++) - { - Face face = faces[i]; - newViewerFace.v1 = newLayer.coords[face.v1]; - newViewerFace.v2 = newLayer.coords[face.v2]; - newViewerFace.v3 = newLayer.coords[face.v3]; - - newViewerFace.coordIndex1 = face.v1; - newViewerFace.coordIndex2 = face.v2; - newViewerFace.coordIndex3 = face.v3; - - newViewerFace.n1 = faceNormal; - newViewerFace.n2 = faceNormal; - newViewerFace.n3 = faceNormal; - - newViewerFace.uv1 = newLayer.faceUVs[face.v1]; - newViewerFace.uv2 = newLayer.faceUVs[face.v2]; - newViewerFace.uv3 = newLayer.faceUVs[face.v3]; - - if (pathType == PathType.Linear) - { - newViewerFace.uv1.Flip(); - newViewerFace.uv2.Flip(); - newViewerFace.uv3.Flip(); - } - - this.viewerFaces.Add(newViewerFace); - } - } - } // if (nodeIndex == 0) - - // append this layer - - int coordsLen = this.coords.Count; - newLayer.AddValue2FaceVertexIndices(coordsLen); - - this.coords.AddRange(newLayer.coords); - - if (this.calcVertexNormals) - { - newLayer.AddValue2FaceNormalIndices(this.normals.Count); - this.normals.AddRange(newLayer.vertexNormals); - } - - if (node.percentOfPath < this.pathCutBegin + 0.01f || node.percentOfPath > this.pathCutEnd - 0.01f) - this.faces.AddRange(newLayer.faces); - - // fill faces between layers - - int numVerts = newLayer.coords.Count; - Face newFace1 = new Face(); - Face newFace2 = new Face(); - - thisV = 1.0f - node.percentOfPath; - - if (nodeIndex > 0) - { - int startVert = coordsLen + 1; - int endVert = this.coords.Count; - - if (sides < 5 || this.hasProfileCut || this.hasHollow) - startVert--; - - for (int i = startVert; i < endVert; i++) - { - int iNext = i + 1; - if (i == endVert - 1) - iNext = startVert; - - int whichVert = i - startVert; - - newFace1.v1 = i; - newFace1.v2 = i - numVerts; - newFace1.v3 = iNext; - - newFace1.n1 = newFace1.v1; - newFace1.n2 = newFace1.v2; - newFace1.n3 = newFace1.v3; - this.faces.Add(newFace1); - - newFace2.v1 = iNext; - newFace2.v2 = i - numVerts; - newFace2.v3 = iNext - numVerts; - - newFace2.n1 = newFace2.v1; - newFace2.n2 = newFace2.v2; - newFace2.n3 = newFace2.v3; - this.faces.Add(newFace2); - - if (this.viewerMode) - { - // add the side faces to the list of viewerFaces here - - int primFaceNum = profile.faceNumbers[whichVert]; - if (!needEndFaces) - primFaceNum -= 1; - - ViewerFace newViewerFace1 = new ViewerFace(primFaceNum); - ViewerFace newViewerFace2 = new ViewerFace(primFaceNum); - - int uIndex = whichVert; - if (!hasHollow && sides > 4 && uIndex < newLayer.us.Count - 1) - { - uIndex++; - } - - float u1 = newLayer.us[uIndex]; - float u2 = 1.0f; - if (uIndex < (int)newLayer.us.Count - 1) - u2 = newLayer.us[uIndex + 1]; - - if (whichVert == cut1Vert || whichVert == cut2Vert) - { - u1 = 0.0f; - u2 = 1.0f; - } - else if (sides < 5) - { - if (whichVert < profile.numOuterVerts) - { // boxes and prisms have one texture face per side of the prim, so the U values have to be scaled - // to reflect the entire texture width - u1 *= sides; - u2 *= sides; - u2 -= (int)u1; - u1 -= (int)u1; - if (u2 < 0.1f) - u2 = 1.0f; - } - } - - if (this.sphereMode) - { - if (whichVert != cut1Vert && whichVert != cut2Vert) - { - u1 = u1 * 2.0f - 1.0f; - u2 = u2 * 2.0f - 1.0f; - - if (whichVert >= newLayer.numOuterVerts) - { - u1 -= hollow; - u2 -= hollow; - } - - } - } - - newViewerFace1.uv1.U = u1; - newViewerFace1.uv2.U = u1; - newViewerFace1.uv3.U = u2; - - newViewerFace1.uv1.V = thisV; - newViewerFace1.uv2.V = lastV; - newViewerFace1.uv3.V = thisV; - - newViewerFace2.uv1.U = u2; - newViewerFace2.uv2.U = u1; - newViewerFace2.uv3.U = u2; - - newViewerFace2.uv1.V = thisV; - newViewerFace2.uv2.V = lastV; - newViewerFace2.uv3.V = lastV; - - newViewerFace1.v1 = this.coords[newFace1.v1]; - newViewerFace1.v2 = this.coords[newFace1.v2]; - newViewerFace1.v3 = this.coords[newFace1.v3]; - - newViewerFace2.v1 = this.coords[newFace2.v1]; - newViewerFace2.v2 = this.coords[newFace2.v2]; - newViewerFace2.v3 = this.coords[newFace2.v3]; - - newViewerFace1.coordIndex1 = newFace1.v1; - newViewerFace1.coordIndex2 = newFace1.v2; - newViewerFace1.coordIndex3 = newFace1.v3; - - newViewerFace2.coordIndex1 = newFace2.v1; - newViewerFace2.coordIndex2 = newFace2.v2; - newViewerFace2.coordIndex3 = newFace2.v3; - - // profile cut faces - if (whichVert == cut1Vert) - { - newViewerFace1.primFaceNumber = cut1FaceNumber; - newViewerFace2.primFaceNumber = cut1FaceNumber; - newViewerFace1.n1 = newLayer.cutNormal1; - newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal1; - - newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal1; - newViewerFace2.n2 = lastCutNormal1; - } - else if (whichVert == cut2Vert) - { - newViewerFace1.primFaceNumber = cut2FaceNumber; - newViewerFace2.primFaceNumber = cut2FaceNumber; - newViewerFace1.n1 = newLayer.cutNormal2; - newViewerFace1.n2 = lastCutNormal2; - newViewerFace1.n3 = lastCutNormal2; - - newViewerFace2.n1 = newLayer.cutNormal2; - newViewerFace2.n3 = newLayer.cutNormal2; - newViewerFace2.n2 = lastCutNormal2; - } - - else // outer and hollow faces - { - if ((sides < 5 && whichVert < newLayer.numOuterVerts) || (hollowSides < 5 && whichVert >= newLayer.numOuterVerts)) - { // looks terrible when path is twisted... need vertex normals here - newViewerFace1.CalcSurfaceNormal(); - newViewerFace2.CalcSurfaceNormal(); - } - else - { - newViewerFace1.n1 = this.normals[newFace1.n1]; - newViewerFace1.n2 = this.normals[newFace1.n2]; - newViewerFace1.n3 = this.normals[newFace1.n3]; - - newViewerFace2.n1 = this.normals[newFace2.n1]; - newViewerFace2.n2 = this.normals[newFace2.n2]; - newViewerFace2.n3 = this.normals[newFace2.n3]; - } - } - - this.viewerFaces.Add(newViewerFace1); - this.viewerFaces.Add(newViewerFace2); - - } - } - } - - lastCutNormal1 = newLayer.cutNormal1; - lastCutNormal2 = newLayer.cutNormal2; - lastV = thisV; - - if (needEndFaces && nodeIndex == path.pathNodes.Count - 1 && viewerMode) - { - // add the top faces to the viewerFaces list here - Coord faceNormal = newLayer.faceNormal; - ViewerFace newViewerFace = new ViewerFace(0); - int numFaces = newLayer.faces.Count; - List faces = newLayer.faces; - - for (int i = 0; i < numFaces; i++) - { - Face face = faces[i]; - newViewerFace.v1 = newLayer.coords[face.v1 - coordsLen]; - newViewerFace.v2 = newLayer.coords[face.v2 - coordsLen]; - newViewerFace.v3 = newLayer.coords[face.v3 - coordsLen]; - - newViewerFace.coordIndex1 = face.v1 - coordsLen; - newViewerFace.coordIndex2 = face.v2 - coordsLen; - newViewerFace.coordIndex3 = face.v3 - coordsLen; - - newViewerFace.n1 = faceNormal; - newViewerFace.n2 = faceNormal; - newViewerFace.n3 = faceNormal; - - newViewerFace.uv1 = newLayer.faceUVs[face.v1 - coordsLen]; - newViewerFace.uv2 = newLayer.faceUVs[face.v2 - coordsLen]; - newViewerFace.uv3 = newLayer.faceUVs[face.v3 - coordsLen]; - - if (pathType == PathType.Linear) - { - newViewerFace.uv1.Flip(); - newViewerFace.uv2.Flip(); - newViewerFace.uv3.Flip(); - } - - this.viewerFaces.Add(newViewerFace); - } - } - - - } // for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++) - - } - - - /// - /// DEPRICATED - use Extrude(PathType.Linear) instead - /// Extrudes a profile along a straight line path. Used for prim types box, cylinder, and prism. - /// - /// - public void ExtrudeLinear() - { - this.Extrude(PathType.Linear); - } - - - /// - /// DEPRICATED - use Extrude(PathType.Circular) instead - /// Extrude a profile into a circular path prim mesh. Used for prim types torus, tube, and ring. - /// - /// - public void ExtrudeCircular() - { - this.Extrude(PathType.Circular); - } - - - private Coord SurfaceNormal(Coord c1, Coord c2, Coord c3) - { - Coord edge1 = new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z); - Coord edge2 = new Coord(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z); - - Coord normal = Coord.Cross(edge1, edge2); - - normal.Normalize(); - - return normal; - } - - private Coord SurfaceNormal(Face face) - { - return SurfaceNormal(this.coords[face.v1], this.coords[face.v2], this.coords[face.v3]); - } - - /// - /// Calculate the surface normal for a face in the list of faces - /// - /// - /// - public Coord SurfaceNormal(int faceIndex) - { - int numFaces = this.faces.Count; - if (faceIndex < 0 || faceIndex >= numFaces) - throw new Exception("faceIndex out of range"); - - return SurfaceNormal(this.faces[faceIndex]); - } - - /// - /// Duplicates a PrimMesh object. All object properties are copied by value, including lists. - /// - /// - public PrimMesh Copy() - { - PrimMesh copy = new PrimMesh(this.sides, this.profileStart, this.profileEnd, this.hollow, this.hollowSides); - copy.twistBegin = this.twistBegin; - copy.twistEnd = this.twistEnd; - copy.topShearX = this.topShearX; - copy.topShearY = this.topShearY; - copy.pathCutBegin = this.pathCutBegin; - copy.pathCutEnd = this.pathCutEnd; - copy.dimpleBegin = this.dimpleBegin; - copy.dimpleEnd = this.dimpleEnd; - copy.skew = this.skew; - copy.holeSizeX = this.holeSizeX; - copy.holeSizeY = this.holeSizeY; - copy.taperX = this.taperX; - copy.taperY = this.taperY; - copy.radius = this.radius; - copy.revolutions = this.revolutions; - copy.stepsPerRevolution = this.stepsPerRevolution; - copy.calcVertexNormals = this.calcVertexNormals; - copy.normalsProcessed = this.normalsProcessed; - copy.viewerMode = this.viewerMode; - copy.numPrimFaces = this.numPrimFaces; - copy.errorMessage = this.errorMessage; - - copy.coords = new List(this.coords); - copy.faces = new List(this.faces); - copy.viewerFaces = new List(this.viewerFaces); - copy.normals = new List(this.normals); - - return copy; - } - - /// - /// Calculate surface normals for all of the faces in the list of faces in this mesh - /// - public void CalcNormals() - { - if (normalsProcessed) - return; - - normalsProcessed = true; - - int numFaces = faces.Count; - - if (!this.calcVertexNormals) - this.normals = new List(); - - for (int i = 0; i < numFaces; i++) - { - Face face = faces[i]; - - this.normals.Add(SurfaceNormal(i).Normalize()); - - int normIndex = normals.Count - 1; - face.n1 = normIndex; - face.n2 = normIndex; - face.n3 = normIndex; - - this.faces[i] = face; - } - } - - /// - /// Adds a value to each XYZ vertex coordinate in the mesh - /// - /// - /// - /// - public void AddPos(float x, float y, float z) - { - int i; - int numVerts = this.coords.Count; - Coord vert; - - for (i = 0; i < numVerts; i++) - { - vert = this.coords[i]; - vert.X += x; - vert.Y += y; - vert.Z += z; - this.coords[i] = vert; - } - - if (this.viewerFaces != null) - { - int numViewerFaces = this.viewerFaces.Count; - - for (i = 0; i < numViewerFaces; i++) - { - ViewerFace v = this.viewerFaces[i]; - v.AddPos(x, y, z); - this.viewerFaces[i] = v; - } - } - } - - /// - /// Rotates the mesh - /// - /// - public void AddRot(Quat q) - { - int i; - int numVerts = this.coords.Count; - - for (i = 0; i < numVerts; i++) - this.coords[i] *= q; - - if (this.normals != null) - { - int numNormals = this.normals.Count; - for (i = 0; i < numNormals; i++) - this.normals[i] *= q; - } - - if (this.viewerFaces != null) - { - int numViewerFaces = this.viewerFaces.Count; - - for (i = 0; i < numViewerFaces; i++) - { - ViewerFace v = this.viewerFaces[i]; - v.v1 *= q; - v.v2 *= q; - v.v3 *= q; - - v.n1 *= q; - v.n2 *= q; - v.n3 *= q; - this.viewerFaces[i] = v; - } - } - } - -#if VERTEX_INDEXER - public VertexIndexer GetVertexIndexer() - { - if (this.viewerMode && this.viewerFaces.Count > 0) - return new VertexIndexer(this); - return null; - } -#endif - - /// - /// Scales the mesh - /// - /// - /// - /// - public void Scale(float x, float y, float z) - { - int i; - int numVerts = this.coords.Count; - //Coord vert; - - Coord m = new Coord(x, y, z); - for (i = 0; i < numVerts; i++) - this.coords[i] *= m; - - if (this.viewerFaces != null) - { - int numViewerFaces = this.viewerFaces.Count; - for (i = 0; i < numViewerFaces; i++) - { - ViewerFace v = this.viewerFaces[i]; - v.v1 *= m; - v.v2 *= m; - v.v3 *= m; - this.viewerFaces[i] = v; - } - - } - - } - - /// - /// Dumps the mesh to a Blender compatible "Raw" format file - /// - /// - /// - /// - public void DumpRaw(String path, String name, String title) - { - if (path == null) - return; - String fileName = name + "_" + title + ".raw"; - String completePath = System.IO.Path.Combine(path, fileName); - StreamWriter sw = new StreamWriter(completePath); - - for (int i = 0; i < this.faces.Count; i++) - { - string s = this.coords[this.faces[i].v1].ToString(); - s += " " + this.coords[this.faces[i].v2].ToString(); - s += " " + this.coords[this.faces[i].v3].ToString(); - - sw.WriteLine(s); - } - - sw.Close(); - } - } -} diff --git a/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs deleted file mode 100644 index 4cc1731..0000000 --- a/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("OpenSim.Region.Physics.Meshing")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("http://opensimulator.org")] -[assembly: AssemblyProduct("OpenSim")] -[assembly: AssemblyCopyright("OpenSimulator developers")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("4b7e35c2-a9dd-4b10-b778-eb417f4f6884")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -[assembly: AssemblyVersion("0.7.5.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/OpenSim/Region/Physics/Meshing/SculptMap.cs b/OpenSim/Region/Physics/Meshing/SculptMap.cs deleted file mode 100644 index 740424e..0000000 --- a/OpenSim/Region/Physics/Meshing/SculptMap.cs +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) Contributors - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// to build without references to System.Drawing, comment this out -#define SYSTEM_DRAWING - -using System; -using System.Collections.Generic; -using System.Text; - -#if SYSTEM_DRAWING -using System.Drawing; -using System.Drawing.Imaging; - -namespace PrimMesher -{ - public class SculptMap - { - public int width; - public int height; - public byte[] redBytes; - public byte[] greenBytes; - public byte[] blueBytes; - - public SculptMap() - { - } - - public SculptMap(Bitmap bm, int lod) - { - int bmW = bm.Width; - int bmH = bm.Height; - - if (bmW == 0 || bmH == 0) - throw new Exception("SculptMap: bitmap has no data"); - - int numLodPixels = lod * 2 * lod * 2; // (32 * 2)^2 = 64^2 pixels for default sculpt map image - - bool needsScaling = false; - - bool smallMap = bmW * bmH <= lod * lod; - - width = bmW; - height = bmH; - while (width * height > numLodPixels) - { - width >>= 1; - height >>= 1; - needsScaling = true; - } - - - - try - { - if (needsScaling) - bm = ScaleImage(bm, width, height, - System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor); - } - - catch (Exception e) - { - throw new Exception("Exception in ScaleImage(): e: " + e.ToString()); - } - - if (width * height > lod * lod) - { - width >>= 1; - height >>= 1; - } - - int numBytes = (width + 1) * (height + 1); - redBytes = new byte[numBytes]; - greenBytes = new byte[numBytes]; - blueBytes = new byte[numBytes]; - - int byteNdx = 0; - - try - { - for (int y = 0; y <= height; y++) - { - for (int x = 0; x <= width; x++) - { - Color c; - - if (smallMap) - c = bm.GetPixel(x < width ? x : x - 1, - y < height ? y : y - 1); - else - c = bm.GetPixel(x < width ? x * 2 : x * 2 - 1, - y < height ? y * 2 : y * 2 - 1); - - redBytes[byteNdx] = c.R; - greenBytes[byteNdx] = c.G; - blueBytes[byteNdx] = c.B; - - ++byteNdx; - } - } - } - catch (Exception e) - { - throw new Exception("Caught exception processing byte arrays in SculptMap(): e: " + e.ToString()); - } - - width++; - height++; - } - - public List> ToRows(bool mirror) - { - int numRows = height; - int numCols = width; - - List> rows = new List>(numRows); - - float pixScale = 1.0f / 255; - - int rowNdx, colNdx; - int smNdx = 0; - - for (rowNdx = 0; rowNdx < numRows; rowNdx++) - { - List row = new List(numCols); - for (colNdx = 0; colNdx < numCols; colNdx++) - { - if (mirror) - row.Add(new Coord(-(redBytes[smNdx] * pixScale - 0.5f), (greenBytes[smNdx] * pixScale - 0.5f), blueBytes[smNdx] * pixScale - 0.5f)); - else - row.Add(new Coord(redBytes[smNdx] * pixScale - 0.5f, greenBytes[smNdx] * pixScale - 0.5f, blueBytes[smNdx] * pixScale - 0.5f)); - - ++smNdx; - } - rows.Add(row); - } - return rows; - } - - private Bitmap ScaleImage(Bitmap srcImage, int destWidth, int destHeight, - System.Drawing.Drawing2D.InterpolationMode interpMode) - { - Bitmap scaledImage = new Bitmap(srcImage, destWidth, destHeight); - scaledImage.SetResolution(96.0f, 96.0f); - - Graphics grPhoto = Graphics.FromImage(scaledImage); - grPhoto.InterpolationMode = interpMode; - - grPhoto.DrawImage(srcImage, - new Rectangle(0, 0, destWidth, destHeight), - new Rectangle(0, 0, srcImage.Width, srcImage.Height), - GraphicsUnit.Pixel); - - grPhoto.Dispose(); - return scaledImage; - } - } -} -#endif diff --git a/OpenSim/Region/Physics/Meshing/SculptMesh.cs b/OpenSim/Region/Physics/Meshing/SculptMesh.cs deleted file mode 100644 index 4a7f3ad..0000000 --- a/OpenSim/Region/Physics/Meshing/SculptMesh.cs +++ /dev/null @@ -1,646 +0,0 @@ -/* - * Copyright (c) Contributors - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// to build without references to System.Drawing, comment this out -#define SYSTEM_DRAWING - -using System; -using System.Collections.Generic; -using System.Text; -using System.IO; - -#if SYSTEM_DRAWING -using System.Drawing; -using System.Drawing.Imaging; -#endif - -namespace PrimMesher -{ - - public class SculptMesh - { - public List coords; - public List faces; - - public List viewerFaces; - public List normals; - public List uvs; - - public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 }; - -#if SYSTEM_DRAWING - - public SculptMesh SculptMeshFromFile(string fileName, SculptType sculptType, int lod, bool viewerMode) - { - Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName); - SculptMesh sculptMesh = new SculptMesh(bitmap, sculptType, lod, viewerMode); - bitmap.Dispose(); - return sculptMesh; - } - - - public SculptMesh(string fileName, int sculptType, int lod, int viewerMode, int mirror, int invert) - { - Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName); - _SculptMesh(bitmap, (SculptType)sculptType, lod, viewerMode != 0, mirror != 0, invert != 0); - bitmap.Dispose(); - } -#endif - - /// - /// ** Experimental ** May disappear from future versions ** not recommeneded for use in applications - /// Construct a sculpt mesh from a 2D array of floats - /// - /// - /// - /// - /// - /// - /// - public SculptMesh(float[,] zMap, float xBegin, float xEnd, float yBegin, float yEnd, bool viewerMode) - { - float xStep, yStep; - float uStep, vStep; - - int numYElements = zMap.GetLength(0); - int numXElements = zMap.GetLength(1); - - try - { - xStep = (xEnd - xBegin) / (float)(numXElements - 1); - yStep = (yEnd - yBegin) / (float)(numYElements - 1); - - uStep = 1.0f / (numXElements - 1); - vStep = 1.0f / (numYElements - 1); - } - catch (DivideByZeroException) - { - return; - } - - coords = new List(); - faces = new List(); - normals = new List(); - uvs = new List(); - - viewerFaces = new List(); - - int p1, p2, p3, p4; - - int x, y; - int xStart = 0, yStart = 0; - - for (y = yStart; y < numYElements; y++) - { - int rowOffset = y * numXElements; - - for (x = xStart; x < numXElements; x++) - { - /* - * p1-----p2 - * | \ f2 | - * | \ | - * | f1 \| - * p3-----p4 - */ - - p4 = rowOffset + x; - p3 = p4 - 1; - - p2 = p4 - numXElements; - p1 = p3 - numXElements; - - Coord c = new Coord(xBegin + x * xStep, yBegin + y * yStep, zMap[y, x]); - this.coords.Add(c); - if (viewerMode) - { - this.normals.Add(new Coord()); - this.uvs.Add(new UVCoord(uStep * x, 1.0f - vStep * y)); - } - - if (y > 0 && x > 0) - { - Face f1, f2; - - if (viewerMode) - { - f1 = new Face(p1, p4, p3, p1, p4, p3); - f1.uv1 = p1; - f1.uv2 = p4; - f1.uv3 = p3; - - f2 = new Face(p1, p2, p4, p1, p2, p4); - f2.uv1 = p1; - f2.uv2 = p2; - f2.uv3 = p4; - } - else - { - f1 = new Face(p1, p4, p3); - f2 = new Face(p1, p2, p4); - } - - this.faces.Add(f1); - this.faces.Add(f2); - } - } - } - - if (viewerMode) - calcVertexNormals(SculptType.plane, numXElements, numYElements); - } - -#if SYSTEM_DRAWING - public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode) - { - _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, false, false); - } - - public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert) - { - _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, mirror, invert); - } -#endif - - public SculptMesh(List> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert) - { - _SculptMesh(rows, sculptType, viewerMode, mirror, invert); - } - -#if SYSTEM_DRAWING - /// - /// converts a bitmap to a list of lists of coords, while scaling the image. - /// the scaling is done in floating point so as to allow for reduced vertex position - /// quantization as the position will be averaged between pixel values. this routine will - /// likely fail if the bitmap width and height are not powers of 2. - /// - /// - /// - /// - /// - private List> bitmap2Coords(Bitmap bitmap, int scale, bool mirror) - { - int numRows = bitmap.Height / scale; - int numCols = bitmap.Width / scale; - List> rows = new List>(numRows); - - float pixScale = 1.0f / (scale * scale); - pixScale /= 255; - - int imageX, imageY = 0; - - int rowNdx, colNdx; - - for (rowNdx = 0; rowNdx < numRows; rowNdx++) - { - List row = new List(numCols); - for (colNdx = 0; colNdx < numCols; colNdx++) - { - imageX = colNdx * scale; - int imageYStart = rowNdx * scale; - int imageYEnd = imageYStart + scale; - int imageXEnd = imageX + scale; - float rSum = 0.0f; - float gSum = 0.0f; - float bSum = 0.0f; - for (; imageX < imageXEnd; imageX++) - { - for (imageY = imageYStart; imageY < imageYEnd; imageY++) - { - Color c = bitmap.GetPixel(imageX, imageY); - if (c.A != 255) - { - bitmap.SetPixel(imageX, imageY, Color.FromArgb(255, c.R, c.G, c.B)); - c = bitmap.GetPixel(imageX, imageY); - } - rSum += c.R; - gSum += c.G; - bSum += c.B; - } - } - if (mirror) - row.Add(new Coord(-(rSum * pixScale - 0.5f), gSum * pixScale - 0.5f, bSum * pixScale - 0.5f)); - else - row.Add(new Coord(rSum * pixScale - 0.5f, gSum * pixScale - 0.5f, bSum * pixScale - 0.5f)); - - } - rows.Add(row); - } - return rows; - } - - private List> bitmap2CoordsSampled(Bitmap bitmap, int scale, bool mirror) - { - int numRows = bitmap.Height / scale; - int numCols = bitmap.Width / scale; - List> rows = new List>(numRows); - - float pixScale = 1.0f / 256.0f; - - int imageX, imageY = 0; - - int rowNdx, colNdx; - - for (rowNdx = 0; rowNdx <= numRows; rowNdx++) - { - List row = new List(numCols); - imageY = rowNdx * scale; - if (rowNdx == numRows) imageY--; - for (colNdx = 0; colNdx <= numCols; colNdx++) - { - imageX = colNdx * scale; - if (colNdx == numCols) imageX--; - - Color c = bitmap.GetPixel(imageX, imageY); - if (c.A != 255) - { - bitmap.SetPixel(imageX, imageY, Color.FromArgb(255, c.R, c.G, c.B)); - c = bitmap.GetPixel(imageX, imageY); - } - - if (mirror) - row.Add(new Coord(-(c.R * pixScale - 0.5f), c.G * pixScale - 0.5f, c.B * pixScale - 0.5f)); - else - row.Add(new Coord(c.R * pixScale - 0.5f, c.G * pixScale - 0.5f, c.B * pixScale - 0.5f)); - - } - rows.Add(row); - } - return rows; - } - - - void _SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert) - { - _SculptMesh(new SculptMap(sculptBitmap, lod).ToRows(mirror), sculptType, viewerMode, mirror, invert); - } -#endif - - void _SculptMesh(List> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert) - { - coords = new List(); - faces = new List(); - normals = new List(); - uvs = new List(); - - sculptType = (SculptType)(((int)sculptType) & 0x07); - - if (mirror) - invert = !invert; - - viewerFaces = new List(); - - int width = rows[0].Count; - - int p1, p2, p3, p4; - - int imageX, imageY; - - if (sculptType != SculptType.plane) - { - if (rows.Count % 2 == 0) - { - for (int rowNdx = 0; rowNdx < rows.Count; rowNdx++) - rows[rowNdx].Add(rows[rowNdx][0]); - } - else - { - int lastIndex = rows[0].Count - 1; - - for (int i = 0; i < rows.Count; i++) - rows[i][0] = rows[i][lastIndex]; - } - } - - Coord topPole = rows[0][width / 2]; - Coord bottomPole = rows[rows.Count - 1][width / 2]; - - if (sculptType == SculptType.sphere) - { - if (rows.Count % 2 == 0) - { - int count = rows[0].Count; - List topPoleRow = new List(count); - List bottomPoleRow = new List(count); - - for (int i = 0; i < count; i++) - { - topPoleRow.Add(topPole); - bottomPoleRow.Add(bottomPole); - } - rows.Insert(0, topPoleRow); - rows.Add(bottomPoleRow); - } - else - { - int count = rows[0].Count; - - List topPoleRow = rows[0]; - List bottomPoleRow = rows[rows.Count - 1]; - - for (int i = 0; i < count; i++) - { - topPoleRow[i] = topPole; - bottomPoleRow[i] = bottomPole; - } - } - } - - if (sculptType == SculptType.torus) - rows.Add(rows[0]); - - int coordsDown = rows.Count; - int coordsAcross = rows[0].Count; -// int lastColumn = coordsAcross - 1; - - float widthUnit = 1.0f / (coordsAcross - 1); - float heightUnit = 1.0f / (coordsDown - 1); - - for (imageY = 0; imageY < coordsDown; imageY++) - { - int rowOffset = imageY * coordsAcross; - - for (imageX = 0; imageX < coordsAcross; imageX++) - { - /* - * p1-----p2 - * | \ f2 | - * | \ | - * | f1 \| - * p3-----p4 - */ - - p4 = rowOffset + imageX; - p3 = p4 - 1; - - p2 = p4 - coordsAcross; - p1 = p3 - coordsAcross; - - this.coords.Add(rows[imageY][imageX]); - if (viewerMode) - { - this.normals.Add(new Coord()); - this.uvs.Add(new UVCoord(widthUnit * imageX, heightUnit * imageY)); - } - - if (imageY > 0 && imageX > 0) - { - Face f1, f2; - - if (viewerMode) - { - if (invert) - { - f1 = new Face(p1, p4, p3, p1, p4, p3); - f1.uv1 = p1; - f1.uv2 = p4; - f1.uv3 = p3; - - f2 = new Face(p1, p2, p4, p1, p2, p4); - f2.uv1 = p1; - f2.uv2 = p2; - f2.uv3 = p4; - } - else - { - f1 = new Face(p1, p3, p4, p1, p3, p4); - f1.uv1 = p1; - f1.uv2 = p3; - f1.uv3 = p4; - - f2 = new Face(p1, p4, p2, p1, p4, p2); - f2.uv1 = p1; - f2.uv2 = p4; - f2.uv3 = p2; - } - } - else - { - if (invert) - { - f1 = new Face(p1, p4, p3); - f2 = new Face(p1, p2, p4); - } - else - { - f1 = new Face(p1, p3, p4); - f2 = new Face(p1, p4, p2); - } - } - - this.faces.Add(f1); - this.faces.Add(f2); - } - } - } - - if (viewerMode) - calcVertexNormals(sculptType, coordsAcross, coordsDown); - } - - /// - /// Duplicates a SculptMesh object. All object properties are copied by value, including lists. - /// - /// - public SculptMesh Copy() - { - return new SculptMesh(this); - } - - public SculptMesh(SculptMesh sm) - { - coords = new List(sm.coords); - faces = new List(sm.faces); - viewerFaces = new List(sm.viewerFaces); - normals = new List(sm.normals); - uvs = new List(sm.uvs); - } - - private void calcVertexNormals(SculptType sculptType, int xSize, int ySize) - { // compute vertex normals by summing all the surface normals of all the triangles sharing - // each vertex and then normalizing - int numFaces = this.faces.Count; - for (int i = 0; i < numFaces; i++) - { - Face face = this.faces[i]; - Coord surfaceNormal = face.SurfaceNormal(this.coords); - this.normals[face.n1] += surfaceNormal; - this.normals[face.n2] += surfaceNormal; - this.normals[face.n3] += surfaceNormal; - } - - int numNormals = this.normals.Count; - for (int i = 0; i < numNormals; i++) - this.normals[i] = this.normals[i].Normalize(); - - if (sculptType != SculptType.plane) - { // blend the vertex normals at the cylinder seam - for (int y = 0; y < ySize; y++) - { - int rowOffset = y * xSize; - - this.normals[rowOffset] = this.normals[rowOffset + xSize - 1] = (this.normals[rowOffset] + this.normals[rowOffset + xSize - 1]).Normalize(); - } - } - - foreach (Face face in this.faces) - { - ViewerFace vf = new ViewerFace(0); - vf.v1 = this.coords[face.v1]; - vf.v2 = this.coords[face.v2]; - vf.v3 = this.coords[face.v3]; - - vf.coordIndex1 = face.v1; - vf.coordIndex2 = face.v2; - vf.coordIndex3 = face.v3; - - vf.n1 = this.normals[face.n1]; - vf.n2 = this.normals[face.n2]; - vf.n3 = this.normals[face.n3]; - - vf.uv1 = this.uvs[face.uv1]; - vf.uv2 = this.uvs[face.uv2]; - vf.uv3 = this.uvs[face.uv3]; - - this.viewerFaces.Add(vf); - } - } - - /// - /// Adds a value to each XYZ vertex coordinate in the mesh - /// - /// - /// - /// - public void AddPos(float x, float y, float z) - { - int i; - int numVerts = this.coords.Count; - Coord vert; - - for (i = 0; i < numVerts; i++) - { - vert = this.coords[i]; - vert.X += x; - vert.Y += y; - vert.Z += z; - this.coords[i] = vert; - } - - if (this.viewerFaces != null) - { - int numViewerFaces = this.viewerFaces.Count; - - for (i = 0; i < numViewerFaces; i++) - { - ViewerFace v = this.viewerFaces[i]; - v.AddPos(x, y, z); - this.viewerFaces[i] = v; - } - } - } - - /// - /// Rotates the mesh - /// - /// - public void AddRot(Quat q) - { - int i; - int numVerts = this.coords.Count; - - for (i = 0; i < numVerts; i++) - this.coords[i] *= q; - - int numNormals = this.normals.Count; - for (i = 0; i < numNormals; i++) - this.normals[i] *= q; - - if (this.viewerFaces != null) - { - int numViewerFaces = this.viewerFaces.Count; - - for (i = 0; i < numViewerFaces; i++) - { - ViewerFace v = this.viewerFaces[i]; - v.v1 *= q; - v.v2 *= q; - v.v3 *= q; - - v.n1 *= q; - v.n2 *= q; - v.n3 *= q; - - this.viewerFaces[i] = v; - } - } - } - - public void Scale(float x, float y, float z) - { - int i; - int numVerts = this.coords.Count; - - Coord m = new Coord(x, y, z); - for (i = 0; i < numVerts; i++) - this.coords[i] *= m; - - if (this.viewerFaces != null) - { - int numViewerFaces = this.viewerFaces.Count; - for (i = 0; i < numViewerFaces; i++) - { - ViewerFace v = this.viewerFaces[i]; - v.v1 *= m; - v.v2 *= m; - v.v3 *= m; - this.viewerFaces[i] = v; - } - } - } - - public void DumpRaw(String path, String name, String title) - { - if (path == null) - return; - String fileName = name + "_" + title + ".raw"; - String completePath = System.IO.Path.Combine(path, fileName); - StreamWriter sw = new StreamWriter(completePath); - - for (int i = 0; i < this.faces.Count; i++) - { - string s = this.coords[this.faces[i].v1].ToString(); - s += " " + this.coords[this.faces[i].v2].ToString(); - s += " " + this.coords[this.faces[i].v3].ToString(); - - sw.WriteLine(s); - } - - sw.Close(); - } - } -} diff --git a/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs deleted file mode 100644 index 3c4f06a..0000000 --- a/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Reflection; -using System.Runtime.InteropServices; - -// Information about this assembly is defined by the following -// attributes. -// -// change them to the information which is associated with the assembly -// you compile. - -[assembly : AssemblyTitle("OdePlugin")] -[assembly : AssemblyDescription("")] -[assembly : AssemblyConfiguration("")] -[assembly : AssemblyCompany("http://opensimulator.org")] -[assembly : AssemblyProduct("OdePlugin")] -[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers")] -[assembly : AssemblyTrademark("")] -[assembly : AssemblyCulture("")] - -// This sets the default COM visibility of types in the assembly to invisible. -// If you need to expose a type to COM, use [ComVisible(true)] on that type. - -[assembly : ComVisible(false)] - -// The assembly version has following format : -// -// Major.Minor.Build.Revision -// -// You can specify all values by your own or you can build default build and revision -// numbers with the '*' character (the default): - -[assembly : AssemblyVersion("0.7.5.*")] diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs deleted file mode 100644 index 319f6ab..0000000 --- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs +++ /dev/null @@ -1,1411 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using OpenMetaverse; -using Ode.NET; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; -using log4net; - -namespace OpenSim.Region.Physics.OdePlugin -{ - /// - /// Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ourselves. - /// - public enum dParam : int - { - LowStop = 0, - HiStop = 1, - Vel = 2, - FMax = 3, - FudgeFactor = 4, - Bounce = 5, - CFM = 6, - StopERP = 7, - StopCFM = 8, - LoStop2 = 256, - HiStop2 = 257, - Vel2 = 258, - FMax2 = 259, - StopERP2 = 7 + 256, - StopCFM2 = 8 + 256, - LoStop3 = 512, - HiStop3 = 513, - Vel3 = 514, - FMax3 = 515, - StopERP3 = 7 + 512, - StopCFM3 = 8 + 512 - } - - public class OdeCharacter : PhysicsActor - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private Vector3 _position; - private d.Vector3 _zeroPosition; - private bool _zeroFlag = false; - private bool m_lastUpdateSent = false; - private Vector3 _velocity; - private Vector3 m_taintTargetVelocity; - private Vector3 _target_velocity; - private Vector3 _acceleration; - private Vector3 m_rotationalVelocity; - private float m_mass = 80f; - private float m_density = 60f; - private bool m_pidControllerActive = true; - private float PID_D = 800.0f; - private float PID_P = 900.0f; - //private static float POSTURE_SERVO = 10000.0f; - private float CAPSULE_RADIUS = 0.37f; - private float CAPSULE_LENGTH = 2.140599f; - private float m_tensor = 3800000f; -// private float heightFudgeFactor = 0.52f; - private float walkDivisor = 1.3f; - private float runDivisor = 0.8f; - private bool flying = false; - private bool m_iscolliding = false; - private bool m_iscollidingGround = false; - private bool m_wascolliding = false; - private bool m_wascollidingGround = false; - private bool m_iscollidingObj = false; - private bool m_alwaysRun = false; - private bool m_hackSentFall = false; - private bool m_hackSentFly = false; - private int m_requestedUpdateFrequency = 0; - private Vector3 m_taintPosition; - internal bool m_avatarplanted = false; - /// - /// Hold set forces so we can process them outside physics calculations. This prevents race conditions if we set force - /// while calculatios are going on - /// - private Vector3 m_taintForce; - - // taints and their non-tainted counterparts - private bool m_isPhysical = false; // the current physical status - private bool m_tainted_isPhysical = false; // set when the physical status is tainted (false=not existing in physics engine, true=existing) - internal float MinimumGroundFlightOffset = 3f; - - private float m_tainted_CAPSULE_LENGTH; // set when the capsule length changes. - - /// - /// Base movement for calculating tilt. - /// - private float m_tiltBaseMovement = (float)Math.Sqrt(2); - - /// - /// Used to introduce a fixed tilt because a straight-up capsule falls through terrain, probably a bug in terrain collider - /// - private float m_tiltMagnitudeWhenProjectedOnXYPlane = 0.1131371f; - - private float m_buoyancy = 0f; - - // private CollisionLocker ode; - private bool[] m_colliderarr = new bool[11]; - private bool[] m_colliderGroundarr = new bool[11]; - - // Default we're a Character - private CollisionCategories m_collisionCategories = (CollisionCategories.Character); - - // Default, Collide with Other Geometries, spaces, bodies and characters. - private CollisionCategories m_collisionFlags = (CollisionCategories.Geom - | CollisionCategories.Space - | CollisionCategories.Body - | CollisionCategories.Character - | CollisionCategories.Land); - /// - /// Body for dynamics simulation - /// - internal IntPtr Body { get; private set; } - - private OdeScene _parent_scene; - - /// - /// Collision geometry - /// - internal IntPtr Shell { get; private set; } - - private IntPtr Amotor = IntPtr.Zero; - private d.Mass ShellMass; - - private int m_eventsubscription = 0; - private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate(); - - // unique UUID of this character object - internal UUID m_uuid { get; private set; } - internal bool bad = false; - - /// - /// ODE Avatar. - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// Only used right now to return information to LSL. Not actually used to set mass in ODE! - /// - /// - /// - public OdeCharacter( - String avName, OdeScene parent_scene, Vector3 pos, Vector3 size, float pid_d, float pid_p, - float capsule_radius, float tensor, float density, - float walk_divisor, float rundivisor) - { - m_uuid = UUID.Random(); - - if (pos.IsFinite()) - { - if (pos.Z > 9999999f) - { - pos.Z = parent_scene.GetTerrainHeightAtXY(127, 127) + 5; - } - if (pos.Z < -90000f) - { - pos.Z = parent_scene.GetTerrainHeightAtXY(127, 127) + 5; - } - - _position = pos; - m_taintPosition = pos; - } - else - { - _position - = new Vector3( - (float)_parent_scene.WorldExtents.X * 0.5f, - (float)_parent_scene.WorldExtents.Y * 0.5f, - parent_scene.GetTerrainHeightAtXY(128f, 128f) + 10f); - m_taintPosition = _position; - - m_log.WarnFormat("[ODE CHARACTER]: Got NaN Position on Character Create for {0}", avName); - } - - _parent_scene = parent_scene; - - PID_D = pid_d; - PID_P = pid_p; - CAPSULE_RADIUS = capsule_radius; - m_tensor = tensor; - m_density = density; -// heightFudgeFactor = height_fudge_factor; - walkDivisor = walk_divisor; - runDivisor = rundivisor; - - // m_StandUpRotation = - // new d.Matrix3(0.5f, 0.7071068f, 0.5f, -0.7071068f, 0f, 0.7071068f, 0.5f, -0.7071068f, - // 0.5f); - - // We can set taint and actual to be the same here, since the entire character will be set up when the - // m_tainted_isPhysical is processed. - SetTaintedCapsuleLength(size); - CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH; - - m_isPhysical = false; // current status: no ODE information exists - m_tainted_isPhysical = true; // new tainted status: need to create ODE information - - _parent_scene.AddPhysicsActorTaint(this); - - Name = avName; - } - - public override int PhysicsActorType - { - get { return (int) ActorTypes.Agent; } - set { return; } - } - - /// - /// If this is set, the avatar will move faster - /// - public override bool SetAlwaysRun - { - get { return m_alwaysRun; } - set { m_alwaysRun = value; } - } - - public override bool Grabbed - { - set { return; } - } - - public override bool Selected - { - set { return; } - } - - public override float Buoyancy - { - get { return m_buoyancy; } - set { m_buoyancy = value; } - } - - public override bool FloatOnWater - { - set { return; } - } - - public override bool IsPhysical - { - get { return false; } - set { return; } - } - - public override bool ThrottleUpdates - { - get { return false; } - set { return; } - } - - public override bool Flying - { - get { return flying; } - set - { - flying = value; -// m_log.DebugFormat("[ODE CHARACTER]: Set OdeCharacter Flying to {0}", flying); - } - } - - /// - /// Returns if the avatar is colliding in general. - /// This includes the ground and objects and avatar. - /// - public override bool IsColliding - { - get { return m_iscolliding; } - set - { - int i; - int truecount = 0; - int falsecount = 0; - - if (m_colliderarr.Length >= 10) - { - for (i = 0; i < 10; i++) - { - m_colliderarr[i] = m_colliderarr[i + 1]; - } - } - m_colliderarr[10] = value; - - for (i = 0; i < 11; i++) - { - if (m_colliderarr[i]) - { - truecount++; - } - else - { - falsecount++; - } - } - - // Equal truecounts and false counts means we're colliding with something. - - if (falsecount > 1.2*truecount) - { - m_iscolliding = false; - } - else - { - m_iscolliding = true; - } - - if (m_wascolliding != m_iscolliding) - { - //base.SendCollisionUpdate(new CollisionEventUpdate()); - } - - m_wascolliding = m_iscolliding; - } - } - - /// - /// Returns if an avatar is colliding with the ground - /// - public override bool CollidingGround - { - get { return m_iscollidingGround; } - set - { - // Collisions against the ground are not really reliable - // So, to get a consistant value we have to average the current result over time - // Currently we use 1 second = 10 calls to this. - int i; - int truecount = 0; - int falsecount = 0; - - if (m_colliderGroundarr.Length >= 10) - { - for (i = 0; i < 10; i++) - { - m_colliderGroundarr[i] = m_colliderGroundarr[i + 1]; - } - } - m_colliderGroundarr[10] = value; - - for (i = 0; i < 11; i++) - { - if (m_colliderGroundarr[i]) - { - truecount++; - } - else - { - falsecount++; - } - } - - // Equal truecounts and false counts means we're colliding with something. - - if (falsecount > 1.2*truecount) - { - m_iscollidingGround = false; - } - else - { - m_iscollidingGround = true; - } - if (m_wascollidingGround != m_iscollidingGround) - { - //base.SendCollisionUpdate(new CollisionEventUpdate()); - } - m_wascollidingGround = m_iscollidingGround; - } - } - - /// - /// Returns if the avatar is colliding with an object - /// - public override bool CollidingObj - { - get { return m_iscollidingObj; } - set - { - m_iscollidingObj = value; - if (value && !m_avatarplanted) - m_pidControllerActive = false; - else - m_pidControllerActive = true; - } - } - - /// - /// turn the PID controller on or off. - /// The PID Controller will turn on all by itself in many situations - /// - /// - public void SetPidStatus(bool status) - { - m_pidControllerActive = status; - } - - public override bool Stopped - { - get { return _zeroFlag; } - } - - /// - /// This 'puts' an avatar somewhere in the physics space. - /// Not really a good choice unless you 'know' it's a good - /// spot otherwise you're likely to orbit the avatar. - /// - public override Vector3 Position - { - get { return _position; } - set - { - if (Body == IntPtr.Zero || Shell == IntPtr.Zero) - { - if (value.IsFinite()) - { - if (value.Z > 9999999f) - { - value.Z = _parent_scene.GetTerrainHeightAtXY(127, 127) + 5; - } - if (value.Z < -90000f) - { - value.Z = _parent_scene.GetTerrainHeightAtXY(127, 127) + 5; - } - - m_taintPosition = value; - _parent_scene.AddPhysicsActorTaint(this); - } - else - { - m_log.WarnFormat("[ODE CHARACTER]: Got a NaN Position from Scene on character {0}", Name); - } - } - } - } - - public override Vector3 RotationalVelocity - { - get { return m_rotationalVelocity; } - set { m_rotationalVelocity = value; } - } - - /// - /// This property sets the height of the avatar only. We use the height to make sure the avatar stands up straight - /// and use it to offset landings properly - /// - public override Vector3 Size - { - get { return new Vector3(CAPSULE_RADIUS * 2, CAPSULE_RADIUS * 2, CAPSULE_LENGTH); } - set - { - SetTaintedCapsuleLength(value); - - // If we reset velocity here, then an avatar stalls when it crosses a border for the first time - // (as the height of the new root agent is set). -// Velocity = Vector3.Zero; - - _parent_scene.AddPhysicsActorTaint(this); - } - } - - private void SetTaintedCapsuleLength(Vector3 size) - { - if (size.IsFinite()) - { - m_pidControllerActive = true; - - m_tainted_CAPSULE_LENGTH = (size.Z * 1.15f) - CAPSULE_RADIUS * 2.0f; -// m_log.Info("[ODE CHARACTER]: " + CAPSULE_LENGTH); - } - else - { - m_log.WarnFormat("[ODE CHARACTER]: Got a NaN Size for {0} in {1}", Name, _parent_scene.Name); - } - } - - private void AlignAvatarTiltWithCurrentDirectionOfMovement(Vector3 movementVector) - { - movementVector.Z = 0f; - float magnitude = (float)Math.Sqrt((double)(movementVector.X * movementVector.X + movementVector.Y * movementVector.Y)); - if (magnitude < 0.1f) return; - - // normalize the velocity vector - float invMagnitude = 1.0f / magnitude; - movementVector.X *= invMagnitude; - movementVector.Y *= invMagnitude; - - // if we change the capsule heading too often, the capsule can fall down - // therefore we snap movement vector to just 1 of 4 predefined directions (ne, nw, se, sw), - // meaning only 4 possible capsule tilt orientations - if (movementVector.X > 0) - { - // east - if (movementVector.Y > 0) - { - // northeast - movementVector.X = m_tiltBaseMovement; - movementVector.Y = m_tiltBaseMovement; - } - else - { - // southeast - movementVector.X = m_tiltBaseMovement; - movementVector.Y = -m_tiltBaseMovement; - } - } - else - { - // west - if (movementVector.Y > 0) - { - // northwest - movementVector.X = -m_tiltBaseMovement; - movementVector.Y = m_tiltBaseMovement; - } - else - { - // southwest - movementVector.X = -m_tiltBaseMovement; - movementVector.Y = -m_tiltBaseMovement; - } - } - - // movementVector.Z is zero - - // calculate tilt components based on desired amount of tilt and current (snapped) heading. - // the "-" sign is to force the tilt to be OPPOSITE the direction of movement. - float xTiltComponent = -movementVector.X * m_tiltMagnitudeWhenProjectedOnXYPlane; - float yTiltComponent = -movementVector.Y * m_tiltMagnitudeWhenProjectedOnXYPlane; - - //m_log.Debug("[ODE CHARACTER]: changing avatar tilt"); - d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, xTiltComponent); - d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, xTiltComponent); // must be same as lowstop, else a different, spurious tilt is introduced - d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, yTiltComponent); - d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, yTiltComponent); // same as lowstop - d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, 0f); - d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); // same as lowstop - } - - /// - /// Uses the capped cyllinder volume formula to calculate the avatar's mass. - /// This may be used in calculations in the scene/scenepresence - /// - public override float Mass - { - get - { - float AVvolume = (float)(Math.PI * Math.Pow(CAPSULE_RADIUS, 2) * CAPSULE_LENGTH); - return m_density * AVvolume; - } - } - - public override void link(PhysicsActor obj) {} - - public override void delink() {} - - public override void LockAngularMotion(Vector3 axis) {} - -// This code is very useful. Written by DanX0r. We're just not using it right now. -// Commented out to prevent a warning. -// -// private void standupStraight() -// { -// // The purpose of this routine here is to quickly stabilize the Body while it's popped up in the air. -// // The amotor needs a few seconds to stabilize so without it, the avatar shoots up sky high when you -// // change appearance and when you enter the simulator -// // After this routine is done, the amotor stabilizes much quicker -// d.Vector3 feet; -// d.Vector3 head; -// d.BodyGetRelPointPos(Body, 0.0f, 0.0f, -1.0f, out feet); -// d.BodyGetRelPointPos(Body, 0.0f, 0.0f, 1.0f, out head); -// float posture = head.Z - feet.Z; - -// // restoring force proportional to lack of posture: -// float servo = (2.5f - posture) * POSTURE_SERVO; -// d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f); -// d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f); -// //d.Matrix3 bodyrotation = d.BodyGetRotation(Body); -// //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyFArotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22); -// } - - public override Vector3 Force - { - get { return _target_velocity; } - set { return; } - } - - 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) - { - } - - public override void SetVolumeDetect(int param) - { - } - - public override Vector3 CenterOfMass - { - get { return Vector3.Zero; } - } - - public override Vector3 GeometricCenter - { - get { return Vector3.Zero; } - } - - public override PrimitiveBaseShape Shape - { - set { return; } - } - - public override Vector3 TargetVelocity - { - get - { - return m_taintTargetVelocity; - } - - set - { - Velocity = value; - } - } - - - public override Vector3 Velocity - { - get - { - // There's a problem with Vector3.Zero! Don't Use it Here! - if (_zeroFlag) - return Vector3.Zero; - m_lastUpdateSent = false; - return _velocity; - } - - set - { - if (value.IsFinite()) - { - m_pidControllerActive = true; - m_taintTargetVelocity = value; - _parent_scene.AddPhysicsActorTaint(this); - } - else - { - m_log.WarnFormat("[ODE CHARACTER]: Got a NaN velocity from Scene for {0}", Name); - } - -// m_log.DebugFormat("[PHYSICS]: Set target velocity of {0}", m_taintTargetVelocity); - } - } - - public override Vector3 Torque - { - get { return Vector3.Zero; } - set { return; } - } - - public override float CollisionScore - { - get { return 0f; } - set { } - } - - public override bool Kinematic - { - get { return false; } - set { } - } - - public override Quaternion Orientation - { - get { return Quaternion.Identity; } - set { - //Matrix3 or = Orientation.ToRotationMatrix(); - //d.Matrix3 ord = new d.Matrix3(or.m00, or.m10, or.m20, or.m01, or.m11, or.m21, or.m02, or.m12, or.m22); - //d.BodySetRotation(Body, ref ord); - } - } - - public override Vector3 Acceleration - { - get { return _acceleration; } - set { _acceleration = value; } - } - - /// - /// Adds the force supplied to the Target Velocity - /// The PID controller takes this target velocity and tries to make it a reality - /// - /// - public override void AddForce(Vector3 force, bool pushforce) - { - if (force.IsFinite()) - { - if (pushforce) - { - m_pidControllerActive = false; - force *= 100f; - m_taintForce += force; - _parent_scene.AddPhysicsActorTaint(this); - - // If uncommented, things get pushed off world - // - // m_log.Debug("Push!"); - // m_taintTargetVelocity.X += force.X; - // m_taintTargetVelocity.Y += force.Y; - // m_taintTargetVelocity.Z += force.Z; - } - else - { - m_pidControllerActive = true; - m_taintTargetVelocity += force; - } - } - else - { - m_log.WarnFormat("[ODE CHARACTER]: Got a NaN force applied to {0}", Name); - } - //m_lastUpdateSent = false; - } - - public override void AddAngularForce(Vector3 force, bool pushforce) - { - } - - public override void SetMomentum(Vector3 momentum) - { - } - - /// - /// Called from Simulate - /// This is the avatar's movement control + PID Controller - /// - /// The character will be added to this list if there is something wrong (non-finite - /// position or velocity). - /// - internal void Move(List defects) - { - // no lock; for now it's only called from within Simulate() - - // If the PID Controller isn't active then we set our force - // calculating base velocity to the current position - - if (Body == IntPtr.Zero) - return; - - if (m_pidControllerActive == false) - { - _zeroPosition = d.BodyGetPosition(Body); - } - //PidStatus = true; - - d.Vector3 localpos = d.BodyGetPosition(Body); - Vector3 localPos = new Vector3(localpos.X, localpos.Y, localpos.Z); - - if (!localPos.IsFinite()) - { - m_log.WarnFormat( - "[ODE CHARACTER]: Avatar position of {0} for {1} is non-finite! Removing from physics scene.", - localPos, Name); - - defects.Add(this); - - return; - } - - Vector3 vec = Vector3.Zero; - d.Vector3 vel = d.BodyGetLinearVel(Body); - -// m_log.DebugFormat( -// "[ODE CHARACTER]: Current velocity in Move() is <{0},{1},{2}>, target {3} for {4}", -// vel.X, vel.Y, vel.Z, _target_velocity, Name); - - float movementdivisor = 1f; - - if (!m_alwaysRun) - { - movementdivisor = walkDivisor; - } - else - { - movementdivisor = runDivisor; - } - - // if velocity is zero, use position control; otherwise, velocity control - if (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f && m_iscolliding) - { - // keep track of where we stopped. No more slippin' & slidin' - if (!_zeroFlag) - { - _zeroFlag = true; - _zeroPosition = d.BodyGetPosition(Body); - } - - if (m_pidControllerActive) - { - // We only want to deactivate the PID Controller if we think we want to have our surrogate - // react to the physics scene by moving it's position. - // Avatar to Avatar collisions - // Prim to avatar collisions - - d.Vector3 pos = d.BodyGetPosition(Body); - vec.X = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2); - vec.Y = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y)* (PID_P * 2); - if (flying) - { - vec.Z = (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P; - } - } - //PidStatus = true; - } - else - { - m_pidControllerActive = true; - _zeroFlag = false; - if (m_iscolliding && !flying) - { - // We're standing on something - vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D); - vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D); - } - else if (m_iscolliding && flying) - { - // We're flying and colliding with something - vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 16); - vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 16); - } - else if (!m_iscolliding && flying) - { - // we're in mid air suspended - vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 6); - vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 6); - -// m_log.DebugFormat( -// "[ODE CHARACTER]: !m_iscolliding && flying, vec {0}, _target_velocity {1}, movementdivisor {2}, vel {3}", -// vec, _target_velocity, movementdivisor, vel); - } - - if (m_iscolliding && !flying && _target_velocity.Z > 0.0f) - { - // We're colliding with something and we're not flying but we're moving - // This means we're walking or running. - d.Vector3 pos = d.BodyGetPosition(Body); - vec.Z = (_target_velocity.Z - vel.Z)*PID_D + (_zeroPosition.Z - pos.Z)*PID_P; - if (_target_velocity.X > 0) - { - vec.X = ((_target_velocity.X - vel.X) / 1.2f) * PID_D; - } - if (_target_velocity.Y > 0) - { - vec.Y = ((_target_velocity.Y - vel.Y) / 1.2f) * PID_D; - } - } - else if (!m_iscolliding && !flying) - { - // we're not colliding and we're not flying so that means we're falling! - // m_iscolliding includes collisions with the ground. - - // d.Vector3 pos = d.BodyGetPosition(Body); - if (_target_velocity.X > 0) - { - vec.X = ((_target_velocity.X - vel.X) / 1.2f) * PID_D; - } - if (_target_velocity.Y > 0) - { - vec.Y = ((_target_velocity.Y - vel.Y) / 1.2f) * PID_D; - } - } - - if (flying) - { - // This also acts as anti-gravity so that we hover when flying rather than fall. - vec.Z = (_target_velocity.Z - vel.Z) * (PID_D); - } - } - - if (flying) - { - // Anti-gravity so that we hover when flying rather than fall. - vec.Z += ((-1 * _parent_scene.gravityz) * m_mass); - - //Added for auto fly height. Kitto Flora - //d.Vector3 pos = d.BodyGetPosition(Body); - float target_altitude = _parent_scene.GetTerrainHeightAtXY(_position.X, _position.Y) + MinimumGroundFlightOffset; - - if (_position.Z < target_altitude) - { - vec.Z += (target_altitude - _position.Z) * PID_P * 5.0f; - } - // end add Kitto Flora - } - - if (vec.IsFinite()) - { - // Apply the total force acting on this avatar - d.BodyAddForce(Body, vec.X, vec.Y, vec.Z); - - if (!_zeroFlag) - AlignAvatarTiltWithCurrentDirectionOfMovement(vec); - } - else - { - m_log.WarnFormat( - "[ODE CHARACTER]: Got a NaN force vector {0} in Move() for {1}. Removing character from physics scene.", - vec, Name); - - defects.Add(this); - - return; - } - - d.Vector3 newVel = d.BodyGetLinearVel(Body); - if (newVel.X >= 256 || newVel.X <= 256 || newVel.Y >= 256 || newVel.Y <= 256 || newVel.Z >= 256 || newVel.Z <= 256) - { -// m_log.DebugFormat( -// "[ODE CHARACTER]: Limiting falling velocity from {0} to {1} for {2}", newVel.Z, -9.8, Name); - - newVel.X = Util.Clamp(newVel.X, -255f, 255f); - newVel.Y = Util.Clamp(newVel.Y, -255f, 255f); - - if (!flying) - newVel.Z - = Util.Clamp( - newVel.Z, -_parent_scene.AvatarTerminalVelocity, _parent_scene.AvatarTerminalVelocity); - else - newVel.Z = Util.Clamp(newVel.Z, -255f, 255f); - - d.BodySetLinearVel(Body, newVel.X, newVel.Y, newVel.Z); - } - } - - /// - /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence. - /// - /// The character will be added to this list if there is something wrong (non-finite - /// position or velocity). - /// - internal void UpdatePositionAndVelocity(List defects) - { - // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! - d.Vector3 newPos; - try - { - newPos = d.BodyGetPosition(Body); - } - catch (NullReferenceException) - { - bad = true; - defects.Add(this); - newPos = new d.Vector3(_position.X, _position.Y, _position.Z); - base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem! - m_log.WarnFormat("[ODE CHARACTER]: Avatar Null reference for Avatar {0}, physical actor {1}", Name, m_uuid); - - return; - } - - // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!) - if (newPos.X < 0.0f) newPos.X = 0.0f; - if (newPos.Y < 0.0f) newPos.Y = 0.0f; - if (newPos.X > (int)_parent_scene.WorldExtents.X - 0.05f) newPos.X = (int)_parent_scene.WorldExtents.X - 0.05f; - if (newPos.Y > (int)_parent_scene.WorldExtents.Y - 0.05f) newPos.Y = (int)_parent_scene.WorldExtents.Y - 0.05f; - - _position.X = newPos.X; - _position.Y = newPos.Y; - _position.Z = newPos.Z; - - // I think we need to update the taintPosition too -- Diva 12/24/10 - m_taintPosition = _position; - - // Did we move last? = zeroflag - // This helps keep us from sliding all over - - if (_zeroFlag) - { - _velocity = Vector3.Zero; - - // Did we send out the 'stopped' message? - if (!m_lastUpdateSent) - { - m_lastUpdateSent = true; - //base.RequestPhysicsterseUpdate(); - } - } - else - { - m_lastUpdateSent = false; - d.Vector3 newVelocity; - - try - { - newVelocity = d.BodyGetLinearVel(Body); - } - catch (NullReferenceException) - { - newVelocity.X = _velocity.X; - newVelocity.Y = _velocity.Y; - newVelocity.Z = _velocity.Z; - } - - _velocity.X = newVelocity.X; - _velocity.Y = newVelocity.Y; - _velocity.Z = newVelocity.Z; - - if (_velocity.Z < -6 && !m_hackSentFall) - { - m_hackSentFall = true; - m_pidControllerActive = false; - } - else if (flying && !m_hackSentFly) - { - //m_hackSentFly = true; - //base.SendCollisionUpdate(new CollisionEventUpdate()); - } - else - { - m_hackSentFly = false; - m_hackSentFall = false; - } - } - } - - /// - /// This creates the Avatar's physical Surrogate in ODE at the position supplied - /// - /// - /// WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access - /// to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only - /// place that is safe to call this routine AvatarGeomAndBodyCreation. - /// - /// - /// - /// - /// - private void CreateOdeStructures(float npositionX, float npositionY, float npositionZ, float tensor) - { - if (!(Shell == IntPtr.Zero && Body == IntPtr.Zero && Amotor == IntPtr.Zero)) - { - m_log.ErrorFormat( - "[ODE CHARACTER]: Creating ODE structures for {0} even though some already exist. Shell = {1}, Body = {2}, Amotor = {3}", - Name, Shell, Body, Amotor); - } - - int dAMotorEuler = 1; -// _parent_scene.waitForSpaceUnlock(_parent_scene.space); - if (CAPSULE_LENGTH <= 0) - { - m_log.Warn("[ODE CHARACTER]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!"); - CAPSULE_LENGTH = 0.01f; - } - - if (CAPSULE_RADIUS <= 0) - { - m_log.Warn("[ODE CHARACTER]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!"); - CAPSULE_RADIUS = 0.01f; - } - -// lock (OdeScene.UniversalColliderSyncObject) - Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH); - - d.GeomSetCategoryBits(Shell, (int)m_collisionCategories); - d.GeomSetCollideBits(Shell, (int)m_collisionFlags); - - d.MassSetCapsuleTotal(out ShellMass, m_mass, 2, CAPSULE_RADIUS, CAPSULE_LENGTH); - Body = d.BodyCreate(_parent_scene.world); - d.BodySetPosition(Body, npositionX, npositionY, npositionZ); - - _position.X = npositionX; - _position.Y = npositionY; - _position.Z = npositionZ; - - m_taintPosition = _position; - - d.BodySetMass(Body, ref ShellMass); - d.Matrix3 m_caprot; - // 90 Stand up on the cap of the capped cyllinder - if (_parent_scene.IsAvCapsuleTilted) - { - d.RFromAxisAndAngle(out m_caprot, 1, 0, 1, (float)(Math.PI / 2)); - } - else - { - d.RFromAxisAndAngle(out m_caprot, 0, 0, 1, (float)(Math.PI / 2)); - } - - d.GeomSetRotation(Shell, ref m_caprot); - d.BodySetRotation(Body, ref m_caprot); - - d.GeomSetBody(Shell, Body); - - // The purpose of the AMotor here is to keep the avatar's physical - // surrogate from rotating while moving - Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero); - d.JointAttach(Amotor, Body, IntPtr.Zero); - d.JointSetAMotorMode(Amotor, dAMotorEuler); - d.JointSetAMotorNumAxes(Amotor, 3); - d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0); - d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0); - d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1); - d.JointSetAMotorAngle(Amotor, 0, 0); - d.JointSetAMotorAngle(Amotor, 1, 0); - d.JointSetAMotorAngle(Amotor, 2, 0); - - // These lowstops and high stops are effectively (no wiggle room) - if (_parent_scene.IsAvCapsuleTilted) - { - d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -0.000000000001f); - d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0.000000000001f); - d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -0.000000000001f); - d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.000000000001f); - d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0.000000000001f); - d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.000000000001f); - } - else - { - #region Documentation of capsule motor LowStop and HighStop parameters - // Intentionally introduce some tilt into the capsule by setting - // the motor stops to small epsilon values. This small tilt prevents - // the capsule from falling into the terrain; a straight-up capsule - // (with -0..0 motor stops) falls into the terrain for reasons yet - // to be comprehended in their entirety. - #endregion - AlignAvatarTiltWithCurrentDirectionOfMovement(Vector3.Zero); - d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, 0.08f); - d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0f); - d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, 0.08f); - d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.08f); // must be same as lowstop, else a different, spurious tilt is introduced - d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); // same as lowstop - d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.08f); // same as lowstop - } - - // Fudge factor is 1f by default, we're setting it to 0. We don't want it to Fudge or the - // capped cyllinder will fall over - d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f); - d.JointSetAMotorParam(Amotor, (int)dParam.FMax, tensor); - - //d.Matrix3 bodyrotation = d.BodyGetRotation(Body); - //d.QfromR( - //d.Matrix3 checkrotation = new d.Matrix3(0.7071068,0.5, -0.7071068, - // - //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22); - //standupStraight(); - - _parent_scene.geom_name_map[Shell] = Name; - _parent_scene.actor_name_map[Shell] = this; - } - - /// - /// Cleanup the things we use in the scene. - /// - internal void Destroy() - { - m_tainted_isPhysical = false; - _parent_scene.AddPhysicsActorTaint(this); - } - - /// - /// Used internally to destroy the ODE structures associated with this character. - /// - internal void DestroyOdeStructures() - { - // Create avatar capsule and related ODE data - if (Shell == IntPtr.Zero || Body == IntPtr.Zero || Amotor == IntPtr.Zero) - { - m_log.ErrorFormat( - "[ODE CHARACTER]: Destroying ODE structures for {0} even though some are already null. Shell = {1}, Body = {2}, Amotor = {3}", - Name, Shell, Body, Amotor); - } - - // destroy avatar capsule and related ODE data - if (Amotor != IntPtr.Zero) - { - // Kill the Amotor - d.JointDestroy(Amotor); - Amotor = IntPtr.Zero; - } - - //kill the Geometry -// _parent_scene.waitForSpaceUnlock(_parent_scene.space); - - if (Body != IntPtr.Zero) - { - //kill the body - d.BodyDestroy(Body); - Body = IntPtr.Zero; - } - - if (Shell != IntPtr.Zero) - { -// lock (OdeScene.UniversalColliderSyncObject) - d.GeomDestroy(Shell); - - _parent_scene.geom_name_map.Remove(Shell); - _parent_scene.actor_name_map.Remove(Shell); - - Shell = IntPtr.Zero; - } - } - - public override void CrossingFailure() - { - } - - public override Vector3 PIDTarget { set { return; } } - public override bool PIDActive { set { return; } } - public override float PIDTau { set { return; } } - - public override float PIDHoverHeight { set { return; } } - public override bool PIDHoverActive { set { return; } } - public override PIDHoverType PIDHoverType { set { return; } } - public override float PIDHoverTau { set { return; } } - - 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 SubscribeEvents(int ms) - { - m_requestedUpdateFrequency = ms; - m_eventsubscription = ms; - - // Don't clear collision event reporting here. This is called directly from scene code and so can lead - // to a race condition with the simulate loop - - _parent_scene.AddCollisionEventReporting(this); - } - - public override void UnSubscribeEvents() - { - _parent_scene.RemoveCollisionEventReporting(this); - - // Don't clear collision event reporting here. This is called directly from scene code and so can lead - // to a race condition with the simulate loop - - m_requestedUpdateFrequency = 0; - m_eventsubscription = 0; - } - - internal void AddCollisionEvent(uint CollidedWith, ContactPoint contact) - { - if (m_eventsubscription > 0) - { -// m_log.DebugFormat( -// "[PHYSICS]: Adding collision event for {0}, collidedWith {1}, contact {2}", "", CollidedWith, contact); - - CollisionEventsThisFrame.AddCollider(CollidedWith, contact); - } - } - - internal void SendCollisions() - { - if (m_eventsubscription > m_requestedUpdateFrequency) - { - base.SendCollisionUpdate(CollisionEventsThisFrame); - - CollisionEventsThisFrame.Clear(); - m_eventsubscription = 0; - } - } - - public override bool SubscribedEvents() - { - if (m_eventsubscription > 0) - return true; - return false; - } - - internal void ProcessTaints() - { - if (m_taintPosition != _position) - { - if (Body != IntPtr.Zero) - { - d.BodySetPosition(Body, m_taintPosition.X, m_taintPosition.Y, m_taintPosition.Z); - _position = m_taintPosition; - } - } - - if (m_taintForce != Vector3.Zero) - { - if (Body != IntPtr.Zero) - { - // FIXME: This is not a good solution since it's subject to a race condition if a force is another - // thread sets a new force while we're in this loop (since it could be obliterated by - // m_taintForce = Vector3.Zero. Need to lock ProcessTaints() when we set a new tainted force. - d.BodyAddForce(Body, m_taintForce.X, m_taintForce.Y, m_taintForce.Z); - } - - m_taintForce = Vector3.Zero; - } - - if (m_taintTargetVelocity != _target_velocity) - _target_velocity = m_taintTargetVelocity; - - if (m_tainted_isPhysical != m_isPhysical) - { - if (m_tainted_isPhysical) - { - CreateOdeStructures(_position.X, _position.Y, _position.Z, m_tensor); - _parent_scene.AddCharacter(this); - } - else - { - _parent_scene.RemoveCharacter(this); - DestroyOdeStructures(); - } - - m_isPhysical = m_tainted_isPhysical; - } - - if (m_tainted_CAPSULE_LENGTH != CAPSULE_LENGTH) - { - if (Shell != IntPtr.Zero && Body != IntPtr.Zero && Amotor != IntPtr.Zero) - { -// m_log.DebugFormat( -// "[ODE CHARACTER]: Changing capsule size from {0} to {1} for {2}", -// CAPSULE_LENGTH, m_tainted_CAPSULE_LENGTH, Name); - - m_pidControllerActive = true; - - // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate() - DestroyOdeStructures(); - - float prevCapsule = CAPSULE_LENGTH; - CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH; - - CreateOdeStructures( - _position.X, - _position.Y, - _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor); - - // As with Size, we reset velocity. However, this isn't strictly necessary since it doesn't - // appear to stall initial region crossings when done here. Being done for consistency. -// Velocity = Vector3.Zero; - } - else - { - m_log.Warn("[ODE CHARACTER]: trying to change capsule size for " + Name + ", but the following ODE data is missing - " - + (Shell==IntPtr.Zero ? "Shell ":"") - + (Body==IntPtr.Zero ? "Body ":"") - + (Amotor==IntPtr.Zero ? "Amotor ":"")); - } - } - } - - internal void AddCollisionFrameTime(int p) - { - // protect it from overflow crashing - if (m_eventsubscription + p >= int.MaxValue) - m_eventsubscription = 0; - m_eventsubscription += p; - } - } -} diff --git a/OpenSim/Region/Physics/OdePlugin/ODEDynamics.c_comments b/OpenSim/Region/Physics/OdePlugin/ODEDynamics.c_comments deleted file mode 100644 index 1060aa6..0000000 --- a/OpenSim/Region/Physics/OdePlugin/ODEDynamics.c_comments +++ /dev/null @@ -1,630 +0,0 @@ -/* - * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces - * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised: - * ODEPrim.cs contains methods dealing with Prim editing, Prim - * characteristics and Kinetic motion. - * ODEDynamics.cs contains methods dealing with Prim Physical motion - * (dynamics) and the associated settings. Old Linear and angular - * motors for dynamic motion have been replace with MoveLinear() - * and MoveAngular(); 'Physical' is used only to switch ODE dynamic - * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_ is to - * switch between 'VEHICLE' parameter use and general dynamics - * settings use. - * - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Runtime.InteropServices; -using log4net; -using OpenMetaverse; -using Ode.NET; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.OdePlugin -{ - public class ODEDynamics - { - public Vehicle Type - { - get { return m_type; } - } - - public IntPtr Body - { - get { return m_body; } - } - - private int frcount = 0; // Used to limit dynamics debug output to - // every 100th frame - - // private OdeScene m_parentScene = null; - private IntPtr m_body = IntPtr.Zero; - private IntPtr m_jointGroup = IntPtr.Zero; - private IntPtr m_aMotor = IntPtr.Zero; - - - // Vehicle properties - private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind - // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier - private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings: - // HOVER_TERRAIN_ONLY - // HOVER_GLOBAL_HEIGHT - // NO_DEFLECTION_UP - // HOVER_WATER_ONLY - // HOVER_UP_ONLY - // LIMIT_MOTOR_UP - // LIMIT_ROLL_ONLY - - // Linear properties - private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time - private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL - private Vector3 m_dir = Vector3.Zero; // velocity applied to body - private Vector3 m_linearFrictionTimescale = Vector3.Zero; - private float m_linearMotorDecayTimescale = 0; - private float m_linearMotorTimescale = 0; - private Vector3 m_lastLinearVelocityVector = Vector3.Zero; - // private bool m_LinearMotorSetLastFrame = false; - // private Vector3 m_linearMotorOffset = Vector3.Zero; - - //Angular properties - private Vector3 m_angularMotorDirection = Vector3.Zero; - private Vector3 m_angularMotorDirectionLASTSET = Vector3.Zero; - private Vector3 m_angularFrictionTimescale = Vector3.Zero; - private float m_angularMotorDecayTimescale = 0; - private float m_angularMotorTimescale = 0; - private Vector3 m_lastAngularVelocityVector = Vector3.Zero; - - //Deflection properties - // private float m_angularDeflectionEfficiency = 0; - // private float m_angularDeflectionTimescale = 0; - // private float m_linearDeflectionEfficiency = 0; - // private float m_linearDeflectionTimescale = 0; - - //Banking properties - // private float m_bankingEfficiency = 0; - // private float m_bankingMix = 0; - // private float m_bankingTimescale = 0; - - //Hover and Buoyancy properties - private float m_VhoverHeight = 0f; - private float m_VhoverEfficiency = 0f; - private float m_VhoverTimescale = 0f; - private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height - private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. - // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity) - // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity. - // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity. - - //Attractor properties - private float m_verticalAttractionEfficiency = 0; - private float m_verticalAttractionTimescale = 0; - - - - - - internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) - { - switch (pParam) - { - case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: - if (pValue < 0.01f) pValue = 0.01f; - // m_angularDeflectionEfficiency = pValue; - break; - case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - // m_angularDeflectionTimescale = pValue; - break; - case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_angularMotorDecayTimescale = pValue; - break; - case Vehicle.ANGULAR_MOTOR_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_angularMotorTimescale = pValue; - break; - case Vehicle.BANKING_EFFICIENCY: - if (pValue < 0.01f) pValue = 0.01f; - // m_bankingEfficiency = pValue; - break; - case Vehicle.BANKING_MIX: - if (pValue < 0.01f) pValue = 0.01f; - // m_bankingMix = pValue; - break; - case Vehicle.BANKING_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - // m_bankingTimescale = pValue; - break; - case Vehicle.BUOYANCY: - if (pValue < -1f) pValue = -1f; - if (pValue > 1f) pValue = 1f; - m_VehicleBuoyancy = pValue; - break; - case Vehicle.HOVER_EFFICIENCY: - if (pValue < 0f) pValue = 0f; - if (pValue > 1f) pValue = 1f; - m_VhoverEfficiency = pValue; - break; - case Vehicle.HOVER_HEIGHT: - m_VhoverHeight = pValue; - break; - case Vehicle.HOVER_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_VhoverTimescale = pValue; - break; - case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: - if (pValue < 0.01f) pValue = 0.01f; - // m_linearDeflectionEfficiency = pValue; - break; - case Vehicle.LINEAR_DEFLECTION_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - // m_linearDeflectionTimescale = pValue; - break; - case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_linearMotorDecayTimescale = pValue; - break; - case Vehicle.LINEAR_MOTOR_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_linearMotorTimescale = pValue; - break; - case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: - if (pValue < 0.0f) pValue = 0.0f; - if (pValue > 1.0f) pValue = 1.0f; - m_verticalAttractionEfficiency = pValue; - break; - case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_verticalAttractionTimescale = pValue; - break; - - // These are vector properties but the engine lets you use a single float value to - // set all of the components to the same value - case Vehicle.ANGULAR_FRICTION_TIMESCALE: - m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); - break; - case Vehicle.ANGULAR_MOTOR_DIRECTION: - m_angularMotorDirection = new Vector3(pValue, pValue, pValue); - m_angularMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); - break; - case Vehicle.LINEAR_FRICTION_TIMESCALE: - m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); - break; - case Vehicle.LINEAR_MOTOR_DIRECTION: - m_linearMotorDirection = new Vector3(pValue, pValue, pValue); - m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); - break; - case Vehicle.LINEAR_MOTOR_OFFSET: - // m_linearMotorOffset = new Vector3(pValue, pValue, pValue); - break; - - } - - }//end ProcessFloatVehicleParam - - internal void ProcessVectorVehicleParam(Vehicle pParam, PhysicsVector pValue) - { - switch (pParam) - { - case Vehicle.ANGULAR_FRICTION_TIMESCALE: - m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); - break; - case Vehicle.ANGULAR_MOTOR_DIRECTION: - m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); - m_angularMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); - break; - case Vehicle.LINEAR_FRICTION_TIMESCALE: - m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); - break; - case Vehicle.LINEAR_MOTOR_DIRECTION: - m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); - m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); - break; - case Vehicle.LINEAR_MOTOR_OFFSET: - // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); - break; - } - - }//end ProcessVectorVehicleParam - - internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) - { - switch (pParam) - { - case Vehicle.REFERENCE_FRAME: - // m_referenceFrame = pValue; - break; - } - - }//end ProcessRotationVehicleParam - - internal void ProcessTypeChange(Vehicle pType) - { -Console.WriteLine("ProcessTypeChange to " + pType); - - // Set Defaults For Type - m_type = pType; - switch (pType) - { - case Vehicle.TYPE_SLED: - m_linearFrictionTimescale = new Vector3(30, 1, 1000); - m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 1000; - m_linearMotorDecayTimescale = 120; - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 1000; - m_angularMotorDecayTimescale = 120; - m_VhoverHeight = 0; - m_VhoverEfficiency = 1; - m_VhoverTimescale = 10; - m_VehicleBuoyancy = 0; - // m_linearDeflectionEfficiency = 1; - // m_linearDeflectionTimescale = 1; - // m_angularDeflectionEfficiency = 1; - // m_angularDeflectionTimescale = 1000; - // m_bankingEfficiency = 0; - // m_bankingMix = 1; - // m_bankingTimescale = 10; - // m_referenceFrame = Quaternion.Identity; - m_flags &= - ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | - VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); - break; - case Vehicle.TYPE_CAR: - m_linearFrictionTimescale = new Vector3(100, 2, 1000); - m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 1; - m_linearMotorDecayTimescale = 60; - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 1; - m_angularMotorDecayTimescale = 0.8f; - m_VhoverHeight = 0; - m_VhoverEfficiency = 0; - m_VhoverTimescale = 1000; - m_VehicleBuoyancy = 0; - // // m_linearDeflectionEfficiency = 1; - // // m_linearDeflectionTimescale = 2; - // // m_angularDeflectionEfficiency = 0; - // m_angularDeflectionTimescale = 10; - m_verticalAttractionEfficiency = 1; - m_verticalAttractionTimescale = 10; - // m_bankingEfficiency = -0.2f; - // m_bankingMix = 1; - // m_bankingTimescale = 1; - // m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_UP_ONLY | - VehicleFlag.LIMIT_MOTOR_UP); - break; - case Vehicle.TYPE_BOAT: - m_linearFrictionTimescale = new Vector3(10, 3, 2); - m_angularFrictionTimescale = new Vector3(10,10,10); - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 5; - m_linearMotorDecayTimescale = 60; - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 4; - m_angularMotorDecayTimescale = 4; - m_VhoverHeight = 0; - m_VhoverEfficiency = 0.5f; - m_VhoverTimescale = 2; - m_VehicleBuoyancy = 1; - // m_linearDeflectionEfficiency = 0.5f; - // m_linearDeflectionTimescale = 3; - // m_angularDeflectionEfficiency = 0.5f; - // m_angularDeflectionTimescale = 5; - m_verticalAttractionEfficiency = 0.5f; - m_verticalAttractionTimescale = 5; - // m_bankingEfficiency = -0.3f; - // m_bankingMix = 0.8f; - // m_bankingTimescale = 1; - // m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.LIMIT_ROLL_ONLY | - VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | - VehicleFlag.LIMIT_MOTOR_UP); - break; - case Vehicle.TYPE_AIRPLANE: - m_linearFrictionTimescale = new Vector3(200, 10, 5); - m_angularFrictionTimescale = new Vector3(20, 20, 20); - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 2; - m_linearMotorDecayTimescale = 60; - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 4; - m_angularMotorDecayTimescale = 4; - m_VhoverHeight = 0; - m_VhoverEfficiency = 0.5f; - m_VhoverTimescale = 1000; - m_VehicleBuoyancy = 0; - // m_linearDeflectionEfficiency = 0.5f; - // m_linearDeflectionTimescale = 3; - // m_angularDeflectionEfficiency = 1; - // m_angularDeflectionTimescale = 2; - m_verticalAttractionEfficiency = 0.9f; - m_verticalAttractionTimescale = 2; - // m_bankingEfficiency = 1; - // m_bankingMix = 0.7f; - // m_bankingTimescale = 2; - // m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | - VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP); - m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); - break; - case Vehicle.TYPE_BALLOON: - m_linearFrictionTimescale = new Vector3(5, 5, 5); - m_angularFrictionTimescale = new Vector3(10, 10, 10); - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 5; - m_linearMotorDecayTimescale = 60; - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 6; - m_angularMotorDecayTimescale = 10; - m_VhoverHeight = 5; - m_VhoverEfficiency = 0.8f; - m_VhoverTimescale = 10; - m_VehicleBuoyancy = 1; - // m_linearDeflectionEfficiency = 0; - // m_linearDeflectionTimescale = 5; - // m_angularDeflectionEfficiency = 0; - // m_angularDeflectionTimescale = 5; - m_verticalAttractionEfficiency = 1; - m_verticalAttractionTimescale = 1000; - // m_bankingEfficiency = 0; - // m_bankingMix = 0.7f; - // m_bankingTimescale = 5; - // m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | - VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP); - m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); - break; - - } - }//end SetDefaultsForType - - internal void Enable(IntPtr pBody, OdeScene pParentScene) - { -//Console.WriteLine("Enable m_type=" + m_type + " m_VehicleBuoyancy=" + m_VehicleBuoyancy); - if (m_type == Vehicle.TYPE_NONE) - return; - - m_body = pBody; - //KF: This used to set up the linear and angular joints - } - - internal void Step(float pTimestep, OdeScene pParentScene) - { - if (m_body == IntPtr.Zero || m_type == Vehicle.TYPE_NONE) - return; - frcount++; // used to limit debug comment output - if (frcount > 100) - frcount = 0; - - MoveLinear(pTimestep, pParentScene); - MoveAngular(pTimestep); - }// end Step - - private void MoveLinear(float pTimestep, OdeScene _pParentScene) - { - if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant - { - if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); - - // add drive to body - Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); - m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector? - - // This will work temporarily, but we really need to compare speed on an axis - // KF: Limit body velocity to applied velocity? - if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) - m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; - if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y)) - m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y; - if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z)) - m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z; - - // decay applied velocity - Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); - //Console.WriteLine("decay: " + decayfraction); - m_linearMotorDirection -= m_linearMotorDirection * decayfraction; - //Console.WriteLine("actual: " + m_linearMotorDirection); - } - else - { // requested is not significant - // if what remains of applied is small, zero it. - if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f)) - m_lastLinearVelocityVector = Vector3.Zero; - } - - - // convert requested object velocity to world-referenced vector - m_dir = m_lastLinearVelocityVector; - d.Quaternion rot = d.BodyGetQuaternion(Body); - Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object - m_dir *= rotq; // apply obj rotation to velocity vector - - // add Gravity andBuoyancy - // KF: So far I have found no good method to combine a script-requested - // .Z velocity and gravity. Therefore only 0g will used script-requested - // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. - Vector3 grav = Vector3.Zero; - if(m_VehicleBuoyancy < 1.0f) - { - // There is some gravity, make a gravity force vector - // that is applied after object velocity. - d.Mass objMass; - d.BodyGetMass(Body, out objMass); - // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; - grav.Z = _pParentScene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy); - // Preserve the current Z velocity - d.Vector3 vel_now = d.BodyGetLinearVel(Body); - m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity - } // else its 1.0, no gravity. - - // Check if hovering - if( (m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) - { - // We should hover, get the target height - d.Vector3 pos = d.BodyGetPosition(Body); - if((m_flags & VehicleFlag.HOVER_WATER_ONLY) == VehicleFlag.HOVER_WATER_ONLY) - { - m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight; - } - else if((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) == VehicleFlag.HOVER_TERRAIN_ONLY) - { - m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; - } - else if((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == VehicleFlag.HOVER_GLOBAL_HEIGHT) - { - m_VhoverTargetHeight = m_VhoverHeight; - } - - if((m_flags & VehicleFlag.HOVER_UP_ONLY) == VehicleFlag.HOVER_UP_ONLY) - { - // If body is aready heigher, use its height as target height - if(pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; - } - -// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped -// m_VhoverTimescale = 0f; // time to acheive height -// pTimestep is time since last frame,in secs - float herr0 = pos.Z - m_VhoverTargetHeight; -//if(frcount == 0) Console.WriteLine("herr0=" + herr0); - // Replace Vertical speed with correction figure if significant - if(Math.Abs(herr0) > 0.01f ) - { - d.Mass objMass; - d.BodyGetMass(Body, out objMass); - m_dir.Z = - ( (herr0 * pTimestep * 50.0f) / m_VhoverTimescale); - // m_VhoverEfficiency is not yet implemented - } - else - { - m_dir.Z = 0f; - } - } - - // Apply velocity - d.BodySetLinearVel(Body, m_dir.X, m_dir.Y, m_dir.Z); -//if(frcount == 0) Console.WriteLine("Move " + Body + ":"+ m_dir.X + " " + m_dir.Y + " " + m_dir.Z); - // apply gravity force - d.BodyAddForce(Body, grav.X, grav.Y, grav.Z); -//if(frcount == 0) Console.WriteLine("Force " + Body + ":" + grav.X + " " + grav.Y + " " + grav.Z); - - - // apply friction - Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); - m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; - } // end MoveLinear() - - private void MoveAngular(float pTimestep) - { - - // m_angularMotorDirection is the latest value from the script, and is decayed here - // m_angularMotorDirectionLASTSET is the latest value from the script - // m_lastAngularVelocityVector is what is being applied to the Body, varied up and down here - - if (!m_angularMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) - { - if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); - // ramp up to new value - Vector3 addAmount = m_angularMotorDirection / (m_angularMotorTimescale / pTimestep); - m_lastAngularVelocityVector += (addAmount * 10f); -//if(frcount == 0) Console.WriteLine("add: " + addAmount); - - // limit applied value to what was set by script - // This will work temporarily, but we really need to compare speed on an axis - if (Math.Abs(m_lastAngularVelocityVector.X) > Math.Abs(m_angularMotorDirectionLASTSET.X)) - m_lastAngularVelocityVector.X = m_angularMotorDirectionLASTSET.X; - if (Math.Abs(m_lastAngularVelocityVector.Y) > Math.Abs(m_angularMotorDirectionLASTSET.Y)) - m_lastAngularVelocityVector.Y = m_angularMotorDirectionLASTSET.Y; - if (Math.Abs(m_lastAngularVelocityVector.Z) > Math.Abs(m_angularMotorDirectionLASTSET.Z)) - m_lastAngularVelocityVector.Z = m_angularMotorDirectionLASTSET.Z; - - // decay the requested value - Vector3 decayfraction = ((Vector3.One / (m_angularMotorDecayTimescale / pTimestep))); - //Console.WriteLine("decay: " + decayfraction); - m_angularMotorDirection -= m_angularMotorDirection * decayfraction; - //Console.WriteLine("actual: " + m_linearMotorDirection); - } - // KF: m_lastAngularVelocityVector is rotational speed in rad/sec ? - - // Vertical attractor section - -// d.Mass objMass; -// d.BodyGetMass(Body, out objMass); -// float servo = 100f * objMass.mass * m_verticalAttractionEfficiency / (m_verticalAttractionTimescale * pTimestep); - float servo = 0.1f * m_verticalAttractionEfficiency / (m_verticalAttractionTimescale * pTimestep); - // get present body rotation - d.Quaternion rot = d.BodyGetQuaternion(Body); - Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); - // make a vector pointing up - Vector3 verterr = Vector3.Zero; - verterr.Z = 1.0f; - // rotate it to Body Angle - verterr = verterr * rotq; - // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. - // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go - // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. - if (verterr.Z < 0.0f) - { - verterr.X = 2.0f - verterr.X; - verterr.Y = 2.0f - verterr.Y; - } - // Error is 0 (no error) to +/- 2 (max error) - // scale it by servo - verterr = verterr * servo; - - // rotate to object frame - // verterr = verterr * rotq; - - // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so - // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. - m_lastAngularVelocityVector.X += verterr.Y; - m_lastAngularVelocityVector.Y -= verterr.X; -/* -if(frcount == 0) - { -// Console.WriteLine("AngleMotor " + m_lastAngularVelocityVector); - Console.WriteLine(String.Format("VA Body:{0} servo:{1} err:<{2},{3},{4}> VAE:{5}", - Body, servo, verterr.X, verterr.Y, verterr.Z, m_verticalAttractionEfficiency)); - } - */ - d.BodySetAngularVel (Body, m_lastAngularVelocityVector.X, m_lastAngularVelocityVector.Y, m_lastAngularVelocityVector.Z); - // apply friction - Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep); - m_lastAngularVelocityVector -= m_lastAngularVelocityVector * decayamount; - - } //end MoveAngular - } -} diff --git a/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs b/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs deleted file mode 100644 index 2342bfa..0000000 --- a/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs +++ /dev/null @@ -1,974 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces - * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised: - * ODEPrim.cs contains methods dealing with Prim editing, Prim - * characteristics and Kinetic motion. - * ODEDynamics.cs contains methods dealing with Prim Physical motion - * (dynamics) and the associated settings. Old Linear and angular - * motors for dynamic motion have been replace with MoveLinear() - * and MoveAngular(); 'Physical' is used only to switch ODE dynamic - * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_ is to - * switch between 'VEHICLE' parameter use and general dynamics - * settings use. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Runtime.InteropServices; -using log4net; -using OpenMetaverse; -using Ode.NET; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.OdePlugin -{ - public class ODEDynamics - { - public Vehicle Type - { - get { return m_type; } - } - - public IntPtr Body - { - get { return m_body; } - } - - private int frcount = 0; // Used to limit dynamics debug output to - // every 100th frame - - // private OdeScene m_parentScene = null; - private IntPtr m_body = IntPtr.Zero; -// private IntPtr m_jointGroup = IntPtr.Zero; -// private IntPtr m_aMotor = IntPtr.Zero; - - - // Vehicle properties - private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind - // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier - private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings: - // HOVER_TERRAIN_ONLY - // HOVER_GLOBAL_HEIGHT - // NO_DEFLECTION_UP - // HOVER_WATER_ONLY - // HOVER_UP_ONLY - // LIMIT_MOTOR_UP - // LIMIT_ROLL_ONLY - private VehicleFlag m_Hoverflags = (VehicleFlag)0; - private Vector3 m_BlockingEndPoint = Vector3.Zero; - private Quaternion m_RollreferenceFrame = Quaternion.Identity; - // Linear properties - private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time - private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL - private Vector3 m_dir = Vector3.Zero; // velocity applied to body - private Vector3 m_linearFrictionTimescale = Vector3.Zero; - private float m_linearMotorDecayTimescale = 0; - private float m_linearMotorTimescale = 0; - private Vector3 m_lastLinearVelocityVector = Vector3.Zero; - private d.Vector3 m_lastPositionVector = new d.Vector3(); - // private bool m_LinearMotorSetLastFrame = false; - // private Vector3 m_linearMotorOffset = Vector3.Zero; - - //Angular properties - private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor - private int m_angularMotorApply = 0; // application frame counter - private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity - private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate - private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate - private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate - private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body - // private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body - - //Deflection properties - // private float m_angularDeflectionEfficiency = 0; - // private float m_angularDeflectionTimescale = 0; - // private float m_linearDeflectionEfficiency = 0; - // private float m_linearDeflectionTimescale = 0; - - //Banking properties - // private float m_bankingEfficiency = 0; - // private float m_bankingMix = 0; - // private float m_bankingTimescale = 0; - - //Hover and Buoyancy properties - private float m_VhoverHeight = 0f; -// private float m_VhoverEfficiency = 0f; - private float m_VhoverTimescale = 0f; - private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height - private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. - // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity) - // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity. - // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity. - - //Attractor properties - private float m_verticalAttractionEfficiency = 1.0f; // damped - private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. - - internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) - { - switch (pParam) - { - case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: - if (pValue < 0.01f) pValue = 0.01f; - // m_angularDeflectionEfficiency = pValue; - break; - case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - // m_angularDeflectionTimescale = pValue; - break; - case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_angularMotorDecayTimescale = pValue; - break; - case Vehicle.ANGULAR_MOTOR_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_angularMotorTimescale = pValue; - break; - case Vehicle.BANKING_EFFICIENCY: - if (pValue < 0.01f) pValue = 0.01f; - // m_bankingEfficiency = pValue; - break; - case Vehicle.BANKING_MIX: - if (pValue < 0.01f) pValue = 0.01f; - // m_bankingMix = pValue; - break; - case Vehicle.BANKING_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - // m_bankingTimescale = pValue; - break; - case Vehicle.BUOYANCY: - if (pValue < -1f) pValue = -1f; - if (pValue > 1f) pValue = 1f; - m_VehicleBuoyancy = pValue; - break; -// case Vehicle.HOVER_EFFICIENCY: -// if (pValue < 0f) pValue = 0f; -// if (pValue > 1f) pValue = 1f; -// m_VhoverEfficiency = pValue; -// break; - case Vehicle.HOVER_HEIGHT: - m_VhoverHeight = pValue; - break; - case Vehicle.HOVER_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_VhoverTimescale = pValue; - break; - case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: - if (pValue < 0.01f) pValue = 0.01f; - // m_linearDeflectionEfficiency = pValue; - break; - case Vehicle.LINEAR_DEFLECTION_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - // m_linearDeflectionTimescale = pValue; - break; - case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_linearMotorDecayTimescale = pValue; - break; - case Vehicle.LINEAR_MOTOR_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_linearMotorTimescale = pValue; - break; - case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: - if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable - if (pValue > 1.0f) pValue = 1.0f; - m_verticalAttractionEfficiency = pValue; - break; - case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_verticalAttractionTimescale = pValue; - break; - - // These are vector properties but the engine lets you use a single float value to - // set all of the components to the same value - case Vehicle.ANGULAR_FRICTION_TIMESCALE: - m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); - break; - case Vehicle.ANGULAR_MOTOR_DIRECTION: - m_angularMotorDirection = new Vector3(pValue, pValue, pValue); - m_angularMotorApply = 10; - break; - case Vehicle.LINEAR_FRICTION_TIMESCALE: - m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); - break; - case Vehicle.LINEAR_MOTOR_DIRECTION: - m_linearMotorDirection = new Vector3(pValue, pValue, pValue); - m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); - break; - case Vehicle.LINEAR_MOTOR_OFFSET: - // m_linearMotorOffset = new Vector3(pValue, pValue, pValue); - break; - - } - }//end ProcessFloatVehicleParam - - internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) - { - switch (pParam) - { - case Vehicle.ANGULAR_FRICTION_TIMESCALE: - m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); - break; - case Vehicle.ANGULAR_MOTOR_DIRECTION: - m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); - // Limit requested angular speed to 2 rps= 4 pi rads/sec - if (m_angularMotorDirection.X > 12.56f) m_angularMotorDirection.X = 12.56f; - if (m_angularMotorDirection.X < - 12.56f) m_angularMotorDirection.X = - 12.56f; - if (m_angularMotorDirection.Y > 12.56f) m_angularMotorDirection.Y = 12.56f; - if (m_angularMotorDirection.Y < - 12.56f) m_angularMotorDirection.Y = - 12.56f; - if (m_angularMotorDirection.Z > 12.56f) m_angularMotorDirection.Z = 12.56f; - if (m_angularMotorDirection.Z < - 12.56f) m_angularMotorDirection.Z = - 12.56f; - m_angularMotorApply = 10; - break; - case Vehicle.LINEAR_FRICTION_TIMESCALE: - m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); - break; - case Vehicle.LINEAR_MOTOR_DIRECTION: - m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); - m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); - break; - case Vehicle.LINEAR_MOTOR_OFFSET: - // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); - break; - case Vehicle.BLOCK_EXIT: - m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z); - break; - } - }//end ProcessVectorVehicleParam - - internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) - { - switch (pParam) - { - case Vehicle.REFERENCE_FRAME: - // m_referenceFrame = pValue; - break; - case Vehicle.ROLL_FRAME: - m_RollreferenceFrame = pValue; - break; - } - }//end ProcessRotationVehicleParam - - internal void ProcessVehicleFlags(int pParam, bool remove) - { - if (remove) - { - if (pParam == -1) - { - m_flags = (VehicleFlag)0; - m_Hoverflags = (VehicleFlag)0; - return; - } - if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) - { - if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != (VehicleFlag)0) - m_Hoverflags &= ~(VehicleFlag.HOVER_GLOBAL_HEIGHT); - } - if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY) - { - if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != (VehicleFlag)0) - m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY); - } - if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY) - { - if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != (VehicleFlag)0) - m_Hoverflags &= ~(VehicleFlag.HOVER_UP_ONLY); - } - if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY) - { - if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != (VehicleFlag)0) - m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY); - } - if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP) - { - if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.LIMIT_MOTOR_UP); - } - if ((pParam & (int)VehicleFlag.LIMIT_ROLL_ONLY) == (int)VehicleFlag.LIMIT_ROLL_ONLY) - { - if ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY); - } - if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK) - { - if ((m_flags & VehicleFlag.MOUSELOOK_BANK) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.MOUSELOOK_BANK); - } - if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER) - { - if ((m_flags & VehicleFlag.MOUSELOOK_STEER) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.MOUSELOOK_STEER); - } - if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP) - { - if ((m_flags & VehicleFlag.NO_DEFLECTION_UP) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP); - } - if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED) - { - if ((m_flags & VehicleFlag.CAMERA_DECOUPLED) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.CAMERA_DECOUPLED); - } - if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X) - { - if ((m_flags & VehicleFlag.NO_X) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.NO_X); - } - if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y) - { - if ((m_flags & VehicleFlag.NO_Y) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.NO_Y); - } - if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z) - { - if ((m_flags & VehicleFlag.NO_Z) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.NO_Z); - } - if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT) - { - if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != (VehicleFlag)0) - m_Hoverflags &= ~(VehicleFlag.LOCK_HOVER_HEIGHT); - } - if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION) - { - if ((m_flags & VehicleFlag.NO_DEFLECTION) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.NO_DEFLECTION); - } - if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION) - { - if ((m_flags & VehicleFlag.LOCK_ROTATION) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.LOCK_ROTATION); - } - } - else - { - if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) - { - m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT | m_flags); - } - if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY) - { - m_Hoverflags |= (VehicleFlag.HOVER_TERRAIN_ONLY | m_flags); - } - if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY) - { - m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY | m_flags); - } - if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY) - { - m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY | m_flags); - } - if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP) - { - m_flags |= (VehicleFlag.LIMIT_MOTOR_UP | m_flags); - } - if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK) - { - m_flags |= (VehicleFlag.MOUSELOOK_BANK | m_flags); - } - if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER) - { - m_flags |= (VehicleFlag.MOUSELOOK_STEER | m_flags); - } - if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP) - { - m_flags |= (VehicleFlag.NO_DEFLECTION_UP | m_flags); - } - if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED) - { - m_flags |= (VehicleFlag.CAMERA_DECOUPLED | m_flags); - } - if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X) - { - m_flags |= (VehicleFlag.NO_X); - } - if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y) - { - m_flags |= (VehicleFlag.NO_Y); - } - if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z) - { - m_flags |= (VehicleFlag.NO_Z); - } - if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT) - { - m_Hoverflags |= (VehicleFlag.LOCK_HOVER_HEIGHT); - } - if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION) - { - m_flags |= (VehicleFlag.NO_DEFLECTION); - } - if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION) - { - m_flags |= (VehicleFlag.LOCK_ROTATION); - } - } - }//end ProcessVehicleFlags - - internal void ProcessTypeChange(Vehicle pType) - { - // Set Defaults For Type - m_type = pType; - switch (pType) - { - case Vehicle.TYPE_NONE: - m_linearFrictionTimescale = new Vector3(0, 0, 0); - m_angularFrictionTimescale = new Vector3(0, 0, 0); - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 0; - m_linearMotorDecayTimescale = 0; - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 0; - m_angularMotorDecayTimescale = 0; - m_VhoverHeight = 0; - m_VhoverTimescale = 0; - m_VehicleBuoyancy = 0; - m_flags = (VehicleFlag)0; - break; - - case Vehicle.TYPE_SLED: - m_linearFrictionTimescale = new Vector3(30, 1, 1000); - m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 1000; - m_linearMotorDecayTimescale = 120; - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 1000; - m_angularMotorDecayTimescale = 120; - m_VhoverHeight = 0; -// m_VhoverEfficiency = 1; - m_VhoverTimescale = 10; - m_VehicleBuoyancy = 0; - // m_linearDeflectionEfficiency = 1; - // m_linearDeflectionTimescale = 1; - // m_angularDeflectionEfficiency = 1; - // m_angularDeflectionTimescale = 1000; - // m_bankingEfficiency = 0; - // m_bankingMix = 1; - // m_bankingTimescale = 10; - // m_referenceFrame = Quaternion.Identity; - m_Hoverflags &= - ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | - VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); - break; - case Vehicle.TYPE_CAR: - m_linearFrictionTimescale = new Vector3(100, 2, 1000); - m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 1; - m_linearMotorDecayTimescale = 60; - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 1; - m_angularMotorDecayTimescale = 0.8f; - m_VhoverHeight = 0; -// m_VhoverEfficiency = 0; - m_VhoverTimescale = 1000; - m_VehicleBuoyancy = 0; - // // m_linearDeflectionEfficiency = 1; - // // m_linearDeflectionTimescale = 2; - // // m_angularDeflectionEfficiency = 0; - // m_angularDeflectionTimescale = 10; - m_verticalAttractionEfficiency = 1f; - m_verticalAttractionTimescale = 10f; - // m_bankingEfficiency = -0.2f; - // m_bankingMix = 1; - // m_bankingTimescale = 1; - // m_referenceFrame = Quaternion.Identity; - m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | - VehicleFlag.LIMIT_MOTOR_UP); - m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY); - break; - case Vehicle.TYPE_BOAT: - m_linearFrictionTimescale = new Vector3(10, 3, 2); - m_angularFrictionTimescale = new Vector3(10,10,10); - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 5; - m_linearMotorDecayTimescale = 60; - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 4; - m_angularMotorDecayTimescale = 4; - m_VhoverHeight = 0; -// m_VhoverEfficiency = 0.5f; - m_VhoverTimescale = 2; - m_VehicleBuoyancy = 1; - // m_linearDeflectionEfficiency = 0.5f; - // m_linearDeflectionTimescale = 3; - // m_angularDeflectionEfficiency = 0.5f; - // m_angularDeflectionTimescale = 5; - m_verticalAttractionEfficiency = 0.5f; - m_verticalAttractionTimescale = 5f; - // m_bankingEfficiency = -0.3f; - // m_bankingMix = 0.8f; - // m_bankingTimescale = 1; - // m_referenceFrame = Quaternion.Identity; - m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | - VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); - m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP | - VehicleFlag.LIMIT_MOTOR_UP); - m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY); - break; - case Vehicle.TYPE_AIRPLANE: - m_linearFrictionTimescale = new Vector3(200, 10, 5); - m_angularFrictionTimescale = new Vector3(20, 20, 20); - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 2; - m_linearMotorDecayTimescale = 60; - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 4; - m_angularMotorDecayTimescale = 4; - m_VhoverHeight = 0; -// m_VhoverEfficiency = 0.5f; - m_VhoverTimescale = 1000; - m_VehicleBuoyancy = 0; - // m_linearDeflectionEfficiency = 0.5f; - // m_linearDeflectionTimescale = 3; - // m_angularDeflectionEfficiency = 1; - // m_angularDeflectionTimescale = 2; - m_verticalAttractionEfficiency = 0.9f; - m_verticalAttractionTimescale = 2f; - // m_bankingEfficiency = 1; - // m_bankingMix = 0.7f; - // m_bankingTimescale = 2; - // m_referenceFrame = Quaternion.Identity; - m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | - VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); - m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); - m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); - break; - case Vehicle.TYPE_BALLOON: - m_linearFrictionTimescale = new Vector3(5, 5, 5); - m_angularFrictionTimescale = new Vector3(10, 10, 10); - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 5; - m_linearMotorDecayTimescale = 60; - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 6; - m_angularMotorDecayTimescale = 10; - m_VhoverHeight = 5; -// m_VhoverEfficiency = 0.8f; - m_VhoverTimescale = 10; - m_VehicleBuoyancy = 1; - // m_linearDeflectionEfficiency = 0; - // m_linearDeflectionTimescale = 5; - // m_angularDeflectionEfficiency = 0; - // m_angularDeflectionTimescale = 5; - m_verticalAttractionEfficiency = 1f; - m_verticalAttractionTimescale = 100f; - // m_bankingEfficiency = 0; - // m_bankingMix = 0.7f; - // m_bankingTimescale = 5; - // m_referenceFrame = Quaternion.Identity; - m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | - VehicleFlag.HOVER_UP_ONLY); - m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); - m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); - m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT); - break; - - } - }//end SetDefaultsForType - - internal void Enable(IntPtr pBody, OdeScene pParentScene) - { - if (m_type == Vehicle.TYPE_NONE) - return; - - m_body = pBody; - } - - internal void Step(float pTimestep, OdeScene pParentScene) - { - if (m_body == IntPtr.Zero || m_type == Vehicle.TYPE_NONE) - return; - frcount++; // used to limit debug comment output - if (frcount > 100) - frcount = 0; - - MoveLinear(pTimestep, pParentScene); - MoveAngular(pTimestep); - LimitRotation(pTimestep); - }// end Step - - private void MoveLinear(float pTimestep, OdeScene _pParentScene) - { - if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant - { - if (!d.BodyIsEnabled(Body)) - d.BodyEnable(Body); - - // add drive to body - Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); - m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector? - - // This will work temporarily, but we really need to compare speed on an axis - // KF: Limit body velocity to applied velocity? - if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) - m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; - if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y)) - m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y; - if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z)) - m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z; - - // decay applied velocity - Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); - //Console.WriteLine("decay: " + decayfraction); - m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f; - //Console.WriteLine("actual: " + m_linearMotorDirection); - } - else - { // requested is not significant - // if what remains of applied is small, zero it. - if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f)) - m_lastLinearVelocityVector = Vector3.Zero; - } - - // convert requested object velocity to world-referenced vector - m_dir = m_lastLinearVelocityVector; - d.Quaternion rot = d.BodyGetQuaternion(Body); - Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object - m_dir *= rotq; // apply obj rotation to velocity vector - - // add Gravity andBuoyancy - // KF: So far I have found no good method to combine a script-requested - // .Z velocity and gravity. Therefore only 0g will used script-requested - // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. - Vector3 grav = Vector3.Zero; - // There is some gravity, make a gravity force vector - // that is applied after object velocity. - d.Mass objMass; - d.BodyGetMass(Body, out objMass); - // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; - grav.Z = _pParentScene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy); - // Preserve the current Z velocity - d.Vector3 vel_now = d.BodyGetLinearVel(Body); - m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity - - d.Vector3 pos = d.BodyGetPosition(Body); -// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); - Vector3 posChange = new Vector3(); - posChange.X = pos.X - m_lastPositionVector.X; - posChange.Y = pos.Y - m_lastPositionVector.Y; - posChange.Z = pos.Z - m_lastPositionVector.Z; - double Zchange = Math.Abs(posChange.Z); - if (m_BlockingEndPoint != Vector3.Zero) - { - if (pos.X >= (m_BlockingEndPoint.X - (float)1)) - { - pos.X -= posChange.X + 1; - d.BodySetPosition(Body, pos.X, pos.Y, pos.Z); - } - if (pos.Y >= (m_BlockingEndPoint.Y - (float)1)) - { - pos.Y -= posChange.Y + 1; - d.BodySetPosition(Body, pos.X, pos.Y, pos.Z); - } - if (pos.Z >= (m_BlockingEndPoint.Z - (float)1)) - { - pos.Z -= posChange.Z + 1; - d.BodySetPosition(Body, pos.X, pos.Y, pos.Z); - } - if (pos.X <= 0) - { - pos.X += posChange.X + 1; - d.BodySetPosition(Body, pos.X, pos.Y, pos.Z); - } - if (pos.Y <= 0) - { - pos.Y += posChange.Y + 1; - d.BodySetPosition(Body, pos.X, pos.Y, pos.Z); - } - } - if (pos.Z < _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y)) - { - pos.Z = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + 2; - d.BodySetPosition(Body, pos.X, pos.Y, pos.Z); - } - - // Check if hovering - if ((m_Hoverflags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) - { - // We should hover, get the target height - if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0) - { - m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight; - } - if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) - { - m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; - } - if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) - { - m_VhoverTargetHeight = m_VhoverHeight; - } - - if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != 0) - { - // If body is aready heigher, use its height as target height - if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; - } - if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) - { - if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2) - { - d.BodySetPosition(Body, pos.X, pos.Y, m_VhoverTargetHeight); - } - } - else - { - float herr0 = pos.Z - m_VhoverTargetHeight; - // Replace Vertical speed with correction figure if significant - if (Math.Abs(herr0) > 0.01f) - { - m_dir.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale); - //KF: m_VhoverEfficiency is not yet implemented - } - else - { - m_dir.Z = 0f; - } - } - -// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped -// m_VhoverTimescale = 0f; // time to acheive height -// pTimestep is time since last frame,in secs - } - - if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) - { - //Start Experimental Values - if (Zchange > .3) - { - grav.Z = (float)(grav.Z * 3); - } - if (Zchange > .15) - { - grav.Z = (float)(grav.Z * 2); - } - if (Zchange > .75) - { - grav.Z = (float)(grav.Z * 1.5); - } - if (Zchange > .05) - { - grav.Z = (float)(grav.Z * 1.25); - } - if (Zchange > .025) - { - grav.Z = (float)(grav.Z * 1.125); - } - float terraintemp = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y); - float postemp = (pos.Z - terraintemp); - if (postemp > 2.5f) - { - grav.Z = (float)(grav.Z * 1.037125); - } - //End Experimental Values - } - if ((m_flags & (VehicleFlag.NO_X)) != 0) - { - m_dir.X = 0; - } - if ((m_flags & (VehicleFlag.NO_Y)) != 0) - { - m_dir.Y = 0; - } - if ((m_flags & (VehicleFlag.NO_Z)) != 0) - { - m_dir.Z = 0; - } - - m_lastPositionVector = d.BodyGetPosition(Body); - - // Apply velocity - d.BodySetLinearVel(Body, m_dir.X, m_dir.Y, m_dir.Z); - // apply gravity force - d.BodyAddForce(Body, grav.X, grav.Y, grav.Z); - - - // apply friction - Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); - m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; - } // end MoveLinear() - - private void MoveAngular(float pTimestep) - { - /* - private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor - private int m_angularMotorApply = 0; // application frame counter - private float m_angularMotorVelocity = 0; // current angular motor velocity (ramps up and down) - private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate - private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate - private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate - private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body - */ - - // Get what the body is doing, this includes 'external' influences - d.Vector3 angularVelocity = d.BodyGetAngularVel(Body); - // Vector3 angularVelocity = Vector3.Zero; - - if (m_angularMotorApply > 0) - { - // ramp up to new value - // current velocity += error / (time to get there / step interval) - // requested speed - last motor speed - m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); - m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); - m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); - - m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected - // velocity may still be acheived. - } - else - { - // no motor recently applied, keep the body velocity - /* m_angularMotorVelocity.X = angularVelocity.X; - m_angularMotorVelocity.Y = angularVelocity.Y; - m_angularMotorVelocity.Z = angularVelocity.Z; */ - - // and decay the velocity - m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); - } // end motor section - - // Vertical attractor section - Vector3 vertattr = Vector3.Zero; - - if (m_verticalAttractionTimescale < 300) - { - float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep); - // get present body rotation - d.Quaternion rot = d.BodyGetQuaternion(Body); - Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); - // make a vector pointing up - Vector3 verterr = Vector3.Zero; - verterr.Z = 1.0f; - // rotate it to Body Angle - verterr = verterr * rotq; - // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. - // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go - // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. - if (verterr.Z < 0.0f) - { - verterr.X = 2.0f - verterr.X; - verterr.Y = 2.0f - verterr.Y; - } - // Error is 0 (no error) to +/- 2 (max error) - // scale it by VAservo - verterr = verterr * VAservo; -//if (frcount == 0) Console.WriteLine("VAerr=" + verterr); - - // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so - // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. - vertattr.X = verterr.Y; - vertattr.Y = - verterr.X; - vertattr.Z = 0f; - - // scaling appears better usingsquare-law - float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); - vertattr.X += bounce * angularVelocity.X; - vertattr.Y += bounce * angularVelocity.Y; - - } // else vertical attractor is off - - // m_lastVertAttractor = vertattr; - - // Bank section tba - // Deflection section tba - - // Sum velocities - m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection - - if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) - { - m_lastAngularVelocity.X = 0; - m_lastAngularVelocity.Y = 0; - } - - if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) - { - if (!d.BodyIsEnabled (Body)) d.BodyEnable (Body); - } - else - { - m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. - } - - // apply friction - Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep); - m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; - - // Apply to the body - d.BodySetAngularVel (Body, m_lastAngularVelocity.X, m_lastAngularVelocity.Y, m_lastAngularVelocity.Z); - - } //end MoveAngular - internal void LimitRotation(float timestep) - { - d.Quaternion rot = d.BodyGetQuaternion(Body); - Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object - d.Quaternion m_rot = new d.Quaternion(); - bool changed = false; - m_rot.X = rotq.X; - m_rot.Y = rotq.Y; - m_rot.Z = rotq.Z; - m_rot.W = rotq.W; - if (m_RollreferenceFrame != Quaternion.Identity) - { - if (rotq.X >= m_RollreferenceFrame.X) - { - m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2); - } - if (rotq.Y >= m_RollreferenceFrame.Y) - { - m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2); - } - if (rotq.X <= -m_RollreferenceFrame.X) - { - m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2); - } - if (rotq.Y <= -m_RollreferenceFrame.Y) - { - m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2); - } - changed = true; - } - if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0) - { - m_rot.X = 0; - m_rot.Y = 0; - changed = true; - } - if (changed) - d.BodySetQuaternion(Body, ref m_rot); - } - } -} diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs deleted file mode 100644 index 0d66496..0000000 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ /dev/null @@ -1,3380 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces - * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised: - * ODEPrim.cs contains methods dealing with Prim editing, Prim - * characteristics and Kinetic motion. - * ODEDynamics.cs contains methods dealing with Prim Physical motion - * (dynamics) and the associated settings. Old Linear and angular - * motors for dynamic motion have been replace with MoveLinear() - * and MoveAngular(); 'Physical' is used only to switch ODE dynamic - * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_ is to - * switch between 'VEHICLE' parameter use and general dynamics - * settings use. - */ - -//#define SPAM - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Threading; -using log4net; -using OpenMetaverse; -using Ode.NET; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.OdePlugin -{ - /// - /// Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ourselves. - /// - public class OdePrim : PhysicsActor - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private bool m_isphysical; - - public int ExpectedCollisionContacts { get { return m_expectedCollisionContacts; } } - private int m_expectedCollisionContacts = 0; - - /// - /// Gets collide bits so that we can still perform land collisions if a mesh fails to load. - /// - private int BadMeshAssetCollideBits - { - get { return m_isphysical ? (int)CollisionCategories.Land : 0; } - } - - /// - /// Is this prim subject to physics? Even if not, it's still solid for collision purposes. - /// - public override bool IsPhysical - { - get { return m_isphysical; } - set - { - m_isphysical = value; - if (!m_isphysical) // Zero the remembered last velocity - m_lastVelocity = Vector3.Zero; - } - } - - private Vector3 _position; - private Vector3 _velocity; - private Vector3 _torque; - private Vector3 m_lastVelocity; - private Vector3 m_lastposition; - private Quaternion m_lastorientation = new Quaternion(); - private Vector3 m_rotationalVelocity; - private Vector3 _size; - private Vector3 _acceleration; - // private d.Vector3 _zeroPosition = new d.Vector3(0.0f, 0.0f, 0.0f); - private Quaternion _orientation; - private Vector3 m_taintposition; - private Vector3 m_taintsize; - private Vector3 m_taintVelocity; - private Vector3 m_taintTorque; - private Quaternion m_taintrot; - private Vector3 m_angularlock = Vector3.One; - private Vector3 m_taintAngularLock = Vector3.One; - private IntPtr Amotor = IntPtr.Zero; - - private object m_assetsLock = new object(); - private bool m_assetFailed = false; - - private Vector3 m_PIDTarget; - private float m_PIDTau; - private float PID_D = 35f; - private float PID_G = 25f; - private bool m_usePID; - - // KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau), - // and are for non-VEHICLES only. - - private float m_PIDHoverHeight; - private float m_PIDHoverTau; - private bool m_useHoverPID; - private PIDHoverType m_PIDHoverType = PIDHoverType.Ground; - private float m_targetHoverHeight; - private float m_groundHeight; - private float m_waterHeight; - private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle. - - // private float m_tensor = 5f; - private int body_autodisable_frames = 20; - - - private const CollisionCategories m_default_collisionFlags = (CollisionCategories.Geom - | CollisionCategories.Space - | CollisionCategories.Body - | CollisionCategories.Character - ); - private bool m_taintshape; - private bool m_taintPhysics; - private bool m_collidesLand = true; - private bool m_collidesWater; - - // Default we're a Geometry - private CollisionCategories m_collisionCategories = (CollisionCategories.Geom); - - // Default, Collide with Other Geometries, spaces and Bodies - private CollisionCategories m_collisionFlags = m_default_collisionFlags; - - public bool m_taintremove { get; private set; } - public bool m_taintdisable { get; private set; } - internal bool m_disabled; - public bool m_taintadd { get; private set; } - public bool m_taintselected { get; private set; } - public bool m_taintCollidesWater { get; private set; } - - private bool m_taintforce = false; - private bool m_taintaddangularforce = false; - private Vector3 m_force; - private List m_forcelist = new List(); - private List m_angularforcelist = new List(); - - private PrimitiveBaseShape _pbs; - private OdeScene _parent_scene; - - /// - /// The physics space which contains prim geometries - /// - public IntPtr m_targetSpace = IntPtr.Zero; - - /// - /// The prim geometry, used for collision detection. - /// - /// - /// This is never null except for a brief period when the geometry needs to be replaced (due to resizing or - /// mesh change) or when the physical prim is being removed from the scene. - /// - public IntPtr prim_geom { get; private set; } - - public IntPtr _triMeshData { get; private set; } - - private IntPtr _linkJointGroup = IntPtr.Zero; - private PhysicsActor _parent; - private PhysicsActor m_taintparent; - - private List childrenPrim = new List(); - - private bool iscolliding; - private bool m_isSelected; - - internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively - - private bool m_throttleUpdates; - private int throttleCounter; - public int m_interpenetrationcount { get; private set; } - internal float m_collisionscore; - public int m_roundsUnderMotionThreshold { get; private set; } - private int m_crossingfailures; - - public bool outofBounds { get; private set; } - private float m_density = 10.000006836f; // Aluminum g/cm3; - - public bool _zeroFlag { get; private set; } - private bool m_lastUpdateSent; - - public IntPtr Body = IntPtr.Zero; - private Vector3 _target_velocity; - private d.Mass pMass; - - private int m_eventsubscription; - private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate(); - - /// - /// Signal whether there were collisions on the previous frame, so we know if we need to send the - /// empty CollisionEventsThisFrame to the prim so that it can detect the end of a collision. - /// - /// - /// This is probably a temporary measure, pending storing this information consistently in CollisionEventUpdate itself. - /// - private bool m_collisionsOnPreviousFrame; - - private IntPtr m_linkJoint = IntPtr.Zero; - - internal volatile bool childPrim; - - private ODEDynamics m_vehicle; - - internal int m_material = (int)Material.Wood; - - public OdePrim( - String primName, OdeScene parent_scene, Vector3 pos, Vector3 size, - Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) - { - Name = primName; - m_vehicle = new ODEDynamics(); - //gc = GCHandle.Alloc(prim_geom, GCHandleType.Pinned); - - if (!pos.IsFinite()) - { - pos = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), - parent_scene.GetTerrainHeightAtXY(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f)) + 0.5f); - m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Position for {0}", Name); - } - _position = pos; - m_taintposition = pos; - PID_D = parent_scene.bodyPIDD; - PID_G = parent_scene.bodyPIDG; - m_density = parent_scene.geomDefaultDensity; - // m_tensor = parent_scene.bodyMotorJointMaxforceTensor; - body_autodisable_frames = parent_scene.bodyFramesAutoDisable; - - prim_geom = IntPtr.Zero; - - if (!pos.IsFinite()) - { - size = new Vector3(0.5f, 0.5f, 0.5f); - m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Size for {0}", Name); - } - - if (size.X <= 0) size.X = 0.01f; - if (size.Y <= 0) size.Y = 0.01f; - if (size.Z <= 0) size.Z = 0.01f; - - _size = size; - m_taintsize = _size; - - if (!QuaternionIsFinite(rotation)) - { - rotation = Quaternion.Identity; - m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Rotation for {0}", Name); - } - - _orientation = rotation; - m_taintrot = _orientation; - _pbs = pbs; - - _parent_scene = parent_scene; - m_targetSpace = (IntPtr)0; - - if (pos.Z < 0) - { - IsPhysical = false; - } - else - { - IsPhysical = pisPhysical; - // If we're physical, we need to be in the master space for now. - // linksets *should* be in a space together.. but are not currently - if (IsPhysical) - m_targetSpace = _parent_scene.space; - } - - m_taintadd = true; - m_assetFailed = false; - _parent_scene.AddPhysicsActorTaint(this); - } - - public override int PhysicsActorType - { - get { return (int) ActorTypes.Prim; } - set { return; } - } - - public override bool SetAlwaysRun - { - get { return false; } - set { return; } - } - - public override bool Grabbed - { - set { return; } - } - - public override bool Selected - { - set - { - // This only makes the object not collidable if the object - // is physical or the object is modified somehow *IN THE FUTURE* - // without this, if an avatar selects prim, they can walk right - // through it while it's selected - m_collisionscore = 0; - - if ((IsPhysical && !_zeroFlag) || !value) - { - m_taintselected = value; - _parent_scene.AddPhysicsActorTaint(this); - } - else - { - m_taintselected = value; - m_isSelected = value; - } - - if (m_isSelected) - disableBodySoft(); - } - } - - /// - /// Set a new geometry for this prim. - /// - /// - private void SetGeom(IntPtr geom) - { - prim_geom = geom; -//Console.WriteLine("SetGeom to " + prim_geom + " for " + Name); - - if (m_assetFailed) - { - d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, BadMeshAssetCollideBits); - } - else - { - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); - } - - _parent_scene.geom_name_map[prim_geom] = Name; - _parent_scene.actor_name_map[prim_geom] = this; - - if (childPrim) - { - if (_parent != null && _parent is OdePrim) - { - OdePrim parent = (OdePrim)_parent; -//Console.WriteLine("SetGeom calls ChildSetGeom"); - parent.ChildSetGeom(this); - } - } - //m_log.Warn("Setting Geom to: " + prim_geom); - } - - private void enableBodySoft() - { - if (!childPrim) - { - if (IsPhysical && Body != IntPtr.Zero) - { - d.BodyEnable(Body); - if (m_vehicle.Type != Vehicle.TYPE_NONE) - m_vehicle.Enable(Body, _parent_scene); - } - - m_disabled = false; - } - } - - private void disableBodySoft() - { - m_disabled = true; - - if (IsPhysical && Body != IntPtr.Zero) - { - d.BodyDisable(Body); - } - } - - /// - /// Make a prim subject to physics. - /// - private void enableBody() - { - // Don't enable this body if we're a child prim - // this should be taken care of in the parent function not here - if (!childPrim) - { - // Sets the geom to a body - Body = d.BodyCreate(_parent_scene.world); - - setMass(); - d.BodySetPosition(Body, _position.X, _position.Y, _position.Z); - d.Quaternion myrot = new d.Quaternion(); - myrot.X = _orientation.X; - myrot.Y = _orientation.Y; - myrot.Z = _orientation.Z; - myrot.W = _orientation.W; - d.BodySetQuaternion(Body, ref myrot); - d.GeomSetBody(prim_geom, Body); - - if (m_assetFailed) - { - d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, BadMeshAssetCollideBits); - } - else - { - m_collisionCategories |= CollisionCategories.Body; - m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); - } - - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); - - d.BodySetAutoDisableFlag(Body, true); - d.BodySetAutoDisableSteps(Body, body_autodisable_frames); - - // disconnect from world gravity so we can apply buoyancy - d.BodySetGravityMode (Body, false); - - m_interpenetrationcount = 0; - m_collisionscore = 0; - m_disabled = false; - - // The body doesn't already have a finite rotation mode set here - if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0.0f)) && _parent == null) - { - createAMotor(m_angularlock); - } - if (m_vehicle.Type != Vehicle.TYPE_NONE) - { - m_vehicle.Enable(Body, _parent_scene); - } - - _parent_scene.ActivatePrim(this); - } - } - - #region Mass Calculation - - private float CalculateMass() - { - float volume = _size.X * _size.Y * _size.Z; // default - float tmp; - - float returnMass = 0; - float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f; - float hollowVolume = hollowAmount * hollowAmount; - - switch (_pbs.ProfileShape) - { - case ProfileShape.Square: - // default box - - if (_pbs.PathCurve == (byte)Extrusion.Straight) - { - if (hollowAmount > 0.0) - { - switch (_pbs.HollowShape) - { - case HollowShape.Square: - case HollowShape.Same: - break; - - case HollowShape.Circle: - - hollowVolume *= 0.78539816339f; - break; - - case HollowShape.Triangle: - - hollowVolume *= (0.5f * .5f); - break; - - default: - hollowVolume = 0; - break; - } - volume *= (1.0f - hollowVolume); - } - } - - else if (_pbs.PathCurve == (byte)Extrusion.Curve1) - { - //a tube - - volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX); - tmp= 1.0f -2.0e-2f * (float)(200 - _pbs.PathScaleY); - volume -= volume*tmp*tmp; - - if (hollowAmount > 0.0) - { - hollowVolume *= hollowAmount; - - switch (_pbs.HollowShape) - { - case HollowShape.Square: - case HollowShape.Same: - break; - - case HollowShape.Circle: - hollowVolume *= 0.78539816339f;; - break; - - case HollowShape.Triangle: - hollowVolume *= 0.5f * 0.5f; - break; - default: - hollowVolume = 0; - break; - } - volume *= (1.0f - hollowVolume); - } - } - - break; - - case ProfileShape.Circle: - - if (_pbs.PathCurve == (byte)Extrusion.Straight) - { - volume *= 0.78539816339f; // elipse base - - if (hollowAmount > 0.0) - { - switch (_pbs.HollowShape) - { - case HollowShape.Same: - case HollowShape.Circle: - break; - - case HollowShape.Square: - hollowVolume *= 0.5f * 2.5984480504799f; - break; - - case HollowShape.Triangle: - hollowVolume *= .5f * 1.27323954473516f; - break; - - default: - hollowVolume = 0; - break; - } - volume *= (1.0f - hollowVolume); - } - } - - else if (_pbs.PathCurve == (byte)Extrusion.Curve1) - { - volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX); - tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); - volume *= (1.0f - tmp * tmp); - - if (hollowAmount > 0.0) - { - - // calculate the hollow volume by it's shape compared to the prim shape - hollowVolume *= hollowAmount; - - switch (_pbs.HollowShape) - { - case HollowShape.Same: - case HollowShape.Circle: - break; - - case HollowShape.Square: - hollowVolume *= 0.5f * 2.5984480504799f; - break; - - case HollowShape.Triangle: - hollowVolume *= .5f * 1.27323954473516f; - break; - - default: - hollowVolume = 0; - break; - } - volume *= (1.0f - hollowVolume); - } - } - break; - - case ProfileShape.HalfCircle: - if (_pbs.PathCurve == (byte)Extrusion.Curve1) - { - volume *= 0.52359877559829887307710723054658f; - } - break; - - case ProfileShape.EquilateralTriangle: - - if (_pbs.PathCurve == (byte)Extrusion.Straight) - { - volume *= 0.32475953f; - - if (hollowAmount > 0.0) - { - - // calculate the hollow volume by it's shape compared to the prim shape - switch (_pbs.HollowShape) - { - case HollowShape.Same: - case HollowShape.Triangle: - hollowVolume *= .25f; - break; - - case HollowShape.Square: - hollowVolume *= 0.499849f * 3.07920140172638f; - break; - - case HollowShape.Circle: - // Hollow shape is a perfect cyllinder in respect to the cube's scale - // Cyllinder hollow volume calculation - - hollowVolume *= 0.1963495f * 3.07920140172638f; - break; - - default: - hollowVolume = 0; - break; - } - volume *= (1.0f - hollowVolume); - } - } - else if (_pbs.PathCurve == (byte)Extrusion.Curve1) - { - volume *= 0.32475953f; - volume *= 0.01f * (float)(200 - _pbs.PathScaleX); - tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); - volume *= (1.0f - tmp * tmp); - - if (hollowAmount > 0.0) - { - - hollowVolume *= hollowAmount; - - switch (_pbs.HollowShape) - { - case HollowShape.Same: - case HollowShape.Triangle: - hollowVolume *= .25f; - break; - - case HollowShape.Square: - hollowVolume *= 0.499849f * 3.07920140172638f; - break; - - case HollowShape.Circle: - - hollowVolume *= 0.1963495f * 3.07920140172638f; - break; - - default: - hollowVolume = 0; - break; - } - volume *= (1.0f - hollowVolume); - } - } - break; - - default: - break; - } - - float taperX1; - float taperY1; - float taperX; - float taperY; - float pathBegin; - float pathEnd; - float profileBegin; - float profileEnd; - - if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible) - { - taperX1 = _pbs.PathScaleX * 0.01f; - if (taperX1 > 1.0f) - taperX1 = 2.0f - taperX1; - taperX = 1.0f - taperX1; - - taperY1 = _pbs.PathScaleY * 0.01f; - if (taperY1 > 1.0f) - taperY1 = 2.0f - taperY1; - taperY = 1.0f - taperY1; - } - else - { - taperX = _pbs.PathTaperX * 0.01f; - if (taperX < 0.0f) - taperX = -taperX; - taperX1 = 1.0f - taperX; - - taperY = _pbs.PathTaperY * 0.01f; - if (taperY < 0.0f) - taperY = -taperY; - taperY1 = 1.0f - taperY; - } - - volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); - - pathBegin = (float)_pbs.PathBegin * 2.0e-5f; - pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f; - volume *= (pathEnd - pathBegin); - -// this is crude aproximation - profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f; - profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f; - volume *= (profileEnd - profileBegin); - - returnMass = m_density * volume; - - if (returnMass <= 0) - returnMass = 0.0001f;//ckrinke: Mass must be greater then zero. -// else if (returnMass > _parent_scene.maximumMassObject) -// returnMass = _parent_scene.maximumMassObject; - - // Recursively calculate mass - bool HasChildPrim = false; - lock (childrenPrim) - { - if (childrenPrim.Count > 0) - { - HasChildPrim = true; - } - } - - if (HasChildPrim) - { - OdePrim[] childPrimArr = new OdePrim[0]; - - lock (childrenPrim) - childPrimArr = childrenPrim.ToArray(); - - for (int i = 0; i < childPrimArr.Length; i++) - { - if (childPrimArr[i] != null && !childPrimArr[i].m_taintremove) - returnMass += childPrimArr[i].CalculateMass(); - // failsafe, this shouldn't happen but with OpenSim, you never know :) - if (i > 256) - break; - } - } - - if (returnMass > _parent_scene.maximumMassObject) - returnMass = _parent_scene.maximumMassObject; - - return returnMass; - } - - #endregion - - private void setMass() - { - if (Body != (IntPtr) 0) - { - float newmass = CalculateMass(); - - //m_log.Info("[PHYSICS]: New Mass: " + newmass.ToString()); - - d.MassSetBoxTotal(out pMass, newmass, _size.X, _size.Y, _size.Z); - d.BodySetMass(Body, ref pMass); - } - } - - /// - /// Stop a prim from being subject to physics. - /// - internal void disableBody() - { - //this kills the body so things like 'mesh' can re-create it. - lock (this) - { - if (!childPrim) - { - if (Body != IntPtr.Zero) - { - _parent_scene.DeactivatePrim(this); - m_collisionCategories &= ~CollisionCategories.Body; - m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); - - if (m_assetFailed) - { - d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, 0); - } - else - { - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); - } - - d.BodyDestroy(Body); - lock (childrenPrim) - { - if (childrenPrim.Count > 0) - { - foreach (OdePrim prm in childrenPrim) - { - _parent_scene.DeactivatePrim(prm); - prm.Body = IntPtr.Zero; - } - } - } - Body = IntPtr.Zero; - } - } - else - { - _parent_scene.DeactivatePrim(this); - - m_collisionCategories &= ~CollisionCategories.Body; - m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); - - if (m_assetFailed) - { - d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, 0); - } - else - { - - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); - } - - Body = IntPtr.Zero; - } - } - - m_disabled = true; - m_collisionscore = 0; - } - - private static Dictionary m_MeshToTriMeshMap = new Dictionary(); - - private void setMesh(OdeScene parent_scene, IMesh mesh) - { -// m_log.DebugFormat("[ODE PRIM]: Setting mesh on {0} to {1}", Name, mesh); - - // This sleeper is there to moderate how long it takes between - // setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object - - //Thread.Sleep(10); - - //Kill Body so that mesh can re-make the geom - if (IsPhysical && Body != IntPtr.Zero) - { - if (childPrim) - { - if (_parent != null) - { - OdePrim parent = (OdePrim)_parent; - parent.ChildDelink(this); - } - } - else - { - disableBody(); - } - } - - IntPtr vertices, indices; - int vertexCount, indexCount; - int vertexStride, triStride; - mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap - mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage - m_expectedCollisionContacts = indexCount; - mesh.releaseSourceMeshData(); // free up the original mesh data to save memory - - // We must lock here since m_MeshToTriMeshMap is static and multiple scene threads may call this method at - // the same time. - lock (m_MeshToTriMeshMap) - { - if (m_MeshToTriMeshMap.ContainsKey(mesh)) - { - _triMeshData = m_MeshToTriMeshMap[mesh]; - } - else - { - _triMeshData = d.GeomTriMeshDataCreate(); - - d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride); - d.GeomTriMeshDataPreprocess(_triMeshData); - m_MeshToTriMeshMap[mesh] = _triMeshData; - } - } - -// _parent_scene.waitForSpaceUnlock(m_targetSpace); - try - { - SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null)); - } - catch (AccessViolationException) - { - m_log.ErrorFormat("[PHYSICS]: MESH LOCKED FOR {0}", Name); - return; - } - - // if (IsPhysical && Body == (IntPtr) 0) - // { - // Recreate the body - // m_interpenetrationcount = 0; - // m_collisionscore = 0; - - // enableBody(); - // } - } - - internal void ProcessTaints() - { -#if SPAM -Console.WriteLine("ZProcessTaints for " + Name); -#endif - - // This must be processed as the very first taint so that later operations have a prim_geom to work with - // if this is a new prim. - if (m_taintadd) - changeadd(); - - if (!_position.ApproxEquals(m_taintposition, 0f)) - changemove(); - - if (m_taintrot != _orientation) - { - if (childPrim && IsPhysical) // For physical child prim... - { - rotate(); - // KF: ODE will also rotate the parent prim! - // so rotate the root back to where it was - OdePrim parent = (OdePrim)_parent; - parent.rotate(); - } - else - { - //Just rotate the prim - rotate(); - } - } - - if (m_taintPhysics != IsPhysical && !(m_taintparent != _parent)) - changePhysicsStatus(); - - if (!_size.ApproxEquals(m_taintsize, 0f)) - changesize(); - - if (m_taintshape) - changeshape(); - - if (m_taintforce) - changeAddForce(); - - if (m_taintaddangularforce) - changeAddAngularForce(); - - if (!m_taintTorque.ApproxEquals(Vector3.Zero, 0.001f)) - changeSetTorque(); - - if (m_taintdisable) - changedisable(); - - if (m_taintselected != m_isSelected) - changeSelectedStatus(); - - if (!m_taintVelocity.ApproxEquals(Vector3.Zero, 0.001f)) - changevelocity(); - - if (m_taintparent != _parent) - changelink(); - - if (m_taintCollidesWater != m_collidesWater) - changefloatonwater(); - - if (!m_angularlock.ApproxEquals(m_taintAngularLock,0f)) - changeAngularLock(); - } - - /// - /// Change prim in response to an angular lock taint. - /// - private void changeAngularLock() - { - // do we have a Physical object? - if (Body != IntPtr.Zero) - { - //Check that we have a Parent - //If we have a parent then we're not authorative here - if (_parent == null) - { - if (!m_taintAngularLock.ApproxEquals(Vector3.One, 0f)) - { - //d.BodySetFiniteRotationMode(Body, 0); - //d.BodySetFiniteRotationAxis(Body,m_taintAngularLock.X,m_taintAngularLock.Y,m_taintAngularLock.Z); - createAMotor(m_taintAngularLock); - } - else - { - if (Amotor != IntPtr.Zero) - { - d.JointDestroy(Amotor); - Amotor = IntPtr.Zero; - } - } - } - } - - // Store this for later in case we get turned into a separate body - m_angularlock = m_taintAngularLock; - } - - /// - /// Change prim in response to a link taint. - /// - private void changelink() - { - // If the newly set parent is not null - // create link - if (_parent == null && m_taintparent != null) - { - if (m_taintparent.PhysicsActorType == (int)ActorTypes.Prim) - { - OdePrim obj = (OdePrim)m_taintparent; - //obj.disableBody(); -//Console.WriteLine("changelink calls ParentPrim"); - obj.AddChildPrim(this); - - /* - if (obj.Body != (IntPtr)0 && Body != (IntPtr)0 && obj.Body != Body) - { - _linkJointGroup = d.JointGroupCreate(0); - m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup); - d.JointAttach(m_linkJoint, obj.Body, Body); - d.JointSetFixed(m_linkJoint); - } - */ - } - } - // If the newly set parent is null - // destroy link - else if (_parent != null && m_taintparent == null) - { -//Console.WriteLine(" changelink B"); - - if (_parent is OdePrim) - { - OdePrim obj = (OdePrim)_parent; - obj.ChildDelink(this); - childPrim = false; - //_parent = null; - } - - /* - if (Body != (IntPtr)0 && _linkJointGroup != (IntPtr)0) - d.JointGroupDestroy(_linkJointGroup); - - _linkJointGroup = (IntPtr)0; - m_linkJoint = (IntPtr)0; - */ - } - - _parent = m_taintparent; - m_taintPhysics = IsPhysical; - } - - /// - /// Add a child prim to this parent prim. - /// - /// Child prim - private void AddChildPrim(OdePrim prim) - { - if (LocalID == prim.LocalID) - return; - - if (Body == IntPtr.Zero) - { - Body = d.BodyCreate(_parent_scene.world); - setMass(); - } - - lock (childrenPrim) - { - if (childrenPrim.Contains(prim)) - return; - -// m_log.DebugFormat( -// "[ODE PRIM]: Linking prim {0} {1} to {2} {3}", prim.Name, prim.LocalID, Name, LocalID); - - childrenPrim.Add(prim); - - foreach (OdePrim prm in childrenPrim) - { - d.Mass m2; - d.MassSetZero(out m2); - d.MassSetBoxTotal(out m2, prim.CalculateMass(), prm._size.X, prm._size.Y, prm._size.Z); - - d.Quaternion quat = new d.Quaternion(); - quat.W = prm._orientation.W; - quat.X = prm._orientation.X; - quat.Y = prm._orientation.Y; - quat.Z = prm._orientation.Z; - - d.Matrix3 mat = new d.Matrix3(); - d.RfromQ(out mat, ref quat); - d.MassRotate(ref m2, ref mat); - d.MassTranslate(ref m2, Position.X - prm.Position.X, Position.Y - prm.Position.Y, Position.Z - prm.Position.Z); - d.MassAdd(ref pMass, ref m2); - } - - foreach (OdePrim prm in childrenPrim) - { - prm.m_collisionCategories |= CollisionCategories.Body; - prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); - -//Console.WriteLine(" GeomSetCategoryBits 1: " + prm.prim_geom + " - " + (int)prm.m_collisionCategories + " for " + Name); - if (prm.m_assetFailed) - { - d.GeomSetCategoryBits(prm.prim_geom, 0); - d.GeomSetCollideBits(prm.prim_geom, prm.BadMeshAssetCollideBits); - } - else - { - d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories); - d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags); - } - - d.Quaternion quat = new d.Quaternion(); - quat.W = prm._orientation.W; - quat.X = prm._orientation.X; - quat.Y = prm._orientation.Y; - quat.Z = prm._orientation.Z; - - d.Matrix3 mat = new d.Matrix3(); - d.RfromQ(out mat, ref quat); - if (Body != IntPtr.Zero) - { - d.GeomSetBody(prm.prim_geom, Body); - prm.childPrim = true; - d.GeomSetOffsetWorldPosition(prm.prim_geom, prm.Position.X , prm.Position.Y, prm.Position.Z); - //d.GeomSetOffsetPosition(prim.prim_geom, - // (Position.X - prm.Position.X) - pMass.c.X, - // (Position.Y - prm.Position.Y) - pMass.c.Y, - // (Position.Z - prm.Position.Z) - pMass.c.Z); - d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); - //d.GeomSetOffsetRotation(prm.prim_geom, ref mat); - d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z); - d.BodySetMass(Body, ref pMass); - } - else - { - m_log.DebugFormat("[PHYSICS]: {0} ain't got no boooooooooddy, no body", Name); - } - - prm.m_interpenetrationcount = 0; - prm.m_collisionscore = 0; - prm.m_disabled = false; - - // The body doesn't already have a finite rotation mode set here - if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null) - { - prm.createAMotor(m_angularlock); - } - prm.Body = Body; - _parent_scene.ActivatePrim(prm); - } - - m_collisionCategories |= CollisionCategories.Body; - m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); - - if (m_assetFailed) - { - d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, BadMeshAssetCollideBits); - } - else - { - //Console.WriteLine("GeomSetCategoryBits 2: " + prim_geom + " - " + (int)m_collisionCategories + " for " + Name); - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - //Console.WriteLine(" Post GeomSetCategoryBits 2"); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); - } - - d.Quaternion quat2 = new d.Quaternion(); - quat2.W = _orientation.W; - quat2.X = _orientation.X; - quat2.Y = _orientation.Y; - quat2.Z = _orientation.Z; - - d.Matrix3 mat2 = new d.Matrix3(); - d.RfromQ(out mat2, ref quat2); - d.GeomSetBody(prim_geom, Body); - d.GeomSetOffsetWorldPosition(prim_geom, Position.X - pMass.c.X, Position.Y - pMass.c.Y, Position.Z - pMass.c.Z); - //d.GeomSetOffsetPosition(prim.prim_geom, - // (Position.X - prm.Position.X) - pMass.c.X, - // (Position.Y - prm.Position.Y) - pMass.c.Y, - // (Position.Z - prm.Position.Z) - pMass.c.Z); - //d.GeomSetOffsetRotation(prim_geom, ref mat2); - d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z); - d.BodySetMass(Body, ref pMass); - - d.BodySetAutoDisableFlag(Body, true); - d.BodySetAutoDisableSteps(Body, body_autodisable_frames); - - m_interpenetrationcount = 0; - m_collisionscore = 0; - m_disabled = false; - - // The body doesn't already have a finite rotation mode set here - if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null) - { - createAMotor(m_angularlock); - } - - d.BodySetPosition(Body, Position.X, Position.Y, Position.Z); - - if (m_vehicle.Type != Vehicle.TYPE_NONE) - m_vehicle.Enable(Body, _parent_scene); - - _parent_scene.ActivatePrim(this); - } - } - - private void ChildSetGeom(OdePrim odePrim) - { -// m_log.DebugFormat( -// "[ODE PRIM]: ChildSetGeom {0} {1} for {2} {3}", odePrim.Name, odePrim.LocalID, Name, LocalID); - - //if (IsPhysical && Body != IntPtr.Zero) - lock (childrenPrim) - { - foreach (OdePrim prm in childrenPrim) - { - //prm.childPrim = true; - prm.disableBody(); - //prm.m_taintparent = null; - //prm._parent = null; - //prm.m_taintPhysics = false; - //prm.m_disabled = true; - //prm.childPrim = false; - } - } - - disableBody(); - - // Spurious - Body == IntPtr.Zero after disableBody() -// if (Body != IntPtr.Zero) -// { -// _parent_scene.DeactivatePrim(this); -// } - - lock (childrenPrim) - { - foreach (OdePrim prm in childrenPrim) - { -//Console.WriteLine("ChildSetGeom calls ParentPrim"); - AddChildPrim(prm); - } - } - } - - private void ChildDelink(OdePrim odePrim) - { -// m_log.DebugFormat( -// "[ODE PRIM]: Delinking prim {0} {1} from {2} {3}", odePrim.Name, odePrim.LocalID, Name, LocalID); - - // Okay, we have a delinked child.. need to rebuild the body. - lock (childrenPrim) - { - foreach (OdePrim prm in childrenPrim) - { - prm.childPrim = true; - prm.disableBody(); - //prm.m_taintparent = null; - //prm._parent = null; - //prm.m_taintPhysics = false; - //prm.m_disabled = true; - //prm.childPrim = false; - } - } - - disableBody(); - - lock (childrenPrim) - { - //Console.WriteLine("childrenPrim.Remove " + odePrim); - childrenPrim.Remove(odePrim); - } - - // Spurious - Body == IntPtr.Zero after disableBody() -// if (Body != IntPtr.Zero) -// { -// _parent_scene.DeactivatePrim(this); -// } - - lock (childrenPrim) - { - foreach (OdePrim prm in childrenPrim) - { -//Console.WriteLine("ChildDelink calls ParentPrim"); - AddChildPrim(prm); - } - } - } - - /// - /// Change prim in response to a selection taint. - /// - private void changeSelectedStatus() - { - if (m_taintselected) - { - m_collisionCategories = CollisionCategories.Selected; - m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space); - - // We do the body disable soft twice because 'in theory' a collision could have happened - // in between the disabling and the collision properties setting - // which would wake the physical body up from a soft disabling and potentially cause it to fall - // through the ground. - - // NOTE FOR JOINTS: this doesn't always work for jointed assemblies because if you select - // just one part of the assembly, the rest of the assembly is non-selected and still simulating, - // so that causes the selected part to wake up and continue moving. - - // even if you select all parts of a jointed assembly, it is not guaranteed that the entire - // assembly will stop simulating during the selection, because of the lack of atomicity - // of select operations (their processing could be interrupted by a thread switch, causing - // simulation to continue before all of the selected object notifications trickle down to - // the physics engine). - - // e.g. we select 100 prims that are connected by joints. non-atomically, the first 50 are - // selected and disabled. then, due to a thread switch, the selection processing is - // interrupted and the physics engine continues to simulate, so the last 50 items, whose - // selection was not yet processed, continues to simulate. this wakes up ALL of the - // first 50 again. then the last 50 are disabled. then the first 50, which were just woken - // up, start simulating again, which in turn wakes up the last 50. - - if (IsPhysical) - { - disableBodySoft(); - } - - if (m_assetFailed) - { - d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, 0); - } - else - { - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); - } - - if (IsPhysical) - { - disableBodySoft(); - } - } - else - { - m_collisionCategories = CollisionCategories.Geom; - - if (IsPhysical) - m_collisionCategories |= CollisionCategories.Body; - - m_collisionFlags = m_default_collisionFlags; - - if (m_collidesLand) - m_collisionFlags |= CollisionCategories.Land; - if (m_collidesWater) - m_collisionFlags |= CollisionCategories.Water; - - if (m_assetFailed) - { - d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, BadMeshAssetCollideBits); - } - else - { - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); - } - - if (IsPhysical) - { - if (Body != IntPtr.Zero) - { - d.BodySetLinearVel(Body, 0f, 0f, 0f); - d.BodySetForce(Body, 0, 0, 0); - enableBodySoft(); - } - } - } - - resetCollisionAccounting(); - m_isSelected = m_taintselected; - }//end changeSelectedStatus - - internal void ResetTaints() - { - m_taintposition = _position; - m_taintrot = _orientation; - m_taintPhysics = IsPhysical; - m_taintselected = m_isSelected; - m_taintsize = _size; - m_taintshape = false; - m_taintforce = false; - m_taintdisable = false; - m_taintVelocity = Vector3.Zero; - } - - /// - /// Create a geometry for the given mesh in the given target space. - /// - /// - /// If null, then a mesh is used that is based on the profile shape data. - private void CreateGeom(IntPtr m_targetSpace, IMesh mesh) - { -#if SPAM -Console.WriteLine("CreateGeom:"); -#endif - if (mesh != null) - { - setMesh(_parent_scene, mesh); - } - else - { - if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) - { - if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) - { - if (((_size.X / 2f) > 0f)) - { -// _parent_scene.waitForSpaceUnlock(m_targetSpace); - try - { -//Console.WriteLine(" CreateGeom 1"); - SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); - m_expectedCollisionContacts = 3; - } - catch (AccessViolationException) - { - m_log.WarnFormat("[PHYSICS]: Unable to create physics proxy for object {0}", Name); - return; - } - } - else - { -// _parent_scene.waitForSpaceUnlock(m_targetSpace); - try - { -//Console.WriteLine(" CreateGeom 2"); - SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); - m_expectedCollisionContacts = 4; - } - catch (AccessViolationException) - { - m_log.WarnFormat("[PHYSICS]: Unable to create physics proxy for object {0}", Name); - return; - } - } - } - else - { -// _parent_scene.waitForSpaceUnlock(m_targetSpace); - try - { -//Console.WriteLine(" CreateGeom 3"); - SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); - m_expectedCollisionContacts = 4; - } - catch (AccessViolationException) - { - m_log.WarnFormat("[PHYSICS]: Unable to create physics proxy for object {0}", Name); - return; - } - } - } - else - { -// _parent_scene.waitForSpaceUnlock(m_targetSpace); - try - { -//Console.WriteLine(" CreateGeom 4"); - SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); - m_expectedCollisionContacts = 4; - } - catch (AccessViolationException) - { - m_log.WarnFormat("[PHYSICS]: Unable to create physics proxy for object {0}", Name); - return; - } - } - } - } - - /// - /// Remove the existing geom from this prim. - /// - /// - /// If null, then a mesh is used that is based on the profile shape data. - /// true if the geom was successfully removed, false if it was already gone or the remove failed. - internal bool RemoveGeom() - { - if (prim_geom != IntPtr.Zero) - { - try - { - _parent_scene.geom_name_map.Remove(prim_geom); - _parent_scene.actor_name_map.Remove(prim_geom); - d.GeomDestroy(prim_geom); - m_expectedCollisionContacts = 0; - prim_geom = IntPtr.Zero; - } - catch (System.AccessViolationException) - { - prim_geom = IntPtr.Zero; - m_expectedCollisionContacts = 0; - m_log.ErrorFormat("[PHYSICS]: PrimGeom dead for {0}", Name); - - return false; - } - - return true; - } - else - { - m_log.WarnFormat( - "[ODE PRIM]: Called RemoveGeom() on {0} {1} where geometry was already null.", Name, LocalID); - - return false; - } - } - /// - /// Add prim in response to an add taint. - /// - private void changeadd() - { -// m_log.DebugFormat("[ODE PRIM]: Adding prim {0}", Name); - - int[] iprimspaceArrItem = _parent_scene.calculateSpaceArrayItemFromPos(_position); - IntPtr targetspace = _parent_scene.calculateSpaceForGeom(_position); - - if (targetspace == IntPtr.Zero) - targetspace = _parent_scene.createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]); - - m_targetSpace = targetspace; - - IMesh mesh = null; - - if (_parent_scene.needsMeshing(_pbs)) - { - // Don't need to re-enable body.. it's done in SetMesh - mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical); - // createmesh returns null when it's a shape that isn't a cube. - // m_log.Debug(m_localID); - if (mesh == null) - CheckMeshAsset(); - else - m_assetFailed = false; - } - -#if SPAM -Console.WriteLine("changeadd 1"); -#endif - CreateGeom(m_targetSpace, mesh); - - d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); - d.Quaternion myrot = new d.Quaternion(); - myrot.X = _orientation.X; - myrot.Y = _orientation.Y; - myrot.Z = _orientation.Z; - myrot.W = _orientation.W; - d.GeomSetQuaternion(prim_geom, ref myrot); - - if (IsPhysical && Body == IntPtr.Zero) - enableBody(); - - changeSelectedStatus(); - - m_taintadd = false; - } - - /// - /// Move prim in response to a move taint. - /// - private void changemove() - { - if (IsPhysical) - { - if (!m_disabled && !m_taintremove && !childPrim) - { - if (Body == IntPtr.Zero) - enableBody(); - - //Prim auto disable after 20 frames, - //if you move it, re-enable the prim manually. - if (_parent != null) - { - if (m_linkJoint != IntPtr.Zero) - { - d.JointDestroy(m_linkJoint); - m_linkJoint = IntPtr.Zero; - } - } - - if (Body != IntPtr.Zero) - { - d.BodySetPosition(Body, _position.X, _position.Y, _position.Z); - - if (_parent != null) - { - OdePrim odParent = (OdePrim)_parent; - if (Body != (IntPtr)0 && odParent.Body != (IntPtr)0 && Body != odParent.Body) - { -// KF: Fixed Joints were removed? Anyway - this Console.WriteLine does not show up, so routine is not used?? -Console.WriteLine(" JointCreateFixed"); - m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup); - d.JointAttach(m_linkJoint, Body, odParent.Body); - d.JointSetFixed(m_linkJoint); - } - } - d.BodyEnable(Body); - if (m_vehicle.Type != Vehicle.TYPE_NONE) - { - m_vehicle.Enable(Body, _parent_scene); - } - } - else - { - m_log.WarnFormat("[PHYSICS]: Body for {0} still null after enableBody(). This is a crash scenario.", Name); - } - } - //else - // { - //m_log.Debug("[BUG]: race!"); - //} - } - - // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position); - // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position); -// _parent_scene.waitForSpaceUnlock(m_targetSpace); - - IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace); - m_targetSpace = tempspace; - -// _parent_scene.waitForSpaceUnlock(m_targetSpace); - - d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); - -// _parent_scene.waitForSpaceUnlock(m_targetSpace); - d.SpaceAdd(m_targetSpace, prim_geom); - - changeSelectedStatus(); - - resetCollisionAccounting(); - m_taintposition = _position; - } - - internal void Move(float timestep) - { - float fx = 0; - float fy = 0; - float fz = 0; - - if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // KF: Only move root prims. - { - if (m_vehicle.Type != Vehicle.TYPE_NONE) - { - // 'VEHICLES' are dealt with in ODEDynamics.cs - m_vehicle.Step(timestep, _parent_scene); - } - else - { -//Console.WriteLine("Move " + Name); - if (!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009 - // NON-'VEHICLES' are dealt with here -// if (d.BodyIsEnabled(Body) && !m_angularlock.ApproxEquals(Vector3.Zero, 0.003f)) -// { -// d.Vector3 avel2 = d.BodyGetAngularVel(Body); -// /* -// if (m_angularlock.X == 1) -// avel2.X = 0; -// if (m_angularlock.Y == 1) -// avel2.Y = 0; -// if (m_angularlock.Z == 1) -// avel2.Z = 0; -// d.BodySetAngularVel(Body, avel2.X, avel2.Y, avel2.Z); -// */ -// } - //float PID_P = 900.0f; - - float m_mass = CalculateMass(); - -// fz = 0f; - //m_log.Info(m_collisionFlags.ToString()); - - - //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle. - // would come from SceneObjectPart.cs, public void SetBuoyancy(float fvalue) , PhysActor.Buoyancy = fvalue; ?? - // m_buoyancy: (unlimited value) <0=Falls fast; 0=1g; 1=0g; >1 = floats up - // gravityz multiplier = 1 - m_buoyancy - fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass; - - if (m_usePID) - { -//Console.WriteLine("PID " + Name); - // KF - this is for object move? eg. llSetPos() ? - //if (!d.BodyIsEnabled(Body)) - //d.BodySetForce(Body, 0f, 0f, 0f); - // If we're using the PID controller, then we have no gravity - //fz = (-1 * _parent_scene.gravityz) * m_mass; //KF: ?? Prims have no global gravity,so simply... - fz = 0f; - - // no lock; for now it's only called from within Simulate() - - // If the PID Controller isn't active then we set our force - // calculating base velocity to the current position - - if ((m_PIDTau < 1) && (m_PIDTau != 0)) - { - //PID_G = PID_G / m_PIDTau; - m_PIDTau = 1; - } - - if ((PID_G - m_PIDTau) <= 0) - { - PID_G = m_PIDTau + 1; - } - //PidStatus = true; - - // PhysicsVector vec = new PhysicsVector(); - d.Vector3 vel = d.BodyGetLinearVel(Body); - - d.Vector3 pos = d.BodyGetPosition(Body); - _target_velocity = - new Vector3( - (m_PIDTarget.X - pos.X) * ((PID_G - m_PIDTau) * timestep), - (m_PIDTarget.Y - pos.Y) * ((PID_G - m_PIDTau) * timestep), - (m_PIDTarget.Z - pos.Z) * ((PID_G - m_PIDTau) * timestep) - ); - - // if velocity is zero, use position control; otherwise, velocity control - - if (_target_velocity.ApproxEquals(Vector3.Zero,0.1f)) - { - // keep track of where we stopped. No more slippin' & slidin' - - // We only want to deactivate the PID Controller if we think we want to have our surrogate - // react to the physics scene by moving it's position. - // Avatar to Avatar collisions - // Prim to avatar collisions - - //fx = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2); - //fy = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2); - //fz = fz + (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P; - d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z); - d.BodySetLinearVel(Body, 0, 0, 0); - d.BodyAddForce(Body, 0, 0, fz); - return; - } - else - { - _zeroFlag = false; - - // We're flying and colliding with something - fx = ((_target_velocity.X) - vel.X) * (PID_D); - fy = ((_target_velocity.Y) - vel.Y) * (PID_D); - - // vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P; - - fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass); - } - } // end if (m_usePID) - - // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller - if (m_useHoverPID && !m_usePID) - { -//Console.WriteLine("Hover " + Name); - - // If we're using the PID controller, then we have no gravity - fz = (-1 * _parent_scene.gravityz) * m_mass; - - // no lock; for now it's only called from within Simulate() - - // If the PID Controller isn't active then we set our force - // calculating base velocity to the current position - - if ((m_PIDTau < 1)) - { - PID_G = PID_G / m_PIDTau; - } - - if ((PID_G - m_PIDTau) <= 0) - { - PID_G = m_PIDTau + 1; - } - - // Where are we, and where are we headed? - d.Vector3 pos = d.BodyGetPosition(Body); - d.Vector3 vel = d.BodyGetLinearVel(Body); - - // Non-Vehicles have a limited set of Hover options. - // determine what our target height really is based on HoverType - switch (m_PIDHoverType) - { - case PIDHoverType.Ground: - m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y); - m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight; - break; - case PIDHoverType.GroundAndWater: - m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y); - m_waterHeight = _parent_scene.GetWaterLevel(); - if (m_groundHeight > m_waterHeight) - { - m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight; - } - else - { - m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight; - } - break; - - } // end switch (m_PIDHoverType) - - - _target_velocity = - new Vector3(0.0f, 0.0f, - (m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep) - ); - - // if velocity is zero, use position control; otherwise, velocity control - - if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f)) - { - // keep track of where we stopped. No more slippin' & slidin' - - // We only want to deactivate the PID Controller if we think we want to have our surrogate - // react to the physics scene by moving it's position. - // Avatar to Avatar collisions - // Prim to avatar collisions - - d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight); - d.BodySetLinearVel(Body, vel.X, vel.Y, 0); - d.BodyAddForce(Body, 0, 0, fz); - return; - } - else - { - _zeroFlag = false; - - // We're flying and colliding with something - fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass); - } - } - - fx *= m_mass; - fy *= m_mass; - //fz *= m_mass; - - fx += m_force.X; - fy += m_force.Y; - fz += m_force.Z; - - //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString()); - if (fx != 0 || fy != 0 || fz != 0) - { - //m_taintdisable = true; - //base.RaiseOutOfBounds(Position); - //d.BodySetLinearVel(Body, fx, fy, 0f); - if (!d.BodyIsEnabled(Body)) - { - // A physical body at rest on a surface will auto-disable after a while, - // this appears to re-enable it incase the surface it is upon vanishes, - // and the body should fall again. - d.BodySetLinearVel(Body, 0f, 0f, 0f); - d.BodySetForce(Body, 0, 0, 0); - enableBodySoft(); - } - - // 35x10 = 350n times the mass per second applied maximum. - float nmax = 35f * m_mass; - float nmin = -35f * m_mass; - - if (fx > nmax) - fx = nmax; - if (fx < nmin) - fx = nmin; - if (fy > nmax) - fy = nmax; - if (fy < nmin) - fy = nmin; - d.BodyAddForce(Body, fx, fy, fz); -//Console.WriteLine("AddForce " + fx + "," + fy + "," + fz); - } - } - } - else - { // is not physical, or is not a body or is selected - // _zeroPosition = d.BodyGetPosition(Body); - return; -//Console.WriteLine("Nothing " + Name); - - } - } - - private void rotate() - { - d.Quaternion myrot = new d.Quaternion(); - myrot.X = _orientation.X; - myrot.Y = _orientation.Y; - myrot.Z = _orientation.Z; - myrot.W = _orientation.W; - if (Body != IntPtr.Zero) - { - // KF: If this is a root prim do BodySet - d.BodySetQuaternion(Body, ref myrot); - if (IsPhysical) - { - if (!m_angularlock.ApproxEquals(Vector3.One, 0f)) - createAMotor(m_angularlock); - } - } - else - { - // daughter prim, do Geom set - d.GeomSetQuaternion(prim_geom, ref myrot); - } - - resetCollisionAccounting(); - m_taintrot = _orientation; - } - - private void resetCollisionAccounting() - { - m_collisionscore = 0; - m_interpenetrationcount = 0; - m_disabled = false; - } - - /// - /// Change prim in response to a disable taint. - /// - private void changedisable() - { - m_disabled = true; - if (Body != IntPtr.Zero) - { - d.BodyDisable(Body); - Body = IntPtr.Zero; - } - - m_taintdisable = false; - } - - /// - /// Change prim in response to a physics status taint - /// - private void changePhysicsStatus() - { - if (IsPhysical) - { - if (Body == IntPtr.Zero) - { - if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim) - { - changeshape(); - } - else - { - enableBody(); - } - } - } - else - { - if (Body != IntPtr.Zero) - { - if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim) - { - RemoveGeom(); - -//Console.WriteLine("changePhysicsStatus for " + Name); - changeadd(); - } - - if (childPrim) - { - if (_parent != null) - { - OdePrim parent = (OdePrim)_parent; - parent.ChildDelink(this); - } - } - else - { - disableBody(); - } - } - } - - changeSelectedStatus(); - - resetCollisionAccounting(); - m_taintPhysics = IsPhysical; - } - - /// - /// Change prim in response to a size taint. - /// - private void changesize() - { -#if SPAM - m_log.DebugFormat("[ODE PRIM]: Called changesize"); -#endif - - if (_size.X <= 0) _size.X = 0.01f; - if (_size.Y <= 0) _size.Y = 0.01f; - if (_size.Z <= 0) _size.Z = 0.01f; - - //kill body to rebuild - if (IsPhysical && Body != IntPtr.Zero) - { - if (childPrim) - { - if (_parent != null) - { - OdePrim parent = (OdePrim)_parent; - parent.ChildDelink(this); - } - } - else - { - disableBody(); - } - } - - if (d.SpaceQuery(m_targetSpace, prim_geom)) - { -// _parent_scene.waitForSpaceUnlock(m_targetSpace); - d.SpaceRemove(m_targetSpace, prim_geom); - } - - RemoveGeom(); - - // we don't need to do space calculation because the client sends a position update also. - - IMesh mesh = null; - - // Construction of new prim - if (_parent_scene.needsMeshing(_pbs)) - { - float meshlod = _parent_scene.meshSculptLOD; - - if (IsPhysical) - meshlod = _parent_scene.MeshSculptphysicalLOD; - // Don't need to re-enable body.. it's done in SetMesh - - if (_parent_scene.needsMeshing(_pbs)) - { - mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical); - if (mesh == null) - CheckMeshAsset(); - else - m_assetFailed = false; - } - - } - - CreateGeom(m_targetSpace, mesh); - d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); - d.Quaternion myrot = new d.Quaternion(); - myrot.X = _orientation.X; - myrot.Y = _orientation.Y; - myrot.Z = _orientation.Z; - myrot.W = _orientation.W; - d.GeomSetQuaternion(prim_geom, ref myrot); - - //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z); - if (IsPhysical && Body == IntPtr.Zero && !childPrim) - { - // Re creates body on size. - // EnableBody also does setMass() - enableBody(); - d.BodyEnable(Body); - } - - changeSelectedStatus(); - - if (childPrim) - { - if (_parent is OdePrim) - { - OdePrim parent = (OdePrim)_parent; - parent.ChildSetGeom(this); - } - } - resetCollisionAccounting(); - m_taintsize = _size; - } - - /// - /// Change prim in response to a float on water taint. - /// - /// - private void changefloatonwater() - { - m_collidesWater = m_taintCollidesWater; - - if (m_collidesWater) - { - m_collisionFlags |= CollisionCategories.Water; - } - else - { - m_collisionFlags &= ~CollisionCategories.Water; - } - - if (m_assetFailed) - d.GeomSetCollideBits(prim_geom, BadMeshAssetCollideBits); - else - - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); - } - /// - /// Change prim in response to a shape taint. - /// - private void changeshape() - { - m_taintshape = false; - - // Cleanup of old prim geometry and Bodies - if (IsPhysical && Body != IntPtr.Zero) - { - if (childPrim) - { - if (_parent != null) - { - OdePrim parent = (OdePrim)_parent; - parent.ChildDelink(this); - } - } - else - { - disableBody(); - } - } - - RemoveGeom(); - - // we don't need to do space calculation because the client sends a position update also. - if (_size.X <= 0) _size.X = 0.01f; - if (_size.Y <= 0) _size.Y = 0.01f; - if (_size.Z <= 0) _size.Z = 0.01f; - // Construction of new prim - - IMesh mesh = null; - - - if (_parent_scene.needsMeshing(_pbs)) - { - // Don't need to re-enable body.. it's done in CreateMesh - float meshlod = _parent_scene.meshSculptLOD; - - if (IsPhysical) - meshlod = _parent_scene.MeshSculptphysicalLOD; - - // createmesh returns null when it doesn't mesh. - mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical); - if (mesh == null) - CheckMeshAsset(); - else - m_assetFailed = false; - } - - CreateGeom(m_targetSpace, mesh); - d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); - d.Quaternion myrot = new d.Quaternion(); - //myrot.W = _orientation.w; - myrot.W = _orientation.W; - myrot.X = _orientation.X; - myrot.Y = _orientation.Y; - myrot.Z = _orientation.Z; - d.GeomSetQuaternion(prim_geom, ref myrot); - - //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z); - if (IsPhysical && Body == IntPtr.Zero) - { - // Re creates body on size. - // EnableBody also does setMass() - enableBody(); - if (Body != IntPtr.Zero) - { - d.BodyEnable(Body); - } - } - - changeSelectedStatus(); - - if (childPrim) - { - if (_parent is OdePrim) - { - OdePrim parent = (OdePrim)_parent; - parent.ChildSetGeom(this); - } - } - - resetCollisionAccounting(); -// m_taintshape = false; - } - - /// - /// Change prim in response to an add force taint. - /// - private void changeAddForce() - { - if (!m_isSelected) - { - lock (m_forcelist) - { - //m_log.Info("[PHYSICS]: dequeing forcelist"); - if (IsPhysical) - { - Vector3 iforce = Vector3.Zero; - int i = 0; - try - { - for (i = 0; i < m_forcelist.Count; i++) - { - - iforce = iforce + (m_forcelist[i] * 100); - } - } - catch (IndexOutOfRangeException) - { - m_forcelist = new List(); - m_collisionscore = 0; - m_interpenetrationcount = 0; - m_taintforce = false; - return; - } - catch (ArgumentOutOfRangeException) - { - m_forcelist = new List(); - m_collisionscore = 0; - m_interpenetrationcount = 0; - m_taintforce = false; - return; - } - d.BodyEnable(Body); - d.BodyAddForce(Body, iforce.X, iforce.Y, iforce.Z); - } - m_forcelist.Clear(); - } - - m_collisionscore = 0; - m_interpenetrationcount = 0; - } - - m_taintforce = false; - } - - /// - /// Change prim in response to a torque taint. - /// - private void changeSetTorque() - { - if (!m_isSelected) - { - if (IsPhysical && Body != IntPtr.Zero) - { - d.BodySetTorque(Body, m_taintTorque.X, m_taintTorque.Y, m_taintTorque.Z); - } - } - - m_taintTorque = Vector3.Zero; - } - - /// - /// Change prim in response to an angular force taint. - /// - private void changeAddAngularForce() - { - if (!m_isSelected) - { - lock (m_angularforcelist) - { - //m_log.Info("[PHYSICS]: dequeing forcelist"); - if (IsPhysical) - { - Vector3 iforce = Vector3.Zero; - for (int i = 0; i < m_angularforcelist.Count; i++) - { - iforce = iforce + (m_angularforcelist[i] * 100); - } - d.BodyEnable(Body); - d.BodyAddTorque(Body, iforce.X, iforce.Y, iforce.Z); - - } - m_angularforcelist.Clear(); - } - - m_collisionscore = 0; - m_interpenetrationcount = 0; - } - - m_taintaddangularforce = false; - } - - /// - /// Change prim in response to a velocity taint. - /// - private void changevelocity() - { - if (!m_isSelected) - { - // Not sure exactly why this sleep is here, but from experimentation it appears to stop an avatar - // walking through a default rez size prim if it keeps kicking it around - justincc. - Thread.Sleep(20); - - if (IsPhysical) - { - if (Body != IntPtr.Zero) - { - d.BodySetLinearVel(Body, m_taintVelocity.X, m_taintVelocity.Y, m_taintVelocity.Z); - } - } - - //resetCollisionAccounting(); - } - - m_taintVelocity = Vector3.Zero; - } - - internal void setPrimForRemoval() - { - m_taintremove = true; - } - - public override bool Flying - { - // no flying prims for you - get { return false; } - set { } - } - - public override bool IsColliding - { - get { return iscolliding; } - set { iscolliding = value; } - } - - public override bool CollidingGround - { - get { return false; } - set { return; } - } - - public override bool CollidingObj - { - get { return false; } - set { return; } - } - - public override bool ThrottleUpdates - { - get { return m_throttleUpdates; } - set { m_throttleUpdates = value; } - } - - public override bool Stopped - { - get { return _zeroFlag; } - } - - public override Vector3 Position - { - get { return _position; } - - set { _position = value; - //m_log.Info("[PHYSICS]: " + _position.ToString()); - } - } - - public override Vector3 Size - { - get { return _size; } - set - { - if (value.IsFinite()) - { - _size = value; -// m_log.DebugFormat("[PHYSICS]: Set size on {0} to {1}", Name, value); - } - else - { - m_log.WarnFormat("[PHYSICS]: Got NaN Size on object {0}", Name); - } - } - } - - public override float Mass - { - get { return CalculateMass(); } - } - - public override Vector3 Force - { - //get { return Vector3.Zero; } - get { return m_force; } - set - { - if (value.IsFinite()) - { - m_force = value; - } - else - { - m_log.WarnFormat("[PHYSICS]: NaN in Force Applied to an Object {0}", Name); - } - } - } - - public override int VehicleType - { - get { return (int)m_vehicle.Type; } - set { m_vehicle.ProcessTypeChange((Vehicle)value); } - } - - public override void VehicleFloatParam(int param, float value) - { - m_vehicle.ProcessFloatVehicleParam((Vehicle) param, value); - } - - public override void VehicleVectorParam(int param, Vector3 value) - { - m_vehicle.ProcessVectorVehicleParam((Vehicle) param, value); - } - - public override void VehicleRotationParam(int param, Quaternion rotation) - { - m_vehicle.ProcessRotationVehicleParam((Vehicle) param, rotation); - } - - public override void VehicleFlags(int param, bool remove) - { - m_vehicle.ProcessVehicleFlags(param, remove); - } - - public override void SetVolumeDetect(int param) - { - // We have to lock the scene here so that an entire simulate loop either uses volume detect for all - // possible collisions with this prim or for none of them. - lock (_parent_scene.OdeLock) - { - m_isVolumeDetect = (param != 0); - } - } - - public override Vector3 CenterOfMass - { - get { return Vector3.Zero; } - } - - public override Vector3 GeometricCenter - { - get { return Vector3.Zero; } - } - - public override PrimitiveBaseShape Shape - { - set - { - _pbs = value; - m_assetFailed = false; - m_taintshape = true; - } - } - - public override Vector3 Velocity - { - get - { - // Average previous velocity with the new one so - // client object interpolation works a 'little' better - if (_zeroFlag) - return Vector3.Zero; - - Vector3 returnVelocity = Vector3.Zero; - returnVelocity.X = (m_lastVelocity.X + _velocity.X) * 0.5f; // 0.5f is mathematically equiv to '/ 2' - returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y) * 0.5f; - returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z) * 0.5f; - return returnVelocity; - } - set - { - if (value.IsFinite()) - { - _velocity = value; - - m_taintVelocity = value; - _parent_scene.AddPhysicsActorTaint(this); - } - else - { - m_log.WarnFormat("[PHYSICS]: Got NaN Velocity in Object {0}", Name); - } - - } - } - - public override Vector3 Torque - { - get - { - if (!IsPhysical || Body == IntPtr.Zero) - return Vector3.Zero; - - return _torque; - } - - set - { - if (value.IsFinite()) - { - m_taintTorque = value; - _parent_scene.AddPhysicsActorTaint(this); - } - else - { - m_log.WarnFormat("[PHYSICS]: Got NaN Torque in Object {0}", Name); - } - } - } - - public override float CollisionScore - { - get { return m_collisionscore; } - set { m_collisionscore = value; } - } - - public override bool Kinematic - { - get { return false; } - set { } - } - - public override Quaternion Orientation - { - get { return _orientation; } - set - { - if (QuaternionIsFinite(value)) - _orientation = value; - else - m_log.WarnFormat("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object {0}", Name); - } - } - - private static bool QuaternionIsFinite(Quaternion q) - { - if (Single.IsNaN(q.X) || Single.IsInfinity(q.X)) - return false; - if (Single.IsNaN(q.Y) || Single.IsInfinity(q.Y)) - return false; - if (Single.IsNaN(q.Z) || Single.IsInfinity(q.Z)) - return false; - if (Single.IsNaN(q.W) || Single.IsInfinity(q.W)) - return false; - return true; - } - - public override Vector3 Acceleration - { - get { return _acceleration; } - set { _acceleration = value; } - } - - public override void AddForce(Vector3 force, bool pushforce) - { - if (force.IsFinite()) - { - lock (m_forcelist) - m_forcelist.Add(force); - - m_taintforce = true; - } - else - { - m_log.WarnFormat("[PHYSICS]: Got Invalid linear force vector from Scene in Object {0}", Name); - } - //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString()); - } - - public override void AddAngularForce(Vector3 force, bool pushforce) - { - if (force.IsFinite()) - { - m_angularforcelist.Add(force); - m_taintaddangularforce = true; - } - else - { - m_log.WarnFormat("[PHYSICS]: Got Invalid Angular force vector from Scene in Object {0}", Name); - } - } - - public override Vector3 RotationalVelocity - { - get - { - Vector3 pv = Vector3.Zero; - if (_zeroFlag) - return pv; - m_lastUpdateSent = false; - - if (m_rotationalVelocity.ApproxEquals(pv, 0.2f)) - return pv; - - return m_rotationalVelocity; - } - set - { - if (value.IsFinite()) - { - m_rotationalVelocity = value; - } - else - { - m_log.WarnFormat("[PHYSICS]: Got NaN RotationalVelocity in Object {0}", Name); - } - } - } - - public override void CrossingFailure() - { - m_crossingfailures++; - if (m_crossingfailures > _parent_scene.geomCrossingFailuresBeforeOutofbounds) - { - base.RaiseOutOfBounds(_position); - return; - } - else if (m_crossingfailures == _parent_scene.geomCrossingFailuresBeforeOutofbounds) - { - m_log.Warn("[PHYSICS]: Too many crossing failures for: " + Name); - } - } - - public override float Buoyancy - { - get { return m_buoyancy; } - set { m_buoyancy = value; } - } - - public override void link(PhysicsActor obj) - { - m_taintparent = obj; - } - - public override void delink() - { - m_taintparent = null; - } - - public override void LockAngularMotion(Vector3 axis) - { - // reverse the zero/non zero values for ODE. - if (axis.IsFinite()) - { - axis.X = (axis.X > 0) ? 1f : 0f; - axis.Y = (axis.Y > 0) ? 1f : 0f; - axis.Z = (axis.Z > 0) ? 1f : 0f; - m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z); - m_taintAngularLock = axis; - } - else - { - m_log.WarnFormat("[PHYSICS]: Got NaN locking axis from Scene on Object {0}", Name); - } - } - - internal void UpdatePositionAndVelocity() - { - // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! - if (_parent == null) - { - Vector3 pv = Vector3.Zero; - bool lastZeroFlag = _zeroFlag; - float m_minvelocity = 0; - if (Body != (IntPtr)0) // FIXME -> or if it is a joint - { - d.Vector3 vec = d.BodyGetPosition(Body); - d.Quaternion ori = d.BodyGetQuaternion(Body); - d.Vector3 vel = d.BodyGetLinearVel(Body); - d.Vector3 rotvel = d.BodyGetAngularVel(Body); - d.Vector3 torque = d.BodyGetTorque(Body); - _torque = new Vector3(torque.X, torque.Y, torque.Z); - Vector3 l_position = Vector3.Zero; - Quaternion l_orientation = Quaternion.Identity; - - // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!) - //if (vec.X < 0.0f) { vec.X = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } - //if (vec.Y < 0.0f) { vec.Y = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } - //if (vec.X > 255.95f) { vec.X = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } - //if (vec.Y > 255.95f) { vec.Y = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } - - m_lastposition = _position; - m_lastorientation = _orientation; - - l_position.X = vec.X; - l_position.Y = vec.Y; - l_position.Z = vec.Z; - l_orientation.X = ori.X; - l_orientation.Y = ori.Y; - l_orientation.Z = ori.Z; - l_orientation.W = ori.W; - - if (l_position.X > ((int)_parent_scene.WorldExtents.X - 0.05f) || l_position.X < 0f || l_position.Y > ((int)_parent_scene.WorldExtents.Y - 0.05f) || l_position.Y < 0f) - { - //base.RaiseOutOfBounds(l_position); - - if (m_crossingfailures < _parent_scene.geomCrossingFailuresBeforeOutofbounds) - { - _position = l_position; - //_parent_scene.remActivePrim(this); - if (_parent == null) - base.RequestPhysicsterseUpdate(); - return; - } - else - { - if (_parent == null) - base.RaiseOutOfBounds(l_position); - return; - } - } - - if (l_position.Z < 0) - { - // This is so prim that get lost underground don't fall forever and suck up - // - // Sim resources and memory. - // Disables the prim's movement physics.... - // It's a hack and will generate a console message if it fails. - - //IsPhysical = false; - if (_parent == null) - base.RaiseOutOfBounds(_position); - - _acceleration.X = 0; - _acceleration.Y = 0; - _acceleration.Z = 0; - - _velocity.X = 0; - _velocity.Y = 0; - _velocity.Z = 0; - m_rotationalVelocity.X = 0; - m_rotationalVelocity.Y = 0; - m_rotationalVelocity.Z = 0; - - if (_parent == null) - base.RequestPhysicsterseUpdate(); - - m_throttleUpdates = false; - throttleCounter = 0; - _zeroFlag = true; - //outofBounds = true; - } - - //float Adiff = 1.0f - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)); -//Console.WriteLine("Adiff " + Name + " = " + Adiff); - if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02) - && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02) - && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02) -// && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.01)) - && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.0001)) // KF 0.01 is far to large - { - _zeroFlag = true; -//Console.WriteLine("ZFT 2"); - m_throttleUpdates = false; - } - else - { - //m_log.Debug(Math.Abs(m_lastposition.X - l_position.X).ToString()); - _zeroFlag = false; - m_lastUpdateSent = false; - //m_throttleUpdates = false; - } - - if (_zeroFlag) - { - _velocity.X = 0.0f; - _velocity.Y = 0.0f; - _velocity.Z = 0.0f; - - _acceleration.X = 0; - _acceleration.Y = 0; - _acceleration.Z = 0; - - //_orientation.w = 0f; - //_orientation.X = 0f; - //_orientation.Y = 0f; - //_orientation.Z = 0f; - m_rotationalVelocity.X = 0; - m_rotationalVelocity.Y = 0; - m_rotationalVelocity.Z = 0; - if (!m_lastUpdateSent) - { - m_throttleUpdates = false; - throttleCounter = 0; - m_rotationalVelocity = pv; - - if (_parent == null) - { - base.RequestPhysicsterseUpdate(); - } - - m_lastUpdateSent = true; - } - } - else - { - if (lastZeroFlag != _zeroFlag) - { - if (_parent == null) - { - base.RequestPhysicsterseUpdate(); - } - } - - m_lastVelocity = _velocity; - - _position = l_position; - - _velocity.X = vel.X; - _velocity.Y = vel.Y; - _velocity.Z = vel.Z; - - _acceleration = ((_velocity - m_lastVelocity) / 0.1f); - _acceleration = new Vector3(_velocity.X - m_lastVelocity.X / 0.1f, _velocity.Y - m_lastVelocity.Y / 0.1f, _velocity.Z - m_lastVelocity.Z / 0.1f); - //m_log.Info("[PHYSICS]: V1: " + _velocity + " V2: " + m_lastVelocity + " Acceleration: " + _acceleration.ToString()); - - // Note here that linearvelocity is affecting angular velocity... so I'm guessing this is a vehicle specific thing... - // it does make sense to do this for tiny little instabilities with physical prim, however 0.5m/frame is fairly large. - // reducing this to 0.02m/frame seems to help the angular rubberbanding quite a bit, however, to make sure it doesn't affect elevators and vehicles - // adding these logical exclusion situations to maintain this where I think it was intended to be. - if (m_throttleUpdates || m_usePID || (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) || (Amotor != IntPtr.Zero)) - { - m_minvelocity = 0.5f; - } - else - { - m_minvelocity = 0.02f; - } - - if (_velocity.ApproxEquals(pv, m_minvelocity)) - { - m_rotationalVelocity = pv; - } - else - { - m_rotationalVelocity = new Vector3(rotvel.X, rotvel.Y, rotvel.Z); - } - - //m_log.Debug("ODE: " + m_rotationalVelocity.ToString()); - _orientation.X = ori.X; - _orientation.Y = ori.Y; - _orientation.Z = ori.Z; - _orientation.W = ori.W; - m_lastUpdateSent = false; - if (!m_throttleUpdates || throttleCounter > _parent_scene.geomUpdatesPerThrottledUpdate) - { - if (_parent == null) - { - base.RequestPhysicsterseUpdate(); - } - } - else - { - throttleCounter++; - } - } - m_lastposition = l_position; - } - else - { - // Not a body.. so Make sure the client isn't interpolating - _velocity.X = 0; - _velocity.Y = 0; - _velocity.Z = 0; - - _acceleration.X = 0; - _acceleration.Y = 0; - _acceleration.Z = 0; - - m_rotationalVelocity.X = 0; - m_rotationalVelocity.Y = 0; - m_rotationalVelocity.Z = 0; - _zeroFlag = true; - } - } - } - - public override bool FloatOnWater - { - set { - m_taintCollidesWater = value; - _parent_scene.AddPhysicsActorTaint(this); - } - } - - public override void SetMomentum(Vector3 momentum) - { - } - - public override Vector3 PIDTarget - { - set - { - if (value.IsFinite()) - { - m_PIDTarget = value; - } - else - m_log.WarnFormat("[PHYSICS]: Got NaN PIDTarget from Scene on Object {0}", Name); - } - } - public override bool PIDActive { set { m_usePID = value; } } - public override float PIDTau { set { m_PIDTau = value; } } - - public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } } - public override bool PIDHoverActive { set { m_useHoverPID = value; } } - public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } } - public override float PIDHoverTau { set { m_PIDHoverTau = value; } } - - public override Quaternion APIDTarget{ set { return; } } - - public override bool APIDActive{ set { return; } } - - public override float APIDStrength{ set { return; } } - - public override float APIDDamping{ set { return; } } - - private void createAMotor(Vector3 axis) - { - if (Body == IntPtr.Zero) - return; - - if (Amotor != IntPtr.Zero) - { - d.JointDestroy(Amotor); - Amotor = IntPtr.Zero; - } - - float axisnum = 3; - - axisnum = (axisnum - (axis.X + axis.Y + axis.Z)); - - // PhysicsVector totalSize = new PhysicsVector(_size.X, _size.Y, _size.Z); - - - // Inverse Inertia Matrix, set the X, Y, and/r Z inertia to 0 then invert it again. - d.Mass objMass; - d.MassSetZero(out objMass); - DMassCopy(ref pMass, ref objMass); - - //m_log.DebugFormat("1-{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, ", objMass.I.M00, objMass.I.M01, objMass.I.M02, objMass.I.M10, objMass.I.M11, objMass.I.M12, objMass.I.M20, objMass.I.M21, objMass.I.M22); - - Matrix4 dMassMat = FromDMass(objMass); - - Matrix4 mathmat = Inverse(dMassMat); - - /* - //m_log.DebugFormat("2-{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, ", mathmat[0, 0], mathmat[0, 1], mathmat[0, 2], mathmat[1, 0], mathmat[1, 1], mathmat[1, 2], mathmat[2, 0], mathmat[2, 1], mathmat[2, 2]); - - mathmat = Inverse(mathmat); - - - objMass = FromMatrix4(mathmat, ref objMass); - //m_log.DebugFormat("3-{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, ", objMass.I.M00, objMass.I.M01, objMass.I.M02, objMass.I.M10, objMass.I.M11, objMass.I.M12, objMass.I.M20, objMass.I.M21, objMass.I.M22); - - mathmat = Inverse(mathmat); - */ - if (axis.X == 0) - { - mathmat.M33 = 50.0000001f; - //objMass.I.M22 = 0; - } - if (axis.Y == 0) - { - mathmat.M22 = 50.0000001f; - //objMass.I.M11 = 0; - } - if (axis.Z == 0) - { - mathmat.M11 = 50.0000001f; - //objMass.I.M00 = 0; - } - - - - mathmat = Inverse(mathmat); - objMass = FromMatrix4(mathmat, ref objMass); - //m_log.DebugFormat("4-{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, ", objMass.I.M00, objMass.I.M01, objMass.I.M02, objMass.I.M10, objMass.I.M11, objMass.I.M12, objMass.I.M20, objMass.I.M21, objMass.I.M22); - - //return; - if (d.MassCheck(ref objMass)) - { - d.BodySetMass(Body, ref objMass); - } - else - { - //m_log.Debug("[PHYSICS]: Mass invalid, ignoring"); - } - - if (axisnum <= 0) - return; - // int dAMotorEuler = 1; - - Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero); - d.JointAttach(Amotor, Body, IntPtr.Zero); - d.JointSetAMotorMode(Amotor, 0); - - d.JointSetAMotorNumAxes(Amotor,(int)axisnum); - int i = 0; - - if (axis.X == 0) - { - d.JointSetAMotorAxis(Amotor, i, 0, 1, 0, 0); - i++; - } - - if (axis.Y == 0) - { - d.JointSetAMotorAxis(Amotor, i, 0, 0, 1, 0); - i++; - } - - if (axis.Z == 0) - { - d.JointSetAMotorAxis(Amotor, i, 0, 0, 0, 1); - i++; - } - - for (int j = 0; j < (int)axisnum; j++) - { - //d.JointSetAMotorAngle(Amotor, j, 0); - } - - //d.JointSetAMotorAngle(Amotor, 1, 0); - //d.JointSetAMotorAngle(Amotor, 2, 0); - - // These lowstops and high stops are effectively (no wiggle room) - d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -0f); - d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0f); - d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -0f); - d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0f); - d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); - d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0f); - //d.JointSetAMotorParam(Amotor, (int) dParam.Vel, 9000f); - d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f); - d.JointSetAMotorParam(Amotor, (int)dParam.FMax, Mass * 50f);// - } - - private Matrix4 FromDMass(d.Mass pMass) - { - Matrix4 obj; - obj.M11 = pMass.I.M00; - obj.M12 = pMass.I.M01; - obj.M13 = pMass.I.M02; - obj.M14 = 0; - obj.M21 = pMass.I.M10; - obj.M22 = pMass.I.M11; - obj.M23 = pMass.I.M12; - obj.M24 = 0; - obj.M31 = pMass.I.M20; - obj.M32 = pMass.I.M21; - obj.M33 = pMass.I.M22; - obj.M34 = 0; - obj.M41 = 0; - obj.M42 = 0; - obj.M43 = 0; - obj.M44 = 1; - return obj; - } - - private d.Mass FromMatrix4(Matrix4 pMat, ref d.Mass obj) - { - obj.I.M00 = pMat[0, 0]; - obj.I.M01 = pMat[0, 1]; - obj.I.M02 = pMat[0, 2]; - obj.I.M10 = pMat[1, 0]; - obj.I.M11 = pMat[1, 1]; - obj.I.M12 = pMat[1, 2]; - obj.I.M20 = pMat[2, 0]; - obj.I.M21 = pMat[2, 1]; - obj.I.M22 = pMat[2, 2]; - return obj; - } - - public override void SubscribeEvents(int ms) - { - m_eventsubscription = ms; - _parent_scene.AddCollisionEventReporting(this); - } - - public override void UnSubscribeEvents() - { - _parent_scene.RemoveCollisionEventReporting(this); - m_eventsubscription = 0; - } - - public void AddCollisionEvent(uint CollidedWith, ContactPoint contact) - { - CollisionEventsThisFrame.AddCollider(CollidedWith, contact); - } - - public void SendCollisions() - { - if (m_collisionsOnPreviousFrame || CollisionEventsThisFrame.Count > 0) - { - base.SendCollisionUpdate(CollisionEventsThisFrame); - - if (CollisionEventsThisFrame.Count > 0) - { - m_collisionsOnPreviousFrame = true; - CollisionEventsThisFrame.Clear(); - } - else - { - m_collisionsOnPreviousFrame = false; - } - } - } - - public override bool SubscribedEvents() - { - if (m_eventsubscription > 0) - return true; - return false; - } - - public static Matrix4 Inverse(Matrix4 pMat) - { - if (determinant3x3(pMat) == 0) - { - return Matrix4.Identity; // should probably throw an error. singluar matrix inverse not possible - } - - return (Adjoint(pMat) / determinant3x3(pMat)); - } - - public static Matrix4 Adjoint(Matrix4 pMat) - { - Matrix4 adjointMatrix = new Matrix4(); - for (int i=0; i<4; i++) - { - for (int j=0; j<4; j++) - { - Matrix4SetValue(ref adjointMatrix, i, j, (float)(Math.Pow(-1, i + j) * (determinant3x3(Minor(pMat, i, j))))); - } - } - - adjointMatrix = Transpose(adjointMatrix); - return adjointMatrix; - } - - public static Matrix4 Minor(Matrix4 matrix, int iRow, int iCol) - { - Matrix4 minor = new Matrix4(); - int m = 0, n = 0; - for (int i = 0; i < 4; i++) - { - if (i == iRow) - continue; - n = 0; - for (int j = 0; j < 4; j++) - { - if (j == iCol) - continue; - Matrix4SetValue(ref minor, m,n, matrix[i, j]); - n++; - } - m++; - } - - return minor; - } - - public static Matrix4 Transpose(Matrix4 pMat) - { - Matrix4 transposeMatrix = new Matrix4(); - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) - Matrix4SetValue(ref transposeMatrix, i, j, pMat[j, i]); - return transposeMatrix; - } - - public static void Matrix4SetValue(ref Matrix4 pMat, int r, int c, float val) - { - switch (r) - { - case 0: - switch (c) - { - case 0: - pMat.M11 = val; - break; - case 1: - pMat.M12 = val; - break; - case 2: - pMat.M13 = val; - break; - case 3: - pMat.M14 = val; - break; - } - - break; - case 1: - switch (c) - { - case 0: - pMat.M21 = val; - break; - case 1: - pMat.M22 = val; - break; - case 2: - pMat.M23 = val; - break; - case 3: - pMat.M24 = val; - break; - } - - break; - case 2: - switch (c) - { - case 0: - pMat.M31 = val; - break; - case 1: - pMat.M32 = val; - break; - case 2: - pMat.M33 = val; - break; - case 3: - pMat.M34 = val; - break; - } - - break; - case 3: - switch (c) - { - case 0: - pMat.M41 = val; - break; - case 1: - pMat.M42 = val; - break; - case 2: - pMat.M43 = val; - break; - case 3: - pMat.M44 = val; - break; - } - - break; - } - } - - private static float determinant3x3(Matrix4 pMat) - { - float det = 0; - float diag1 = pMat[0, 0]*pMat[1, 1]*pMat[2, 2]; - float diag2 = pMat[0, 1]*pMat[2, 1]*pMat[2, 0]; - float diag3 = pMat[0, 2]*pMat[1, 0]*pMat[2, 1]; - float diag4 = pMat[2, 0]*pMat[1, 1]*pMat[0, 2]; - float diag5 = pMat[2, 1]*pMat[1, 2]*pMat[0, 0]; - float diag6 = pMat[2, 2]*pMat[1, 0]*pMat[0, 1]; - - det = diag1 + diag2 + diag3 - (diag4 + diag5 + diag6); - return det; - } - - private static void DMassCopy(ref d.Mass src, ref d.Mass dst) - { - dst.c.W = src.c.W; - dst.c.X = src.c.X; - dst.c.Y = src.c.Y; - dst.c.Z = src.c.Z; - dst.mass = src.mass; - dst.I.M00 = src.I.M00; - dst.I.M01 = src.I.M01; - dst.I.M02 = src.I.M02; - dst.I.M10 = src.I.M10; - dst.I.M11 = src.I.M11; - dst.I.M12 = src.I.M12; - dst.I.M20 = src.I.M20; - dst.I.M21 = src.I.M21; - dst.I.M22 = src.I.M22; - } - - public override void SetMaterial(int pMaterial) - { - m_material = pMaterial; - } - - private void CheckMeshAsset() - { - if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero) - { - m_assetFailed = true; - Util.FireAndForget(delegate - { - RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod; - if (assetProvider != null) - assetProvider(_pbs.SculptTexture, MeshAssetReceived); - }); - } - } - - private void MeshAssetReceived(AssetBase asset) - { - if (asset != null && asset.Data != null && asset.Data.Length > 0) - { - if (!_pbs.SculptEntry) - return; - if (_pbs.SculptTexture.ToString() != asset.ID) - return; - - _pbs.SculptData = new byte[asset.Data.Length]; - asset.Data.CopyTo(_pbs.SculptData, 0); -// m_assetFailed = false; - -// m_log.DebugFormat( -// "[ODE PRIM]: Received mesh/sculpt data asset {0} with {1} bytes for {2} at {3} in {4}", -// _pbs.SculptTexture, _pbs.SculptData.Length, Name, _position, _parent_scene.Name); - - m_taintshape = true; - _parent_scene.AddPhysicsActorTaint(this); - } - else - { - m_log.WarnFormat( - "[ODE PRIM]: Could not get mesh/sculpt asset {0} for {1} at {2} in {3}", - _pbs.SculptTexture, Name, _position, _parent_scene.Name); - } - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs deleted file mode 100644 index 8d7d3b3..0000000 --- a/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Text; -using OpenMetaverse; -using OpenSim.Region.Physics.Manager; -using Ode.NET; -using log4net; - -namespace OpenSim.Region.Physics.OdePlugin -{ - /// - /// Processes raycast requests as ODE is in a state to be able to do them. - /// This ensures that it's thread safe and there will be no conflicts. - /// Requests get returned by a different thread then they were requested by. - /// - public class ODERayCastRequestManager - { - /// - /// Pending raycast requests - /// - protected List m_PendingRequests = new List(); - - /// - /// Pending ray requests - /// - protected List m_PendingRayRequests = new List(); - - /// - /// Scene that created this object. - /// - private OdeScene m_scene; - - /// - /// ODE contact array to be filled by the collision testing - /// - d.ContactGeom[] contacts = new d.ContactGeom[5]; - - /// - /// ODE near callback delegate - /// - private d.NearCallback nearCallback; - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private List m_contactResults = new List(); - - - public ODERayCastRequestManager(OdeScene pScene) - { - m_scene = pScene; - nearCallback = near; - - } - - /// - /// Queues a raycast - /// - /// Origin of Ray - /// Ray normal - /// Ray length - /// Return method to send the results - public void QueueRequest(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod) - { - lock (m_PendingRequests) - { - ODERayCastRequest req = new ODERayCastRequest(); - req.callbackMethod = retMethod; - req.length = length; - req.Normal = direction; - req.Origin = position; - - m_PendingRequests.Add(req); - } - } - - /// - /// Queues a raycast - /// - /// Origin of Ray - /// Ray normal - /// Ray length - /// - /// Return method to send the results - public void QueueRequest(Vector3 position, Vector3 direction, float length, int count, RayCallback retMethod) - { - lock (m_PendingRequests) - { - ODERayRequest req = new ODERayRequest(); - req.callbackMethod = retMethod; - req.length = length; - req.Normal = direction; - req.Origin = position; - req.Count = count; - - m_PendingRayRequests.Add(req); - } - } - - /// - /// Process all queued raycast requests - /// - /// Time in MS the raycasts took to process. - public int ProcessQueuedRequests() - { - int time = System.Environment.TickCount; - lock (m_PendingRequests) - { - if (m_PendingRequests.Count > 0) - { - ODERayCastRequest[] reqs = m_PendingRequests.ToArray(); - for (int i = 0; i < reqs.Length; i++) - { - if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast - RayCast(reqs[i]); // if there isn't anyone to send results - } - - m_PendingRequests.Clear(); - } - } - - lock (m_PendingRayRequests) - { - if (m_PendingRayRequests.Count > 0) - { - ODERayRequest[] reqs = m_PendingRayRequests.ToArray(); - for (int i = 0; i < reqs.Length; i++) - { - if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast - RayCast(reqs[i]); // if there isn't anyone to send results - } - - m_PendingRayRequests.Clear(); - } - } - - lock (m_contactResults) - m_contactResults.Clear(); - - return System.Environment.TickCount - time; - } - - /// - /// Method that actually initiates the raycast - /// - /// - private void RayCast(ODERayCastRequest req) - { - // Create the ray - IntPtr ray = d.CreateRay(m_scene.space, req.length); - d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z); - - // Collide test - d.SpaceCollide2(m_scene.space, ray, IntPtr.Zero, nearCallback); - - // Remove Ray - d.GeomDestroy(ray); - - // Define default results - bool hitYN = false; - uint hitConsumerID = 0; - float distance = 999999999999f; - Vector3 closestcontact = new Vector3(99999f, 99999f, 99999f); - Vector3 snormal = Vector3.Zero; - - // Find closest contact and object. - lock (m_contactResults) - { - foreach (ContactResult cResult in m_contactResults) - { - if (Vector3.Distance(req.Origin, cResult.Pos) < Vector3.Distance(req.Origin, closestcontact)) - { - closestcontact = cResult.Pos; - hitConsumerID = cResult.ConsumerID; - distance = cResult.Depth; - hitYN = true; - snormal = cResult.Normal; - } - } - - m_contactResults.Clear(); - } - - // Return results - if (req.callbackMethod != null) - req.callbackMethod(hitYN, closestcontact, hitConsumerID, distance, snormal); - } - - /// - /// Method that actually initiates the raycast - /// - /// - private void RayCast(ODERayRequest req) - { - // Create the ray - IntPtr ray = d.CreateRay(m_scene.space, req.length); - d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z); - - // Collide test - d.SpaceCollide2(m_scene.space, ray, IntPtr.Zero, nearCallback); - - // Remove Ray - d.GeomDestroy(ray); - - // Find closest contact and object. - lock (m_contactResults) - { - // Return results - if (req.callbackMethod != null) - req.callbackMethod(m_contactResults); - } - } - - // This is the standard Near. Uses space AABBs to speed up detection. - private void near(IntPtr space, IntPtr g1, IntPtr g2) - { - - //Don't test against heightfield Geom, or you'll be sorry! - - /* - terminate called after throwing an instance of 'std::bad_alloc' - what(): std::bad_alloc - Stacktrace: - - at (wrapper managed-to-native) Ode.NET.d.Collide (intptr,intptr,int,Ode.NET.d/ContactGeom[],int) <0x00004> - at (wrapper managed-to-native) Ode.NET.d.Collide (intptr,intptr,int,Ode.NET.d/ContactGeom[],int) <0xffffffff> - at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.near (intptr,intptr,intptr) <0x00280> - at (wrapper native-to-managed) OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.near (intptr,intptr,intptr) <0xfff - fffff> - at (wrapper managed-to-native) Ode.NET.d.SpaceCollide2 (intptr,intptr,intptr,Ode.NET.d/NearCallback) <0x00004> - at (wrapper managed-to-native) Ode.NET.d.SpaceCollide2 (intptr,intptr,intptr,Ode.NET.d/NearCallback) <0xffffffff> - at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.RayCast (OpenSim.Region.Physics.OdePlugin.ODERayCastRequest) < - 0x00114> - at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.ProcessQueuedRequests () <0x000eb> - at OpenSim.Region.Physics.OdePlugin.OdeScene.Simulate (single) <0x017e6> - at OpenSim.Region.Framework.Scenes.SceneGraph.UpdatePhysics (double) <0x00042> - at OpenSim.Region.Framework.Scenes.Scene.Update () <0x0039e> - at OpenSim.Region.Framework.Scenes.Scene.Heartbeat (object) <0x00019> - at (wrapper runtime-invoke) object.runtime_invoke_void__this___object (object,intptr,intptr,intptr) <0xffffffff> - - Native stacktrace: - - mono [0x80d2a42] - [0xb7f5840c] - /lib/i686/cmov/libc.so.6(abort+0x188) [0xb7d1a018] - /usr/lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x158) [0xb45fc988] - /usr/lib/libstdc++.so.6 [0xb45fa865] - /usr/lib/libstdc++.so.6 [0xb45fa8a2] - /usr/lib/libstdc++.so.6 [0xb45fa9da] - /usr/lib/libstdc++.so.6(_Znwj+0x83) [0xb45fb033] - /usr/lib/libstdc++.so.6(_Znaj+0x1d) [0xb45fb11d] - libode.so(_ZN13dxHeightfield23dCollideHeightfieldZoneEiiiiP6dxGeomiiP12dContactGeomi+0xd04) [0xb46678e4] - libode.so(_Z19dCollideHeightfieldP6dxGeomS0_iP12dContactGeomi+0x54b) [0xb466832b] - libode.so(dCollide+0x102) [0xb46571b2] - [0x95cfdec9] - [0x8ea07fe1] - [0xab260146] - libode.so [0xb465a5c4] - libode.so(_ZN11dxHashSpace8collide2EPvP6dxGeomPFvS0_S2_S2_E+0x75) [0xb465bcf5] - libode.so(dSpaceCollide2+0x177) [0xb465ac67] - [0x95cf978e] - [0x8ea07945] - [0x95cf2bbc] - [0xab2787e7] - [0xab419fb3] - [0xab416657] - [0xab415bda] - [0xb609b08e] - mono(mono_runtime_delegate_invoke+0x34) [0x8192534] - mono [0x81a2f0f] - mono [0x81d28b6] - mono [0x81ea2c6] - /lib/i686/cmov/libpthread.so.0 [0xb7e744c0] - /lib/i686/cmov/libc.so.6(clone+0x5e) [0xb7dcd6de] - */ - - // Exclude heightfield geom - - if (g1 == IntPtr.Zero || g2 == IntPtr.Zero) - return; - if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass || d.GeomGetClass(g2) == d.GeomClassID.HeightfieldClass) - return; - - // Raytest against AABBs of spaces first, then dig into the spaces it hits for actual geoms. - if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2)) - { - if (g1 == IntPtr.Zero || g2 == IntPtr.Zero) - return; - - // Separating static prim geometry spaces. - // We'll be calling near recursivly if one - // of them is a space to find all of the - // contact points in the space - try - { - d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback); - } - catch (AccessViolationException) - { - m_log.Warn("[PHYSICS]: Unable to collide test a space"); - return; - } - //Colliding a space or a geom with a space or a geom. so drill down - - //Collide all geoms in each space.. - //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback); - //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback); - return; - } - - if (g1 == IntPtr.Zero || g2 == IntPtr.Zero) - return; - - int count = 0; - try - { - - if (g1 == g2) - return; // Can't collide with yourself - - lock (contacts) - { - count = d.Collide(g1, g2, contacts.GetLength(0), contacts, d.ContactGeom.SizeOf); - } - } - catch (SEHException) - { - m_log.Error("[PHYSICS]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim."); - } - catch (Exception e) - { - m_log.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e.Message); - return; - } - - PhysicsActor p1 = null; - PhysicsActor p2 = null; - - if (g1 != IntPtr.Zero) - m_scene.actor_name_map.TryGetValue(g1, out p1); - - if (g2 != IntPtr.Zero) - m_scene.actor_name_map.TryGetValue(g1, out p2); - - // Loop over contacts, build results. - for (int i = 0; i < count; i++) - { - if (p1 != null) - { - if (p1 is OdePrim) - { - ContactResult collisionresult = new ContactResult(); - - collisionresult.ConsumerID = p1.LocalID; - collisionresult.Pos = new Vector3(contacts[i].pos.X, contacts[i].pos.Y, contacts[i].pos.Z); - collisionresult.Depth = contacts[i].depth; - collisionresult.Normal = new Vector3(contacts[i].normal.X, contacts[i].normal.Y, - contacts[i].normal.Z); - lock (m_contactResults) - m_contactResults.Add(collisionresult); - } - } - - if (p2 != null) - { - if (p2 is OdePrim) - { - ContactResult collisionresult = new ContactResult(); - - collisionresult.ConsumerID = p2.LocalID; - collisionresult.Pos = new Vector3(contacts[i].pos.X, contacts[i].pos.Y, contacts[i].pos.Z); - collisionresult.Depth = contacts[i].depth; - collisionresult.Normal = new Vector3(contacts[i].normal.X, contacts[i].normal.Y, - contacts[i].normal.Z); - - lock (m_contactResults) - m_contactResults.Add(collisionresult); - } - } - } - } - - /// - /// Dereference the creator scene so that it can be garbage collected if needed. - /// - internal void Dispose() - { - m_scene = null; - } - } - - public struct ODERayCastRequest - { - public Vector3 Origin; - public Vector3 Normal; - public float length; - public RaycastCallback callbackMethod; - } - - public struct ODERayRequest - { - public Vector3 Origin; - public Vector3 Normal; - public int Count; - public float length; - public RayCallback callbackMethod; - } -} \ No newline at end of file diff --git a/OpenSim/Region/Physics/OdePlugin/OdePhysicsJoint.cs b/OpenSim/Region/Physics/OdePlugin/OdePhysicsJoint.cs deleted file mode 100644 index b4a3c48..0000000 --- a/OpenSim/Region/Physics/OdePlugin/OdePhysicsJoint.cs +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using OpenMetaverse; -using Ode.NET; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; -using OpenSim.Region.Physics.OdePlugin; - -namespace OpenSim.Region.Physics.OdePlugin -{ - class OdePhysicsJoint : PhysicsJoint - { - public override bool IsInPhysicsEngine - { - get - { - return (jointID != IntPtr.Zero); - } - } - public IntPtr jointID; - } -} diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs deleted file mode 100644 index 478dd95..0000000 --- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Threading; -using System.IO; -using System.Diagnostics; -using log4net; -using Nini.Config; -using Ode.NET; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.OdePlugin -{ - /// - /// ODE plugin - /// - public class OdePlugin : IPhysicsPlugin - { - private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - private OdeScene m_scene; - - public bool Init() - { - return true; - } - - public PhysicsScene GetScene(String sceneIdentifier) - { - if (m_scene == null) - { - // We do this so that OpenSimulator on Windows loads the correct native ODE library depending on whether - // it's running as a 32-bit process or a 64-bit one. By invoking LoadLibary here, later DLLImports - // will find it already loaded later on. - // - // This isn't necessary for other platforms (e.g. Mac OSX and Linux) since the DLL used can be - // controlled in Ode.NET.dll.config - if (Util.IsWindows()) - Util.LoadArchSpecificWindowsDll("ode.dll"); - - // Initializing ODE only when a scene is created allows alternative ODE plugins to co-habit (according to - // http://opensimulator.org/mantis/view.php?id=2750). - d.InitODE(); - - m_scene = new OdeScene(sceneIdentifier); - } - - return m_scene; - } - - public string GetName() - { - return ("OpenDynamicsEngine"); - } - - public void Dispose() - { - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs deleted file mode 100644 index d53bd90..0000000 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ /dev/null @@ -1,4323 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -//#define USE_DRAWSTUFF -//#define SPAM - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Threading; -using log4net; -using Nini.Config; -using Ode.NET; -using OpenMetaverse; -#if USE_DRAWSTUFF -using Drawstuff.NET; -#endif -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.OdePlugin -{ - public enum StatusIndicators : int - { - Generic = 0, - Start = 1, - End = 2 - } - -// public struct sCollisionData -// { -// public uint ColliderLocalId; -// public uint CollidedWithLocalId; -// public int NumberOfCollisions; -// public int CollisionType; -// public int StatusIndicator; -// public int lastframe; -// } - - [Flags] - public enum CollisionCategories : int - { - Disabled = 0, - Geom = 0x00000001, - Body = 0x00000002, - Space = 0x00000004, - Character = 0x00000008, - Land = 0x00000010, - Water = 0x00000020, - Wind = 0x00000040, - Sensor = 0x00000080, - Selected = 0x00000100 - } - - /// - /// Material type for a primitive - /// - public enum Material : int - { - /// - Stone = 0, - /// - Metal = 1, - /// - Glass = 2, - /// - Wood = 3, - /// - Flesh = 4, - /// - Plastic = 5, - /// - Rubber = 6 - } - - public class OdeScene : PhysicsScene - { - private readonly ILog m_log; - // private Dictionary m_storedCollisions = new Dictionary(); - - /// - /// Provide a sync object so that only one thread calls d.Collide() at a time across all OdeScene instances. - /// - /// - /// With ODE as of r1755 (though also tested on r1860), only one thread can call d.Collide() at a - /// time, even where physics objects are in entirely different ODE worlds. This is because generating contacts - /// uses a static cache at the ODE level. - /// - /// Without locking, simulators running multiple regions will eventually crash with a native stack trace similar - /// to - /// - /// mono() [0x489171] - /// mono() [0x4d154f] - /// /lib/x86_64-linux-gnu/libpthread.so.0(+0xfc60) [0x7f6ded592c60] - /// .../opensim/bin/libode-x86_64.so(_ZN6Opcode11OBBCollider8_CollideEPKNS_14AABBNoLeafNodeE+0xd7a) [0x7f6dd822628a] - /// - /// ODE provides an experimental option to cache in thread local storage but compiling ODE with this option - /// causes OpenSimulator to immediately crash with a native stack trace similar to - /// - /// mono() [0x489171] - /// mono() [0x4d154f] - /// /lib/x86_64-linux-gnu/libpthread.so.0(+0xfc60) [0x7f03c9849c60] - /// .../opensim/bin/libode-x86_64.so(_Z12dCollideCCTLP6dxGeomS0_iP12dContactGeomi+0x92) [0x7f03b44bcf82] - /// - internal static Object UniversalColliderSyncObject = new Object(); - - /// - /// Is stats collecting enabled for this ODE scene? - /// - public bool CollectStats { get; set; } - - /// - /// Statistics for this scene. - /// - private Dictionary m_stats = new Dictionary(); - - /// - /// Stat name for total number of avatars in this ODE scene. - /// - public const string ODETotalAvatarsStatName = "ODETotalAvatars"; - - /// - /// Stat name for total number of prims in this ODE scene. - /// - public const string ODETotalPrimsStatName = "ODETotalPrims"; - - /// - /// Stat name for total number of prims with active physics in this ODE scene. - /// - public const string ODEActivePrimsStatName = "ODEActivePrims"; - - /// - /// Stat name for the total time spent in ODE frame processing. - /// - /// - /// A sanity check for the main scene loop physics time. - /// - public const string ODETotalFrameMsStatName = "ODETotalFrameMS"; - - /// - /// Stat name for time spent processing avatar taints per frame - /// - public const string ODEAvatarTaintMsStatName = "ODEAvatarTaintFrameMS"; - - /// - /// Stat name for time spent processing prim taints per frame - /// - public const string ODEPrimTaintMsStatName = "ODEPrimTaintFrameMS"; - - /// - /// Stat name for time spent calculating avatar forces per frame. - /// - public const string ODEAvatarForcesFrameMsStatName = "ODEAvatarForcesFrameMS"; - - /// - /// Stat name for time spent calculating prim forces per frame - /// - public const string ODEPrimForcesFrameMsStatName = "ODEPrimForcesFrameMS"; - - /// - /// Stat name for time spent fulfilling raycasting requests per frame - /// - public const string ODERaycastingFrameMsStatName = "ODERaycastingFrameMS"; - - /// - /// Stat name for time spent in native code that actually steps through the simulation. - /// - public const string ODENativeStepFrameMsStatName = "ODENativeStepFrameMS"; - - /// - /// Stat name for the number of milliseconds that ODE spends in native space collision code. - /// - public const string ODENativeSpaceCollisionFrameMsStatName = "ODENativeSpaceCollisionFrameMS"; - - /// - /// Stat name for milliseconds that ODE spends in native geom collision code. - /// - public const string ODENativeGeomCollisionFrameMsStatName = "ODENativeGeomCollisionFrameMS"; - - /// - /// Time spent in collision processing that is not spent in native space or geom collision code. - /// - public const string ODEOtherCollisionFrameMsStatName = "ODEOtherCollisionFrameMS"; - - /// - /// Stat name for time spent notifying listeners of collisions - /// - public const string ODECollisionNotificationFrameMsStatName = "ODECollisionNotificationFrameMS"; - - /// - /// Stat name for milliseconds spent updating avatar position and velocity - /// - public const string ODEAvatarUpdateFrameMsStatName = "ODEAvatarUpdateFrameMS"; - - /// - /// Stat name for the milliseconds spent updating prim position and velocity - /// - public const string ODEPrimUpdateFrameMsStatName = "ODEPrimUpdateFrameMS"; - - /// - /// Stat name for avatar collisions with another entity. - /// - public const string ODEAvatarContactsStatsName = "ODEAvatarContacts"; - - /// - /// Stat name for prim collisions with another entity. - /// - public const string ODEPrimContactsStatName = "ODEPrimContacts"; - - /// - /// Used to hold tick numbers for stat collection purposes. - /// - private int m_nativeCollisionStartTick; - - /// - /// A messy way to tell if we need to avoid adding a collision time because this was already done in the callback. - /// - private bool m_inCollisionTiming; - - /// - /// A temporary holder for the number of avatar collisions in a frame, so we can work out how many object - /// collisions occured using the _perloopcontact if stats collection is enabled. - /// - private int m_tempAvatarCollisionsThisFrame; - - /// - /// Used in calculating physics frame time dilation - /// - private int tickCountFrameRun; - - /// - /// Used in calculating physics frame time dilation - /// - private int latertickcount; - - private Random fluidRandomizer = new Random(Environment.TickCount); - - private const uint m_regionWidth = Constants.RegionSize; - private const uint m_regionHeight = Constants.RegionSize; - - private float ODE_STEPSIZE = 0.0178f; - private float metersInSpace = 29.9f; - private float m_timeDilation = 1.0f; - - public float gravityx = 0f; - public float gravityy = 0f; - public float gravityz = -9.8f; - - public float AvatarTerminalVelocity { get; set; } - - private float contactsurfacelayer = 0.001f; - - private int worldHashspaceLow = -4; - private int worldHashspaceHigh = 128; - - private int smallHashspaceLow = -4; - private int smallHashspaceHigh = 66; - - private float waterlevel = 0f; - private int framecount = 0; - //private int m_returncollisions = 10; - - private readonly IntPtr contactgroup; - - internal IntPtr WaterGeom; - - private float nmTerrainContactFriction = 255.0f; - private float nmTerrainContactBounce = 0.1f; - private float nmTerrainContactERP = 0.1025f; - - private float mTerrainContactFriction = 75f; - private float mTerrainContactBounce = 0.1f; - private float mTerrainContactERP = 0.05025f; - - private float nmAvatarObjectContactFriction = 250f; - private float nmAvatarObjectContactBounce = 0.1f; - - private float mAvatarObjectContactFriction = 75f; - private float mAvatarObjectContactBounce = 0.1f; - - private float avPIDD = 3200f; - private float avPIDP = 1400f; - private float avCapRadius = 0.37f; - private float avStandupTensor = 2000000f; - - /// - /// true = old compatibility mode with leaning capsule; false = new corrected mode - /// - /// - /// Even when set to false, the capsule still tilts but this is done in a different way. - /// - public bool IsAvCapsuleTilted { get; private set; } - - private float avDensity = 80f; -// private float avHeightFudgeFactor = 0.52f; - private float avMovementDivisorWalk = 1.3f; - private float avMovementDivisorRun = 0.8f; - private float minimumGroundFlightOffset = 3f; - public float maximumMassObject = 10000.01f; - - public bool meshSculptedPrim = true; - public bool forceSimplePrimMeshing = false; - - public float meshSculptLOD = 32; - public float MeshSculptphysicalLOD = 16; - - public float geomDefaultDensity = 10.000006836f; - - public int geomContactPointsStartthrottle = 3; - public int geomUpdatesPerThrottledUpdate = 15; - private const int avatarExpectedContacts = 3; - - public float bodyPIDD = 35f; - public float bodyPIDG = 25; - - public int geomCrossingFailuresBeforeOutofbounds = 5; - - public float bodyMotorJointMaxforceTensor = 2; - - public int bodyFramesAutoDisable = 20; - - private float[] _watermap; - private bool m_filterCollisions = true; - - private d.NearCallback nearCallback; - public d.TriCallback triCallback; - public d.TriArrayCallback triArrayCallback; - - /// - /// Avatars in the physics scene. - /// - private readonly HashSet _characters = new HashSet(); - - /// - /// Prims in the physics scene. - /// - private readonly HashSet _prims = new HashSet(); - - /// - /// Prims in the physics scene that are subject to physics, not just collisions. - /// - private readonly HashSet _activeprims = new HashSet(); - - /// - /// Prims that the simulator has created/deleted/updated and so need updating in ODE. - /// - private readonly HashSet _taintedPrims = new HashSet(); - - /// - /// Record a character that has taints to be processed. - /// - private readonly HashSet _taintedActors = new HashSet(); - - /// - /// Keep record of contacts in the physics loop so that we can remove duplicates. - /// - private readonly List _perloopContact = new List(); - - /// - /// A dictionary of actors that should receive collision events. - /// - private readonly Dictionary m_collisionEventActors = new Dictionary(); - - /// - /// A dictionary of collision event changes that are waiting to be processed. - /// - private readonly Dictionary m_collisionEventActorsChanges = new Dictionary(); - - /// - /// Maps a unique geometry id (a memory location) to a physics actor name. - /// - /// - /// Only actors participating in collisions have geometries. This has to be maintained separately from - /// actor_name_map because terrain and water currently don't conceptually have a physics actor of their own - /// apart from the singleton PANull - /// - public Dictionary geom_name_map = new Dictionary(); - - /// - /// Maps a unique geometry id (a memory location) to a physics actor. - /// - /// - /// Only actors participating in collisions have geometries. - /// - public Dictionary actor_name_map = new Dictionary(); - - /// - /// Defects list to remove characters that no longer have finite positions due to some other bug. - /// - /// - /// Used repeatedly in Simulate() but initialized once here. - /// - private readonly List defects = new List(); - - private bool m_NINJA_physics_joints_enabled = false; - //private Dictionary jointpart_name_map = new Dictionary(); - private readonly Dictionary> joints_connecting_actor = new Dictionary>(); - private d.ContactGeom[] contacts; - - /// - /// Lock only briefly. accessed by external code (to request new joints) and by OdeScene.Simulate() to move those joints into pending/active - /// - private readonly List requestedJointsToBeCreated = new List(); - - /// - /// can lock for longer. accessed only by OdeScene. - /// - private readonly List pendingJoints = new List(); - - /// - /// can lock for longer. accessed only by OdeScene. - /// - private readonly List activeJoints = new List(); - - /// - /// lock only briefly. accessed by external code (to request deletion of joints) and by OdeScene.Simulate() to move those joints out of pending/active - /// - private readonly List requestedJointsToBeDeleted = new List(); - - private Object externalJointRequestsLock = new Object(); - private readonly Dictionary SOPName_to_activeJoint = new Dictionary(); - private readonly Dictionary SOPName_to_pendingJoint = new Dictionary(); - private readonly DoubleDictionary RegionTerrain = new DoubleDictionary(); - private readonly Dictionary TerrainHeightFieldHeights = new Dictionary(); - - private d.Contact contact; - private d.Contact TerrainContact; - private d.Contact AvatarMovementprimContact; - private d.Contact AvatarMovementTerrainContact; - private d.Contact WaterContact; - private d.Contact[,] m_materialContacts; - -//Ckrinke: Comment out until used. We declare it, initialize it, but do not use it -//Ckrinke private int m_randomizeWater = 200; - private int m_physicsiterations = 10; - private const float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag - private readonly PhysicsActor PANull = new NullPhysicsActor(); -// private float step_time = 0.0f; -//Ckrinke: Comment out until used. We declare it, initialize it, but do not use it -//Ckrinke private int ms = 0; - public IntPtr world; - //private bool returncollisions = false; - // private uint obj1LocalID = 0; - private uint obj2LocalID = 0; - //private int ctype = 0; - private OdeCharacter cc1; - private OdePrim cp1; - private OdeCharacter cc2; - private OdePrim cp2; - private int p1ExpectedPoints = 0; - private int p2ExpectedPoints = 0; - //private int cStartStop = 0; - //private string cDictKey = ""; - - public IntPtr space; - - //private IntPtr tmpSpace; - // split static geometry collision handling into spaces of 30 meters - public IntPtr[,] staticPrimspace; - - /// - /// Used to lock the entire physics scene. Locked during the main part of Simulate() - /// - internal Object OdeLock = new Object(); - - private bool _worldInitialized = false; - - public IMesher mesher; - - private IConfigSource m_config; - - public bool physics_logging = false; - public int physics_logging_interval = 0; - public bool physics_logging_append_existing_logfile = false; - - private bool avplanted = false; - private bool av_av_collisions_off = false; - - public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f); - public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); - - // TODO: unused: private uint heightmapWidth = m_regionWidth + 1; - // TODO: unused: private uint heightmapHeight = m_regionHeight + 1; - // TODO: unused: private uint heightmapWidthSamples; - // TODO: unused: private uint heightmapHeightSamples; - - private volatile int m_global_contactcount = 0; - - private Vector3 m_worldOffset = Vector3.Zero; - public Vector2 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize); - private PhysicsScene m_parentScene = null; - - private ODERayCastRequestManager m_rayCastManager; - - /// - /// Initiailizes the scene - /// Sets many properties that ODE requires to be stable - /// These settings need to be tweaked 'exactly' right or weird stuff happens. - /// - /// Name of the scene. Useful in debug messages. - public OdeScene(string name) - { - m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString() + "." + name); - - Name = name; - - nearCallback = near; - triCallback = TriCallback; - triArrayCallback = TriArrayCallback; - m_rayCastManager = new ODERayCastRequestManager(this); - - // Create the world and the first space - world = d.WorldCreate(); - space = d.HashSpaceCreate(IntPtr.Zero); - - contactgroup = d.JointGroupCreate(0); - - d.WorldSetAutoDisableFlag(world, false); - - #if USE_DRAWSTUFF - Thread viewthread = new Thread(new ParameterizedThreadStart(startvisualization)); - viewthread.Start(); - #endif - - _watermap = new float[258 * 258]; - - // Zero out the prim spaces array (we split our space into smaller spaces so - // we can hit test less. - } - -#if USE_DRAWSTUFF - public void startvisualization(object o) - { - ds.Functions fn; - fn.version = ds.VERSION; - fn.start = new ds.CallbackFunction(start); - fn.step = new ds.CallbackFunction(step); - fn.command = new ds.CallbackFunction(command); - fn.stop = null; - fn.path_to_textures = "./textures"; - string[] args = new string[0]; - ds.SimulationLoop(args.Length, args, 352, 288, ref fn); - } -#endif - - // Initialize the mesh plugin - public override void Initialise(IMesher meshmerizer, IConfigSource config) - { - InitializeExtraStats(); - - mesher = meshmerizer; - m_config = config; - // Defaults - - if (Environment.OSVersion.Platform == PlatformID.Unix) - { - avPIDD = 3200.0f; - avPIDP = 1400.0f; - avStandupTensor = 2000000f; - } - else - { - avPIDD = 2200.0f; - avPIDP = 900.0f; - avStandupTensor = 550000f; - } - - int contactsPerCollision = 80; - - if (m_config != null) - { - IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"]; - if (physicsconfig != null) - { - CollectStats = physicsconfig.GetBoolean("collect_stats", false); - - gravityx = physicsconfig.GetFloat("world_gravityx", 0f); - gravityy = physicsconfig.GetFloat("world_gravityy", 0f); - gravityz = physicsconfig.GetFloat("world_gravityz", -9.8f); - - float avatarTerminalVelocity = physicsconfig.GetFloat("avatar_terminal_velocity", 54f); - AvatarTerminalVelocity = Util.Clamp(avatarTerminalVelocity, 0, 255f); - if (AvatarTerminalVelocity != avatarTerminalVelocity) - { - m_log.WarnFormat( - "[ODE SCENE]: avatar_terminal_velocity of {0} is invalid. Clamping to {1}", - avatarTerminalVelocity, AvatarTerminalVelocity); - } - - worldHashspaceLow = physicsconfig.GetInt("world_hashspace_size_low", -4); - worldHashspaceHigh = physicsconfig.GetInt("world_hashspace_size_high", 128); - - metersInSpace = physicsconfig.GetFloat("meters_in_small_space", 29.9f); - smallHashspaceLow = physicsconfig.GetInt("small_hashspace_size_low", -4); - smallHashspaceHigh = physicsconfig.GetInt("small_hashspace_size_high", 66); - - contactsurfacelayer = physicsconfig.GetFloat("world_contact_surface_layer", 0.001f); - - nmTerrainContactFriction = physicsconfig.GetFloat("nm_terraincontact_friction", 255.0f); - nmTerrainContactBounce = physicsconfig.GetFloat("nm_terraincontact_bounce", 0.1f); - nmTerrainContactERP = physicsconfig.GetFloat("nm_terraincontact_erp", 0.1025f); - - mTerrainContactFriction = physicsconfig.GetFloat("m_terraincontact_friction", 75f); - mTerrainContactBounce = physicsconfig.GetFloat("m_terraincontact_bounce", 0.05f); - mTerrainContactERP = physicsconfig.GetFloat("m_terraincontact_erp", 0.05025f); - - nmAvatarObjectContactFriction = physicsconfig.GetFloat("objectcontact_friction", 250f); - nmAvatarObjectContactBounce = physicsconfig.GetFloat("objectcontact_bounce", 0.2f); - - mAvatarObjectContactFriction = physicsconfig.GetFloat("m_avatarobjectcontact_friction", 75f); - mAvatarObjectContactBounce = physicsconfig.GetFloat("m_avatarobjectcontact_bounce", 0.1f); - - ODE_STEPSIZE = physicsconfig.GetFloat("world_stepsize", ODE_STEPSIZE); - m_physicsiterations = physicsconfig.GetInt("world_internal_steps_without_collisions", 10); - - avDensity = physicsconfig.GetFloat("av_density", 80f); -// avHeightFudgeFactor = physicsconfig.GetFloat("av_height_fudge_factor", 0.52f); - avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f); - avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f); - avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f); - avplanted = physicsconfig.GetBoolean("av_planted", false); - av_av_collisions_off = physicsconfig.GetBoolean("av_av_collisions_off", false); - - IsAvCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false); - - contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80); - - geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 5); - geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15); - geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5); - - geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", 10.000006836f); - bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", 20); - - bodyPIDD = physicsconfig.GetFloat("body_pid_derivative", 35f); - bodyPIDG = physicsconfig.GetFloat("body_pid_gain", 25f); - - forceSimplePrimMeshing = physicsconfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing); - meshSculptedPrim = physicsconfig.GetBoolean("mesh_sculpted_prim", true); - meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f); - MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f); - m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false); - - - - if (Environment.OSVersion.Platform == PlatformID.Unix) - { - avPIDD = physicsconfig.GetFloat("av_pid_derivative_linux", 2200.0f); - avPIDP = physicsconfig.GetFloat("av_pid_proportional_linux", 900.0f); - avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor_linux", 550000f); - bodyMotorJointMaxforceTensor = physicsconfig.GetFloat("body_motor_joint_maxforce_tensor_linux", 5f); - } - else - { - avPIDD = physicsconfig.GetFloat("av_pid_derivative_win", 2200.0f); - avPIDP = physicsconfig.GetFloat("av_pid_proportional_win", 900.0f); - avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor_win", 550000f); - bodyMotorJointMaxforceTensor = physicsconfig.GetFloat("body_motor_joint_maxforce_tensor_win", 5f); - } - - physics_logging = physicsconfig.GetBoolean("physics_logging", false); - physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0); - physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false); - - m_NINJA_physics_joints_enabled = physicsconfig.GetBoolean("use_NINJA_physics_joints", false); - minimumGroundFlightOffset = physicsconfig.GetFloat("minimum_ground_flight_offset", 3f); - maximumMassObject = physicsconfig.GetFloat("maximum_mass_object", 10000.01f); - } - } - - contacts = new d.ContactGeom[contactsPerCollision]; - - staticPrimspace = new IntPtr[(int)(300 / metersInSpace), (int)(300 / metersInSpace)]; - - // Centeral contact friction and bounce - // ckrinke 11/10/08 Enabling soft_erp but not soft_cfm until I figure out why - // an avatar falls through in Z but not in X or Y when walking on a prim. - contact.surface.mode |= d.ContactFlags.SoftERP; - contact.surface.mu = nmAvatarObjectContactFriction; - contact.surface.bounce = nmAvatarObjectContactBounce; - contact.surface.soft_cfm = 0.010f; - contact.surface.soft_erp = 0.010f; - - // Terrain contact friction and Bounce - // This is the *non* moving version. Use this when an avatar - // isn't moving to keep it in place better - TerrainContact.surface.mode |= d.ContactFlags.SoftERP; - TerrainContact.surface.mu = nmTerrainContactFriction; - TerrainContact.surface.bounce = nmTerrainContactBounce; - TerrainContact.surface.soft_erp = nmTerrainContactERP; - - WaterContact.surface.mode |= (d.ContactFlags.SoftERP | d.ContactFlags.SoftCFM); - WaterContact.surface.mu = 0f; // No friction - WaterContact.surface.bounce = 0.0f; // No bounce - WaterContact.surface.soft_cfm = 0.010f; - WaterContact.surface.soft_erp = 0.010f; - - // Prim contact friction and bounce - // THis is the *non* moving version of friction and bounce - // Use this when an avatar comes in contact with a prim - // and is moving - AvatarMovementprimContact.surface.mu = mAvatarObjectContactFriction; - AvatarMovementprimContact.surface.bounce = mAvatarObjectContactBounce; - - // Terrain contact friction bounce and various error correcting calculations - // Use this when an avatar is in contact with the terrain and moving. - AvatarMovementTerrainContact.surface.mode |= d.ContactFlags.SoftERP; - AvatarMovementTerrainContact.surface.mu = mTerrainContactFriction; - AvatarMovementTerrainContact.surface.bounce = mTerrainContactBounce; - AvatarMovementTerrainContact.surface.soft_erp = mTerrainContactERP; - - /* - - Stone = 0, - /// - Metal = 1, - /// - Glass = 2, - /// - Wood = 3, - /// - Flesh = 4, - /// - Plastic = 5, - /// - Rubber = 6 - */ - - m_materialContacts = new d.Contact[7,2]; - - m_materialContacts[(int)Material.Stone, 0] = new d.Contact(); - m_materialContacts[(int)Material.Stone, 0].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Stone, 0].surface.mu = nmAvatarObjectContactFriction; - m_materialContacts[(int)Material.Stone, 0].surface.bounce = nmAvatarObjectContactBounce; - m_materialContacts[(int)Material.Stone, 0].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Stone, 0].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Stone, 1] = new d.Contact(); - m_materialContacts[(int)Material.Stone, 1].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Stone, 1].surface.mu = mAvatarObjectContactFriction; - m_materialContacts[(int)Material.Stone, 1].surface.bounce = mAvatarObjectContactBounce; - m_materialContacts[(int)Material.Stone, 1].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Stone, 1].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Metal, 0] = new d.Contact(); - m_materialContacts[(int)Material.Metal, 0].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Metal, 0].surface.mu = nmAvatarObjectContactFriction; - m_materialContacts[(int)Material.Metal, 0].surface.bounce = nmAvatarObjectContactBounce; - m_materialContacts[(int)Material.Metal, 0].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Metal, 0].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Metal, 1] = new d.Contact(); - m_materialContacts[(int)Material.Metal, 1].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Metal, 1].surface.mu = mAvatarObjectContactFriction; - m_materialContacts[(int)Material.Metal, 1].surface.bounce = mAvatarObjectContactBounce; - m_materialContacts[(int)Material.Metal, 1].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Metal, 1].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Glass, 0] = new d.Contact(); - m_materialContacts[(int)Material.Glass, 0].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Glass, 0].surface.mu = 1f; - m_materialContacts[(int)Material.Glass, 0].surface.bounce = 0.5f; - m_materialContacts[(int)Material.Glass, 0].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Glass, 0].surface.soft_erp = 0.010f; - - /* - private float nmAvatarObjectContactFriction = 250f; - private float nmAvatarObjectContactBounce = 0.1f; - - private float mAvatarObjectContactFriction = 75f; - private float mAvatarObjectContactBounce = 0.1f; - */ - m_materialContacts[(int)Material.Glass, 1] = new d.Contact(); - m_materialContacts[(int)Material.Glass, 1].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Glass, 1].surface.mu = 1f; - m_materialContacts[(int)Material.Glass, 1].surface.bounce = 0.5f; - m_materialContacts[(int)Material.Glass, 1].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Glass, 1].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Wood, 0] = new d.Contact(); - m_materialContacts[(int)Material.Wood, 0].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Wood, 0].surface.mu = nmAvatarObjectContactFriction; - m_materialContacts[(int)Material.Wood, 0].surface.bounce = nmAvatarObjectContactBounce; - m_materialContacts[(int)Material.Wood, 0].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Wood, 0].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Wood, 1] = new d.Contact(); - m_materialContacts[(int)Material.Wood, 1].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Wood, 1].surface.mu = mAvatarObjectContactFriction; - m_materialContacts[(int)Material.Wood, 1].surface.bounce = mAvatarObjectContactBounce; - m_materialContacts[(int)Material.Wood, 1].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Wood, 1].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Flesh, 0] = new d.Contact(); - m_materialContacts[(int)Material.Flesh, 0].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Flesh, 0].surface.mu = nmAvatarObjectContactFriction; - m_materialContacts[(int)Material.Flesh, 0].surface.bounce = nmAvatarObjectContactBounce; - m_materialContacts[(int)Material.Flesh, 0].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Flesh, 0].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Flesh, 1] = new d.Contact(); - m_materialContacts[(int)Material.Flesh, 1].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Flesh, 1].surface.mu = mAvatarObjectContactFriction; - m_materialContacts[(int)Material.Flesh, 1].surface.bounce = mAvatarObjectContactBounce; - m_materialContacts[(int)Material.Flesh, 1].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Flesh, 1].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Plastic, 0] = new d.Contact(); - m_materialContacts[(int)Material.Plastic, 0].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Plastic, 0].surface.mu = nmAvatarObjectContactFriction; - m_materialContacts[(int)Material.Plastic, 0].surface.bounce = nmAvatarObjectContactBounce; - m_materialContacts[(int)Material.Plastic, 0].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Plastic, 0].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Plastic, 1] = new d.Contact(); - m_materialContacts[(int)Material.Plastic, 1].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Plastic, 1].surface.mu = mAvatarObjectContactFriction; - m_materialContacts[(int)Material.Plastic, 1].surface.bounce = mAvatarObjectContactBounce; - m_materialContacts[(int)Material.Plastic, 1].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Plastic, 1].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Rubber, 0] = new d.Contact(); - m_materialContacts[(int)Material.Rubber, 0].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Rubber, 0].surface.mu = nmAvatarObjectContactFriction; - m_materialContacts[(int)Material.Rubber, 0].surface.bounce = nmAvatarObjectContactBounce; - m_materialContacts[(int)Material.Rubber, 0].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Rubber, 0].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Rubber, 1] = new d.Contact(); - m_materialContacts[(int)Material.Rubber, 1].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Rubber, 1].surface.mu = mAvatarObjectContactFriction; - m_materialContacts[(int)Material.Rubber, 1].surface.bounce = mAvatarObjectContactBounce; - m_materialContacts[(int)Material.Rubber, 1].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Rubber, 1].surface.soft_erp = 0.010f; - - d.HashSpaceSetLevels(space, worldHashspaceLow, worldHashspaceHigh); - - // Set the gravity,, don't disable things automatically (we set it explicitly on some things) - - d.WorldSetGravity(world, gravityx, gravityy, gravityz); - d.WorldSetContactSurfaceLayer(world, contactsurfacelayer); - - d.WorldSetLinearDamping(world, 256f); - d.WorldSetAngularDamping(world, 256f); - d.WorldSetAngularDampingThreshold(world, 256f); - d.WorldSetLinearDampingThreshold(world, 256f); - d.WorldSetMaxAngularSpeed(world, 256f); - - // Set how many steps we go without running collision testing - // This is in addition to the step size. - // Essentially Steps * m_physicsiterations - d.WorldSetQuickStepNumIterations(world, m_physicsiterations); - //d.WorldSetContactMaxCorrectingVel(world, 1000.0f); - - for (int i = 0; i < staticPrimspace.GetLength(0); i++) - { - for (int j = 0; j < staticPrimspace.GetLength(1); j++) - { - staticPrimspace[i, j] = IntPtr.Zero; - } - } - - _worldInitialized = true; - } - -// internal void waitForSpaceUnlock(IntPtr space) -// { -// //if (space != IntPtr.Zero) -// //while (d.SpaceLockQuery(space)) { } // Wait and do nothing -// } - -// /// -// /// Debug space message for printing the space that a prim/avatar is in. -// /// -// /// -// /// Returns which split up space the given position is in. -// public string whichspaceamIin(Vector3 pos) -// { -// return calculateSpaceForGeom(pos).ToString(); -// } - - #region Collision Detection - - /// - /// Collides two geometries. - /// - /// - /// - /// /param> - /// - /// - /// - private int CollideGeoms( - IntPtr geom1, IntPtr geom2, int maxContacts, Ode.NET.d.ContactGeom[] contactsArray, int contactGeomSize) - { - int count; - - lock (OdeScene.UniversalColliderSyncObject) - { - // We do this inside the lock so that we don't count any delay in acquiring it - if (CollectStats) - m_nativeCollisionStartTick = Util.EnvironmentTickCount(); - - count = d.Collide(geom1, geom2, maxContacts, contactsArray, contactGeomSize); - } - - // We do this outside the lock so that any waiting threads aren't held up, though the effect is probably - // negligable - if (CollectStats) - m_stats[ODENativeGeomCollisionFrameMsStatName] - += Util.EnvironmentTickCountSubtract(m_nativeCollisionStartTick); - - return count; - } - - /// - /// Collide two spaces or a space and a geometry. - /// - /// - /// /param> - /// - private void CollideSpaces(IntPtr space1, IntPtr space2, IntPtr data) - { - if (CollectStats) - { - m_inCollisionTiming = true; - m_nativeCollisionStartTick = Util.EnvironmentTickCount(); - } - - d.SpaceCollide2(space1, space2, data, nearCallback); - - if (CollectStats && m_inCollisionTiming) - { - m_stats[ODENativeSpaceCollisionFrameMsStatName] - += Util.EnvironmentTickCountSubtract(m_nativeCollisionStartTick); - m_inCollisionTiming = false; - } - } - - /// - /// This is our near callback. A geometry is near a body - /// - /// The space that contains the geoms. Remember, spaces are also geoms - /// a geometry or space - /// another geometry or space - private void near(IntPtr space, IntPtr g1, IntPtr g2) - { - if (CollectStats && m_inCollisionTiming) - { - m_stats[ODENativeSpaceCollisionFrameMsStatName] - += Util.EnvironmentTickCountSubtract(m_nativeCollisionStartTick); - m_inCollisionTiming = false; - } - -// m_log.DebugFormat("[PHYSICS]: Colliding {0} and {1} in {2}", g1, g2, space); - // no lock here! It's invoked from within Simulate(), which is thread-locked - - // Test if we're colliding a geom with a space. - // If so we have to drill down into the space recursively - - if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2)) - { - if (g1 == IntPtr.Zero || g2 == IntPtr.Zero) - return; - - // Separating static prim geometry spaces. - // We'll be calling near recursivly if one - // of them is a space to find all of the - // contact points in the space - try - { - CollideSpaces(g1, g2, IntPtr.Zero); - } - catch (AccessViolationException) - { - m_log.Error("[ODE SCENE]: Unable to collide test a space"); - return; - } - //Colliding a space or a geom with a space or a geom. so drill down - - //Collide all geoms in each space.. - //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback); - //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback); - return; - } - - if (g1 == IntPtr.Zero || g2 == IntPtr.Zero) - return; - - IntPtr b1 = d.GeomGetBody(g1); - IntPtr b2 = d.GeomGetBody(g2); - - // d.GeomClassID id = d.GeomGetClass(g1); - - String name1 = null; - String name2 = null; - - if (!geom_name_map.TryGetValue(g1, out name1)) - { - name1 = "null"; - } - if (!geom_name_map.TryGetValue(g2, out name2)) - { - name2 = "null"; - } - - //if (id == d.GeomClassId.TriMeshClass) - //{ - // m_log.InfoFormat("near: A collision was detected between {1} and {2}", 0, name1, name2); - //m_log.Debug("near: A collision was detected between {1} and {2}", 0, name1, name2); - //} - - // Figure out how many contact points we have - int count = 0; - - try - { - // Colliding Geom To Geom - // This portion of the function 'was' blatantly ripped off from BoxStack.cs - - if (g1 == g2) - return; // Can't collide with yourself - - if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) - return; - - count = CollideGeoms(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf); - - // All code after this is only relevant if we have any collisions - if (count <= 0) - return; - - if (count > contacts.Length) - m_log.Error("[ODE SCENE]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length); - } - catch (SEHException) - { - m_log.Error( - "[ODE SCENE]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim."); - base.TriggerPhysicsBasedRestart(); - } - catch (Exception e) - { - m_log.ErrorFormat("[ODE SCENE]: Unable to collide test an object: {0}", e.Message); - return; - } - - PhysicsActor p1; - PhysicsActor p2; - - p1ExpectedPoints = 0; - p2ExpectedPoints = 0; - - if (!actor_name_map.TryGetValue(g1, out p1)) - { - p1 = PANull; - } - - if (!actor_name_map.TryGetValue(g2, out p2)) - { - p2 = PANull; - } - - ContactPoint maxDepthContact = new ContactPoint(); - if (p1.CollisionScore + count >= float.MaxValue) - p1.CollisionScore = 0; - p1.CollisionScore += count; - - if (p2.CollisionScore + count >= float.MaxValue) - p2.CollisionScore = 0; - p2.CollisionScore += count; - - for (int i = 0; i < count; i++) - { - d.ContactGeom curContact = contacts[i]; - - if (curContact.depth > maxDepthContact.PenetrationDepth) - { - maxDepthContact = new ContactPoint( - new Vector3(curContact.pos.X, curContact.pos.Y, curContact.pos.Z), - new Vector3(curContact.normal.X, curContact.normal.Y, curContact.normal.Z), - curContact.depth - ); - } - - //m_log.Warn("[CCOUNT]: " + count); - IntPtr joint; - // If we're colliding with terrain, use 'TerrainContact' instead of contact. - // allows us to have different settings - - // We only need to test p2 for 'jump crouch purposes' - if (p2 is OdeCharacter && p1.PhysicsActorType == (int)ActorTypes.Prim) - { - // Testing if the collision is at the feet of the avatar - - //m_log.DebugFormat("[PHYSICS]: {0} - {1} - {2} - {3}", curContact.pos.Z, p2.Position.Z, (p2.Position.Z - curContact.pos.Z), (p2.Size.Z * 0.6f)); - if ((p2.Position.Z - curContact.pos.Z) > (p2.Size.Z * 0.6f)) - p2.IsColliding = true; - } - else - { - p2.IsColliding = true; - } - - //if ((framecount % m_returncollisions) == 0) - - switch (p1.PhysicsActorType) - { - case (int)ActorTypes.Agent: - p1ExpectedPoints = avatarExpectedContacts; - p2.CollidingObj = true; - break; - case (int)ActorTypes.Prim: - if (p1 != null && p1 is OdePrim) - p1ExpectedPoints = ((OdePrim) p1).ExpectedCollisionContacts; - - if (p2.Velocity.LengthSquared() > 0.0f) - p2.CollidingObj = true; - break; - case (int)ActorTypes.Unknown: - p2.CollidingGround = true; - break; - default: - p2.CollidingGround = true; - break; - } - - // we don't want prim or avatar to explode - - #region InterPenetration Handling - Unintended physics explosions -# region disabled code1 - - if (curContact.depth >= 0.08f) - { - //This is disabled at the moment only because it needs more tweaking - //It will eventually be uncommented - /* - if (contact.depth >= 1.00f) - { - //m_log.Debug("[PHYSICS]: " + contact.depth.ToString()); - } - - //If you interpenetrate a prim with an agent - if ((p2.PhysicsActorType == (int) ActorTypes.Agent && - p1.PhysicsActorType == (int) ActorTypes.Prim) || - (p1.PhysicsActorType == (int) ActorTypes.Agent && - p2.PhysicsActorType == (int) ActorTypes.Prim)) - { - - //contact.depth = contact.depth * 4.15f; - /* - if (p2.PhysicsActorType == (int) ActorTypes.Agent) - { - p2.CollidingObj = true; - contact.depth = 0.003f; - p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f); - OdeCharacter character = (OdeCharacter) p2; - character.SetPidStatus(true); - contact.pos = new d.Vector3(contact.pos.X + (p1.Size.X / 2), contact.pos.Y + (p1.Size.Y / 2), contact.pos.Z + (p1.Size.Z / 2)); - - } - else - { - - //contact.depth = 0.0000000f; - } - if (p1.PhysicsActorType == (int) ActorTypes.Agent) - { - - p1.CollidingObj = true; - contact.depth = 0.003f; - p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f); - contact.pos = new d.Vector3(contact.pos.X + (p2.Size.X / 2), contact.pos.Y + (p2.Size.Y / 2), contact.pos.Z + (p2.Size.Z / 2)); - OdeCharacter character = (OdeCharacter)p1; - character.SetPidStatus(true); - } - else - { - - //contact.depth = 0.0000000f; - } - - - - } -*/ - // If you interpenetrate a prim with another prim - /* - if (p1.PhysicsActorType == (int) ActorTypes.Prim && p2.PhysicsActorType == (int) ActorTypes.Prim) - { - #region disabledcode2 - //OdePrim op1 = (OdePrim)p1; - //OdePrim op2 = (OdePrim)p2; - //op1.m_collisionscore++; - //op2.m_collisionscore++; - - //if (op1.m_collisionscore > 8000 || op2.m_collisionscore > 8000) - //{ - //op1.m_taintdisable = true; - //AddPhysicsActorTaint(p1); - //op2.m_taintdisable = true; - //AddPhysicsActorTaint(p2); - //} - - //if (contact.depth >= 0.25f) - //{ - // Don't collide, one or both prim will expld. - - //op1.m_interpenetrationcount++; - //op2.m_interpenetrationcount++; - //interpenetrations_before_disable = 200; - //if (op1.m_interpenetrationcount >= interpenetrations_before_disable) - //{ - //op1.m_taintdisable = true; - //AddPhysicsActorTaint(p1); - //} - //if (op2.m_interpenetrationcount >= interpenetrations_before_disable) - //{ - // op2.m_taintdisable = true; - //AddPhysicsActorTaint(p2); - //} - - //contact.depth = contact.depth / 8f; - //contact.normal = new d.Vector3(0, 0, 1); - //} - //if (op1.m_disabled || op2.m_disabled) - //{ - //Manually disabled objects stay disabled - //contact.depth = 0f; - //} - #endregion - } - */ -#endregion - if (curContact.depth >= 1.00f) - { - //m_log.Info("[P]: " + contact.depth.ToString()); - if ((p2.PhysicsActorType == (int) ActorTypes.Agent && - p1.PhysicsActorType == (int) ActorTypes.Unknown) || - (p1.PhysicsActorType == (int) ActorTypes.Agent && - p2.PhysicsActorType == (int) ActorTypes.Unknown)) - { - if (p2.PhysicsActorType == (int) ActorTypes.Agent) - { - if (p2 is OdeCharacter) - { - OdeCharacter character = (OdeCharacter) p2; - - //p2.CollidingObj = true; - curContact.depth = 0.00000003f; - p2.Velocity = p2.Velocity + new Vector3(0f, 0f, 0.5f); - curContact.pos = - new d.Vector3(curContact.pos.X + (p1.Size.X/2), - curContact.pos.Y + (p1.Size.Y/2), - curContact.pos.Z + (p1.Size.Z/2)); - character.SetPidStatus(true); - } - } - - if (p1.PhysicsActorType == (int) ActorTypes.Agent) - { - if (p1 is OdeCharacter) - { - OdeCharacter character = (OdeCharacter) p1; - - //p2.CollidingObj = true; - curContact.depth = 0.00000003f; - p1.Velocity = p1.Velocity + new Vector3(0f, 0f, 0.5f); - curContact.pos = - new d.Vector3(curContact.pos.X + (p1.Size.X/2), - curContact.pos.Y + (p1.Size.Y/2), - curContact.pos.Z + (p1.Size.Z/2)); - character.SetPidStatus(true); - } - } - } - } - } - - #endregion - - // Logic for collision handling - // Note, that if *all* contacts are skipped (VolumeDetect) - // The prim still detects (and forwards) collision events but - // appears to be phantom for the world - Boolean skipThisContact = false; - - if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect)) - skipThisContact = true; // No collision on volume detect prims - - if (av_av_collisions_off) - if ((p1 is OdeCharacter) && (p2 is OdeCharacter)) - skipThisContact = true; - - if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect)) - skipThisContact = true; // No collision on volume detect prims - - if (!skipThisContact && curContact.depth < 0f) - skipThisContact = true; - - if (!skipThisContact && checkDupe(curContact, p2.PhysicsActorType)) - skipThisContact = true; - - const int maxContactsbeforedeath = 4000; - joint = IntPtr.Zero; - - if (!skipThisContact) - { - _perloopContact.Add(curContact); - - if (name1 == "Terrain" || name2 == "Terrain") - { - if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && - (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) - { - p2ExpectedPoints = avatarExpectedContacts; - // Avatar is moving on terrain, use the movement terrain contact - AvatarMovementTerrainContact.geom = curContact; - - if (m_global_contactcount < maxContactsbeforedeath) - { - joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact); - m_global_contactcount++; - } - } - else - { - if (p2.PhysicsActorType == (int)ActorTypes.Agent) - { - p2ExpectedPoints = avatarExpectedContacts; - // Avatar is standing on terrain, use the non moving terrain contact - TerrainContact.geom = curContact; - - if (m_global_contactcount < maxContactsbeforedeath) - { - joint = d.JointCreateContact(world, contactgroup, ref TerrainContact); - m_global_contactcount++; - } - } - else - { - if (p2.PhysicsActorType == (int)ActorTypes.Prim && p1.PhysicsActorType == (int)ActorTypes.Prim) - { - // prim prim contact - // int pj294950 = 0; - int movintYN = 0; - int material = (int) Material.Wood; - // prim terrain contact - if (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f) - { - movintYN = 1; - } - - if (p2 is OdePrim) - { - material = ((OdePrim) p2).m_material; - p2ExpectedPoints = ((OdePrim)p2).ExpectedCollisionContacts; - } - - // Unnessesary because p1 is defined above - //if (p1 is OdePrim) - // { - // p1ExpectedPoints = ((OdePrim)p1).ExpectedCollisionContacts; - // } - //m_log.DebugFormat("Material: {0}", material); - - m_materialContacts[material, movintYN].geom = curContact; - - if (m_global_contactcount < maxContactsbeforedeath) - { - joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]); - m_global_contactcount++; - } - } - else - { - int movintYN = 0; - // prim terrain contact - if (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f) - { - movintYN = 1; - } - - int material = (int)Material.Wood; - - if (p2 is OdePrim) - { - material = ((OdePrim)p2).m_material; - p2ExpectedPoints = ((OdePrim)p2).ExpectedCollisionContacts; - } - - //m_log.DebugFormat("Material: {0}", material); - m_materialContacts[material, movintYN].geom = curContact; - - if (m_global_contactcount < maxContactsbeforedeath) - { - joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]); - m_global_contactcount++; - } - } - } - } - //if (p2.PhysicsActorType == (int)ActorTypes.Prim) - //{ - //m_log.Debug("[PHYSICS]: prim contacting with ground"); - //} - } - else if (name1 == "Water" || name2 == "Water") - { - /* - if ((p2.PhysicsActorType == (int) ActorTypes.Prim)) - { - } - else - { - } - */ - //WaterContact.surface.soft_cfm = 0.0000f; - //WaterContact.surface.soft_erp = 0.00000f; - if (curContact.depth > 0.1f) - { - curContact.depth *= 52; - //contact.normal = new d.Vector3(0, 0, 1); - //contact.pos = new d.Vector3(0, 0, contact.pos.Z - 5f); - } - - WaterContact.geom = curContact; - - if (m_global_contactcount < maxContactsbeforedeath) - { - joint = d.JointCreateContact(world, contactgroup, ref WaterContact); - m_global_contactcount++; - } - //m_log.Info("[PHYSICS]: Prim Water Contact" + contact.depth); - } - else - { - if ((p2.PhysicsActorType == (int)ActorTypes.Agent)) - { - p2ExpectedPoints = avatarExpectedContacts; - if ((Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) - { - // Avatar is moving on a prim, use the Movement prim contact - AvatarMovementprimContact.geom = curContact; - - if (m_global_contactcount < maxContactsbeforedeath) - { - joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact); - m_global_contactcount++; - } - } - else - { - // Avatar is standing still on a prim, use the non movement contact - contact.geom = curContact; - - if (m_global_contactcount < maxContactsbeforedeath) - { - joint = d.JointCreateContact(world, contactgroup, ref contact); - m_global_contactcount++; - } - } - } - else if (p2.PhysicsActorType == (int)ActorTypes.Prim) - { - //p1.PhysicsActorType - int material = (int)Material.Wood; - - if (p2 is OdePrim) - { - material = ((OdePrim)p2).m_material; - p2ExpectedPoints = ((OdePrim)p2).ExpectedCollisionContacts; - } - - //m_log.DebugFormat("Material: {0}", material); - m_materialContacts[material, 0].geom = curContact; - - if (m_global_contactcount < maxContactsbeforedeath) - { - joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, 0]); - m_global_contactcount++; - } - } - } - - if (m_global_contactcount < maxContactsbeforedeath && joint != IntPtr.Zero) // stack collide! - { - d.JointAttach(joint, b1, b2); - m_global_contactcount++; - } - } - - collision_accounting_events(p1, p2, maxDepthContact); - - if (count > ((p1ExpectedPoints + p2ExpectedPoints) * 0.25) + (geomContactPointsStartthrottle)) - { - // If there are more then 3 contact points, it's likely - // that we've got a pile of objects, so ... - // We don't want to send out hundreds of terse updates over and over again - // so lets throttle them and send them again after it's somewhat sorted out. - p2.ThrottleUpdates = true; - } - //m_log.Debug(count.ToString()); - //m_log.Debug("near: A collision was detected between {1} and {2}", 0, name1, name2); - } - } - - private bool checkDupe(d.ContactGeom contactGeom, int atype) - { - if (!m_filterCollisions) - return false; - - bool result = false; - - ActorTypes at = (ActorTypes)atype; - - foreach (d.ContactGeom contact in _perloopContact) - { - //if ((contact.g1 == contactGeom.g1 && contact.g2 == contactGeom.g2)) - //{ - // || (contact.g2 == contactGeom.g1 && contact.g1 == contactGeom.g2) - if (at == ActorTypes.Agent) - { - if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) - && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) - && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f))) - { - if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f) - { - //contactGeom.depth *= .00005f; - //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth)); - // m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z)); - result = true; - break; - } -// else -// { -// //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth)); -// } - } -// else -// { -// //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z)); -// //int i = 0; -// } - } - else if (at == ActorTypes.Prim) - { - //d.AABB aabb1 = new d.AABB(); - //d.AABB aabb2 = new d.AABB(); - - //d.GeomGetAABB(contactGeom.g2, out aabb2); - //d.GeomGetAABB(contactGeom.g1, out aabb1); - //aabb1. - if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f))) - { - if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z) - { - if (Math.Abs(contact.depth - contactGeom.depth) < 0.272f) - { - result = true; - break; - } - } - //m_log.DebugFormat("[Collision]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth)); - //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z)); - } - } - } - - return result; - } - - private void collision_accounting_events(PhysicsActor p1, PhysicsActor p2, ContactPoint contact) - { - // obj1LocalID = 0; - //returncollisions = false; - obj2LocalID = 0; - //ctype = 0; - //cStartStop = 0; - if (!p2.SubscribedEvents() && !p1.SubscribedEvents()) - return; - - switch ((ActorTypes)p2.PhysicsActorType) - { - case ActorTypes.Agent: - cc2 = (OdeCharacter)p2; - - // obj1LocalID = cc2.m_localID; - switch ((ActorTypes)p1.PhysicsActorType) - { - case ActorTypes.Agent: - cc1 = (OdeCharacter)p1; - obj2LocalID = cc1.LocalID; - cc1.AddCollisionEvent(cc2.LocalID, contact); - //ctype = (int)CollisionCategories.Character; - - //if (cc1.CollidingObj) - //cStartStop = (int)StatusIndicators.Generic; - //else - //cStartStop = (int)StatusIndicators.Start; - - //returncollisions = true; - break; - - case ActorTypes.Prim: - if (p1 is OdePrim) - { - cp1 = (OdePrim) p1; - obj2LocalID = cp1.LocalID; - cp1.AddCollisionEvent(cc2.LocalID, contact); - } - //ctype = (int)CollisionCategories.Geom; - - //if (cp1.CollidingObj) - //cStartStop = (int)StatusIndicators.Generic; - //else - //cStartStop = (int)StatusIndicators.Start; - - //returncollisions = true; - break; - - case ActorTypes.Ground: - case ActorTypes.Unknown: - obj2LocalID = 0; - //ctype = (int)CollisionCategories.Land; - //returncollisions = true; - break; - } - - cc2.AddCollisionEvent(obj2LocalID, contact); - break; - - case ActorTypes.Prim: - - if (p2 is OdePrim) - { - cp2 = (OdePrim) p2; - - // obj1LocalID = cp2.m_localID; - switch ((ActorTypes) p1.PhysicsActorType) - { - case ActorTypes.Agent: - if (p1 is OdeCharacter) - { - cc1 = (OdeCharacter) p1; - obj2LocalID = cc1.LocalID; - cc1.AddCollisionEvent(cp2.LocalID, contact); - //ctype = (int)CollisionCategories.Character; - - //if (cc1.CollidingObj) - //cStartStop = (int)StatusIndicators.Generic; - //else - //cStartStop = (int)StatusIndicators.Start; - //returncollisions = true; - } - break; - case ActorTypes.Prim: - - if (p1 is OdePrim) - { - cp1 = (OdePrim) p1; - obj2LocalID = cp1.LocalID; - cp1.AddCollisionEvent(cp2.LocalID, contact); - //ctype = (int)CollisionCategories.Geom; - - //if (cp1.CollidingObj) - //cStartStop = (int)StatusIndicators.Generic; - //else - //cStartStop = (int)StatusIndicators.Start; - - //returncollisions = true; - } - break; - - case ActorTypes.Ground: - case ActorTypes.Unknown: - obj2LocalID = 0; - //ctype = (int)CollisionCategories.Land; - - //returncollisions = true; - break; - } - - cp2.AddCollisionEvent(obj2LocalID, contact); - } - break; - } - //if (returncollisions) - //{ - - //lock (m_storedCollisions) - //{ - //cDictKey = obj1LocalID.ToString() + obj2LocalID.ToString() + cStartStop.ToString() + ctype.ToString(); - //if (m_storedCollisions.ContainsKey(cDictKey)) - //{ - //sCollisionData objd = m_storedCollisions[cDictKey]; - //objd.NumberOfCollisions += 1; - //objd.lastframe = framecount; - //m_storedCollisions[cDictKey] = objd; - //} - //else - //{ - //sCollisionData objd = new sCollisionData(); - //objd.ColliderLocalId = obj1LocalID; - //objd.CollidedWithLocalId = obj2LocalID; - //objd.CollisionType = ctype; - //objd.NumberOfCollisions = 1; - //objd.lastframe = framecount; - //objd.StatusIndicator = cStartStop; - //m_storedCollisions.Add(cDictKey, objd); - //} - //} - // } - } - - private int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount) - { - /* String name1 = null; - String name2 = null; - - if (!geom_name_map.TryGetValue(trimesh, out name1)) - { - name1 = "null"; - } - if (!geom_name_map.TryGetValue(refObject, out name2)) - { - name2 = "null"; - } - - m_log.InfoFormat("TriArrayCallback: A collision was detected between {1} and {2}", 0, name1, name2); - */ - return 1; - } - - private int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex) - { -// String name1 = null; -// String name2 = null; -// -// if (!geom_name_map.TryGetValue(trimesh, out name1)) -// { -// name1 = "null"; -// } -// -// if (!geom_name_map.TryGetValue(refObject, out name2)) -// { -// name2 = "null"; -// } - - // m_log.InfoFormat("TriCallback: A collision was detected between {1} and {2}. Index was {3}", 0, name1, name2, triangleIndex); - - d.Vector3 v0 = new d.Vector3(); - d.Vector3 v1 = new d.Vector3(); - d.Vector3 v2 = new d.Vector3(); - - d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2); - // m_log.DebugFormat("Triangle {0} is <{1},{2},{3}>, <{4},{5},{6}>, <{7},{8},{9}>", triangleIndex, v0.X, v0.Y, v0.Z, v1.X, v1.Y, v1.Z, v2.X, v2.Y, v2.Z); - - return 1; - } - - /// - /// This is our collision testing routine in ODE - /// - private void collision_optimized() - { - _perloopContact.Clear(); - - foreach (OdeCharacter chr in _characters) - { - // Reset the collision values to false - // since we don't know if we're colliding yet - if (chr.Shell == IntPtr.Zero || chr.Body == IntPtr.Zero) - continue; - - chr.IsColliding = false; - chr.CollidingGround = false; - chr.CollidingObj = false; - - // Test the avatar's geometry for collision with the space - // This will return near and the space that they are the closest to - // And we'll run this again against the avatar and the space segment - // This will return with a bunch of possible objects in the space segment - // and we'll run it again on all of them. - try - { - CollideSpaces(space, chr.Shell, IntPtr.Zero); - } - catch (AccessViolationException) - { - m_log.ErrorFormat("[ODE SCENE]: Unable to space collide {0}", Name); - } - - //float terrainheight = GetTerrainHeightAtXY(chr.Position.X, chr.Position.Y); - //if (chr.Position.Z + (chr.Velocity.Z * timeStep) < terrainheight + 10) - //{ - //chr.Position.Z = terrainheight + 10.0f; - //forcedZ = true; - //} - } - - if (CollectStats) - { - m_tempAvatarCollisionsThisFrame = _perloopContact.Count; - m_stats[ODEAvatarContactsStatsName] += m_tempAvatarCollisionsThisFrame; - } - - List removeprims = null; - foreach (OdePrim chr in _activeprims) - { - if (chr.Body != IntPtr.Zero && d.BodyIsEnabled(chr.Body) && (!chr.m_disabled)) - { - try - { - lock (chr) - { - if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false) - { - CollideSpaces(space, chr.prim_geom, IntPtr.Zero); - } - else - { - if (removeprims == null) - { - removeprims = new List(); - } - removeprims.Add(chr); - m_log.Error( - "[ODE SCENE]: unable to collide test active prim against space. The space was zero, the geom was zero or it was in the process of being removed. Removed it from the active prim list. This needs to be fixed!"); - } - } - } - catch (AccessViolationException) - { - m_log.Error("[ODE SCENE]: Unable to space collide"); - } - } - } - - if (CollectStats) - m_stats[ODEPrimContactsStatName] += _perloopContact.Count - m_tempAvatarCollisionsThisFrame; - - if (removeprims != null) - { - foreach (OdePrim chr in removeprims) - { - _activeprims.Remove(chr); - } - } - } - - #endregion - - public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) - { - m_worldOffset = offset; - WorldExtents = new Vector2(extents.X, extents.Y); - m_parentScene = pScene; - } - - // Recovered for use by fly height. Kitto Flora - internal float GetTerrainHeightAtXY(float x, float y) - { - int offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize; - int offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize; - - IntPtr heightFieldGeom = IntPtr.Zero; - - if (RegionTerrain.TryGetValue(new Vector3(offsetX,offsetY,0), out heightFieldGeom)) - { - if (heightFieldGeom != IntPtr.Zero) - { - if (TerrainHeightFieldHeights.ContainsKey(heightFieldGeom)) - { - - int index; - - - if ((int)x > WorldExtents.X || (int)y > WorldExtents.Y || - (int)x < 0.001f || (int)y < 0.001f) - return 0; - - x = x - offsetX; - y = y - offsetY; - - index = (int)((int)x * ((int)Constants.RegionSize + 2) + (int)y); - - if (index < TerrainHeightFieldHeights[heightFieldGeom].Length) - { - //m_log.DebugFormat("x{0} y{1} = {2}", x, y, (float)TerrainHeightFieldHeights[heightFieldGeom][index]); - return (float)TerrainHeightFieldHeights[heightFieldGeom][index]; - } - - else - return 0f; - } - else - { - return 0f; - } - - } - else - { - return 0f; - } - - } - else - { - return 0f; - } - } -// End recovered. Kitto Flora - - /// - /// Add actor to the list that should receive collision events in the simulate loop. - /// - /// - internal void AddCollisionEventReporting(PhysicsActor obj) - { -// m_log.DebugFormat("[PHYSICS]: Adding {0} {1} to collision event reporting", obj.SOPName, obj.LocalID); - - lock (m_collisionEventActorsChanges) - m_collisionEventActorsChanges[obj.LocalID] = obj; - } - - /// - /// Remove actor from the list that should receive collision events in the simulate loop. - /// - /// - internal void RemoveCollisionEventReporting(PhysicsActor obj) - { -// m_log.DebugFormat("[PHYSICS]: Removing {0} {1} from collision event reporting", obj.SOPName, obj.LocalID); - - lock (m_collisionEventActorsChanges) - m_collisionEventActorsChanges[obj.LocalID] = null; - } - - #region Add/Remove Entities - - public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) - { - Vector3 pos; - pos.X = position.X; - pos.Y = position.Y; - pos.Z = position.Z; - - OdeCharacter newAv - = new OdeCharacter( - avName, this, pos, size, avPIDD, avPIDP, - avCapRadius, avStandupTensor, avDensity, - avMovementDivisorWalk, avMovementDivisorRun); - - newAv.Flying = isFlying; - newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset; - newAv.m_avatarplanted = avplanted; - - return newAv; - } - - public override void RemoveAvatar(PhysicsActor actor) - { -// m_log.DebugFormat( -// "[ODE SCENE]: Removing physics character {0} {1} from physics scene {2}", -// actor.Name, actor.LocalID, Name); - - ((OdeCharacter) actor).Destroy(); - } - - internal void AddCharacter(OdeCharacter chr) - { - chr.m_avatarplanted = avplanted; - if (!_characters.Contains(chr)) - { - _characters.Add(chr); - -// m_log.DebugFormat( -// "[ODE SCENE]: Adding physics character {0} {1} to physics scene {2}. Count now {3}", -// chr.Name, chr.LocalID, Name, _characters.Count); - - if (chr.bad) - m_log.ErrorFormat("[ODE SCENE]: Added BAD actor {0} to characters list", chr.m_uuid); - } - else - { - m_log.ErrorFormat( - "[ODE SCENE]: Tried to add character {0} {1} but they are already in the set!", - chr.Name, chr.LocalID); - } - } - - internal void RemoveCharacter(OdeCharacter chr) - { - if (_characters.Contains(chr)) - { - _characters.Remove(chr); - -// m_log.DebugFormat( -// "[ODE SCENE]: Removing physics character {0} {1} from physics scene {2}. Count now {3}", -// chr.Name, chr.LocalID, Name, _characters.Count); - } - else - { - m_log.ErrorFormat( - "[ODE SCENE]: Tried to remove character {0} {1} but they are not in the list!", - chr.Name, chr.LocalID); - } - } - - private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation, - PrimitiveBaseShape pbs, bool isphysical, uint localID) - { - Vector3 pos = position; - Vector3 siz = size; - Quaternion rot = rotation; - - OdePrim newPrim; - lock (OdeLock) - { - newPrim = new OdePrim(name, this, pos, siz, rot, pbs, isphysical); - - lock (_prims) - _prims.Add(newPrim); - } - newPrim.LocalID = localID; - return newPrim; - } - - /// - /// Make this prim subject to physics. - /// - /// - internal void ActivatePrim(OdePrim prim) - { - // adds active prim.. (ones that should be iterated over in collisions_optimized - if (!_activeprims.Contains(prim)) - _activeprims.Add(prim); - //else - // m_log.Warn("[PHYSICS]: Double Entry in _activeprims detected, potential crash immenent"); - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, - Vector3 size, Quaternion rotation, bool isPhysical, uint localid) - { -// m_log.DebugFormat("[ODE SCENE]: Adding physics prim {0} {1} to physics scene {2}", primName, localid, Name); - - return AddPrim(primName, position, size, rotation, pbs, isPhysical, localid); - } - - public override float TimeDilation - { - get { return m_timeDilation; } - } - - public override bool SupportsNINJAJoints - { - get { return m_NINJA_physics_joints_enabled; } - } - - // internal utility function: must be called within a lock (OdeLock) - private void InternalAddActiveJoint(PhysicsJoint joint) - { - activeJoints.Add(joint); - SOPName_to_activeJoint.Add(joint.ObjectNameInScene, joint); - } - - // internal utility function: must be called within a lock (OdeLock) - private void InternalAddPendingJoint(OdePhysicsJoint joint) - { - pendingJoints.Add(joint); - SOPName_to_pendingJoint.Add(joint.ObjectNameInScene, joint); - } - - // internal utility function: must be called within a lock (OdeLock) - private void InternalRemovePendingJoint(PhysicsJoint joint) - { - pendingJoints.Remove(joint); - SOPName_to_pendingJoint.Remove(joint.ObjectNameInScene); - } - - // internal utility function: must be called within a lock (OdeLock) - private void InternalRemoveActiveJoint(PhysicsJoint joint) - { - activeJoints.Remove(joint); - SOPName_to_activeJoint.Remove(joint.ObjectNameInScene); - } - - public override void DumpJointInfo() - { - string hdr = "[NINJA] JOINTINFO: "; - foreach (PhysicsJoint j in pendingJoints) - { - m_log.Debug(hdr + " pending joint, Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams); - } - m_log.Debug(hdr + pendingJoints.Count + " total pending joints"); - foreach (string jointName in SOPName_to_pendingJoint.Keys) - { - m_log.Debug(hdr + " pending joints dict contains Name: " + jointName); - } - m_log.Debug(hdr + SOPName_to_pendingJoint.Keys.Count + " total pending joints dict entries"); - foreach (PhysicsJoint j in activeJoints) - { - m_log.Debug(hdr + " active joint, Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams); - } - m_log.Debug(hdr + activeJoints.Count + " total active joints"); - foreach (string jointName in SOPName_to_activeJoint.Keys) - { - m_log.Debug(hdr + " active joints dict contains Name: " + jointName); - } - m_log.Debug(hdr + SOPName_to_activeJoint.Keys.Count + " total active joints dict entries"); - - m_log.Debug(hdr + " Per-body joint connectivity information follows."); - m_log.Debug(hdr + joints_connecting_actor.Keys.Count + " bodies are connected by joints."); - foreach (string actorName in joints_connecting_actor.Keys) - { - m_log.Debug(hdr + " Actor " + actorName + " has the following joints connecting it"); - foreach (PhysicsJoint j in joints_connecting_actor[actorName]) - { - m_log.Debug(hdr + " * joint Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams); - } - m_log.Debug(hdr + joints_connecting_actor[actorName].Count + " connecting joints total for this actor"); - } - } - - public override void RequestJointDeletion(string ObjectNameInScene) - { - lock (externalJointRequestsLock) - { - if (!requestedJointsToBeDeleted.Contains(ObjectNameInScene)) // forbid same deletion request from entering twice to prevent spurious deletions processed asynchronously - { - requestedJointsToBeDeleted.Add(ObjectNameInScene); - } - } - } - - private void DeleteRequestedJoints() - { - List myRequestedJointsToBeDeleted; - lock (externalJointRequestsLock) - { - // make a local copy of the shared list for processing (threading issues) - myRequestedJointsToBeDeleted = new List(requestedJointsToBeDeleted); - } - - foreach (string jointName in myRequestedJointsToBeDeleted) - { - lock (OdeLock) - { - //m_log.Debug("[NINJA] trying to deleting requested joint " + jointName); - if (SOPName_to_activeJoint.ContainsKey(jointName) || SOPName_to_pendingJoint.ContainsKey(jointName)) - { - OdePhysicsJoint joint = null; - if (SOPName_to_activeJoint.ContainsKey(jointName)) - { - joint = SOPName_to_activeJoint[jointName] as OdePhysicsJoint; - InternalRemoveActiveJoint(joint); - } - else if (SOPName_to_pendingJoint.ContainsKey(jointName)) - { - joint = SOPName_to_pendingJoint[jointName] as OdePhysicsJoint; - InternalRemovePendingJoint(joint); - } - - if (joint != null) - { - //m_log.Debug("joint.BodyNames.Count is " + joint.BodyNames.Count + " and contents " + joint.BodyNames); - for (int iBodyName = 0; iBodyName < 2; iBodyName++) - { - string bodyName = joint.BodyNames[iBodyName]; - if (bodyName != "NULL") - { - joints_connecting_actor[bodyName].Remove(joint); - if (joints_connecting_actor[bodyName].Count == 0) - { - joints_connecting_actor.Remove(bodyName); - } - } - } - - DoJointDeactivated(joint); - if (joint.jointID != IntPtr.Zero) - { - d.JointDestroy(joint.jointID); - joint.jointID = IntPtr.Zero; - //DoJointErrorMessage(joint, "successfully destroyed joint " + jointName); - } - else - { - //m_log.Warn("[NINJA] Ignoring re-request to destroy joint " + jointName); - } - } - else - { - // DoJointErrorMessage(joint, "coult not find joint to destroy based on name " + jointName); - } - } - else - { - // DoJointErrorMessage(joint, "WARNING - joint removal failed, joint " + jointName); - } - } - } - - // remove processed joints from the shared list - lock (externalJointRequestsLock) - { - foreach (string jointName in myRequestedJointsToBeDeleted) - { - requestedJointsToBeDeleted.Remove(jointName); - } - } - } - - // for pending joints we don't know if their associated bodies exist yet or not. - // the joint is actually created during processing of the taints - private void CreateRequestedJoints() - { - List myRequestedJointsToBeCreated; - lock (externalJointRequestsLock) - { - // make a local copy of the shared list for processing (threading issues) - myRequestedJointsToBeCreated = new List(requestedJointsToBeCreated); - } - - foreach (PhysicsJoint joint in myRequestedJointsToBeCreated) - { - lock (OdeLock) - { - if (SOPName_to_pendingJoint.ContainsKey(joint.ObjectNameInScene) && SOPName_to_pendingJoint[joint.ObjectNameInScene] != null) - { - DoJointErrorMessage(joint, "WARNING: ignoring request to re-add already pending joint Name:" + joint.ObjectNameInScene + " type:" + joint.Type + " parms: " + joint.RawParams + " pos: " + joint.Position + " rot:" + joint.Rotation); - continue; - } - if (SOPName_to_activeJoint.ContainsKey(joint.ObjectNameInScene) && SOPName_to_activeJoint[joint.ObjectNameInScene] != null) - { - DoJointErrorMessage(joint, "WARNING: ignoring request to re-add already active joint Name:" + joint.ObjectNameInScene + " type:" + joint.Type + " parms: " + joint.RawParams + " pos: " + joint.Position + " rot:" + joint.Rotation); - continue; - } - - InternalAddPendingJoint(joint as OdePhysicsJoint); - - if (joint.BodyNames.Count >= 2) - { - for (int iBodyName = 0; iBodyName < 2; iBodyName++) - { - string bodyName = joint.BodyNames[iBodyName]; - if (bodyName != "NULL") - { - if (!joints_connecting_actor.ContainsKey(bodyName)) - { - joints_connecting_actor.Add(bodyName, new List()); - } - joints_connecting_actor[bodyName].Add(joint); - } - } - } - } - } - - // remove processed joints from shared list - lock (externalJointRequestsLock) - { - foreach (PhysicsJoint joint in myRequestedJointsToBeCreated) - { - requestedJointsToBeCreated.Remove(joint); - } - } - } - - /// - /// Add a request for joint creation. - /// - /// - /// this joint will just be added to a waiting list that is NOT processed during the main - /// Simulate() loop (to avoid deadlocks). After Simulate() is finished, we handle unprocessed joint requests. - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public override PhysicsJoint RequestJointCreation( - string objectNameInScene, PhysicsJointType jointType, Vector3 position, - Quaternion rotation, string parms, List bodyNames, string trackedBodyName, Quaternion localRotation) - { - OdePhysicsJoint joint = new OdePhysicsJoint(); - joint.ObjectNameInScene = objectNameInScene; - joint.Type = jointType; - joint.Position = position; - joint.Rotation = rotation; - joint.RawParams = parms; - joint.BodyNames = new List(bodyNames); - joint.TrackedBodyName = trackedBodyName; - joint.LocalRotation = localRotation; - joint.jointID = IntPtr.Zero; - joint.ErrorMessageCount = 0; - - lock (externalJointRequestsLock) - { - if (!requestedJointsToBeCreated.Contains(joint)) // forbid same creation request from entering twice - { - requestedJointsToBeCreated.Add(joint); - } - } - - return joint; - } - - private void RemoveAllJointsConnectedToActor(PhysicsActor actor) - { - //m_log.Debug("RemoveAllJointsConnectedToActor: start"); - if (actor.SOPName != null && joints_connecting_actor.ContainsKey(actor.SOPName) && joints_connecting_actor[actor.SOPName] != null) - { - List jointsToRemove = new List(); - //TODO: merge these 2 loops (originally it was needed to avoid altering a list being iterated over, but it is no longer needed due to the joint request queue mechanism) - foreach (PhysicsJoint j in joints_connecting_actor[actor.SOPName]) - { - jointsToRemove.Add(j); - } - foreach (PhysicsJoint j in jointsToRemove) - { - //m_log.Debug("RemoveAllJointsConnectedToActor: about to request deletion of " + j.ObjectNameInScene); - RequestJointDeletion(j.ObjectNameInScene); - //m_log.Debug("RemoveAllJointsConnectedToActor: done request deletion of " + j.ObjectNameInScene); - j.TrackedBodyName = null; // *IMMEDIATELY* prevent any further movement of this joint (else a deleted actor might cause spurious tracking motion of the joint for a few frames, leading to the joint proxy object disappearing) - } - } - } - - public override void RemoveAllJointsConnectedToActorThreadLocked(PhysicsActor actor) - { - //m_log.Debug("RemoveAllJointsConnectedToActorThreadLocked: start"); - lock (OdeLock) - { - //m_log.Debug("RemoveAllJointsConnectedToActorThreadLocked: got lock"); - RemoveAllJointsConnectedToActor(actor); - } - } - - // normally called from within OnJointMoved, which is called from within a lock (OdeLock) - public override Vector3 GetJointAnchor(PhysicsJoint joint) - { - Debug.Assert(joint.IsInPhysicsEngine); - d.Vector3 pos = new d.Vector3(); - - if (!(joint is OdePhysicsJoint)) - { - DoJointErrorMessage(joint, "warning: non-ODE joint requesting anchor: " + joint.ObjectNameInScene); - } - else - { - OdePhysicsJoint odeJoint = (OdePhysicsJoint)joint; - switch (odeJoint.Type) - { - case PhysicsJointType.Ball: - d.JointGetBallAnchor(odeJoint.jointID, out pos); - break; - case PhysicsJointType.Hinge: - d.JointGetHingeAnchor(odeJoint.jointID, out pos); - break; - } - } - return new Vector3(pos.X, pos.Y, pos.Z); - } - - /// - /// Get joint axis. - /// - /// - /// normally called from within OnJointMoved, which is called from within a lock (OdeLock) - /// WARNING: ODE sometimes returns <0,0,0> as the joint axis! Therefore this function - /// appears to be unreliable. Fortunately we can compute the joint axis ourselves by - /// keeping track of the joint's original orientation relative to one of the involved bodies. - /// - /// - /// - public override Vector3 GetJointAxis(PhysicsJoint joint) - { - Debug.Assert(joint.IsInPhysicsEngine); - d.Vector3 axis = new d.Vector3(); - - if (!(joint is OdePhysicsJoint)) - { - DoJointErrorMessage(joint, "warning: non-ODE joint requesting anchor: " + joint.ObjectNameInScene); - } - else - { - OdePhysicsJoint odeJoint = (OdePhysicsJoint)joint; - switch (odeJoint.Type) - { - case PhysicsJointType.Ball: - DoJointErrorMessage(joint, "warning - axis requested for ball joint: " + joint.ObjectNameInScene); - break; - case PhysicsJointType.Hinge: - d.JointGetHingeAxis(odeJoint.jointID, out axis); - break; - } - } - return new Vector3(axis.X, axis.Y, axis.Z); - } - - /// - /// Stop this prim being subject to physics - /// - /// - internal void DeactivatePrim(OdePrim prim) - { - _activeprims.Remove(prim); - } - - public override void RemovePrim(PhysicsActor prim) - { - // As with all ODE physics operations, we don't remove the prim immediately but signal that it should be - // removed in the next physics simulate pass. - if (prim is OdePrim) - { - lock (OdeLock) - { - OdePrim p = (OdePrim) prim; - - p.setPrimForRemoval(); - AddPhysicsActorTaint(prim); - } - } - } - - /// - /// This is called from within simulate but outside the locked portion - /// We need to do our own locking here - /// (Note: As of 20110801 this no longer appears to be true - this is being called within lock (odeLock) in - /// Simulate() -- justincc). - /// - /// Essentially, we need to remove the prim from our space segment, whatever segment it's in. - /// - /// If there are no more prim in the segment, we need to empty (spacedestroy)the segment and reclaim memory - /// that the space was using. - /// - /// - internal void RemovePrimThreadLocked(OdePrim prim) - { -// m_log.DebugFormat("[ODE SCENE]: Removing physical prim {0} {1}", prim.Name, prim.LocalID); - - lock (prim) - { - RemoveCollisionEventReporting(prim); - - if (prim.prim_geom != IntPtr.Zero) - { - prim.ResetTaints(); - - if (prim.IsPhysical) - { - prim.disableBody(); - if (prim.childPrim) - { - prim.childPrim = false; - prim.Body = IntPtr.Zero; - prim.m_disabled = true; - prim.IsPhysical = false; - } - - - } - // we don't want to remove the main space - - // If the geometry is in the targetspace, remove it from the target space - //m_log.Warn(prim.m_targetSpace); - - //if (prim.m_targetSpace != IntPtr.Zero) - //{ - //if (d.SpaceQuery(prim.m_targetSpace, prim.prim_geom)) - //{ - - //if (d.GeomIsSpace(prim.m_targetSpace)) - //{ - //waitForSpaceUnlock(prim.m_targetSpace); - //d.SpaceRemove(prim.m_targetSpace, prim.prim_geom); - prim.m_targetSpace = IntPtr.Zero; - //} - //else - //{ - // m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" + - //((OdePrim)prim).m_targetSpace.ToString()); - //} - - //} - //} - //m_log.Warn(prim.prim_geom); - - if (!prim.RemoveGeom()) - m_log.Warn("[ODE SCENE]: Unable to remove prim from physics scene"); - - lock (_prims) - _prims.Remove(prim); - - //If there are no more geometries in the sub-space, we don't need it in the main space anymore - //if (d.SpaceGetNumGeoms(prim.m_targetSpace) == 0) - //{ - //if (prim.m_targetSpace != null) - //{ - //if (d.GeomIsSpace(prim.m_targetSpace)) - //{ - //waitForSpaceUnlock(prim.m_targetSpace); - //d.SpaceRemove(space, prim.m_targetSpace); - // free up memory used by the space. - //d.SpaceDestroy(prim.m_targetSpace); - //int[] xyspace = calculateSpaceArrayItemFromPos(prim.Position); - //resetSpaceArrayItemToZero(xyspace[0], xyspace[1]); - //} - //else - //{ - //m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" + - //((OdePrim) prim).m_targetSpace.ToString()); - //} - //} - //} - - if (SupportsNINJAJoints) - RemoveAllJointsConnectedToActorThreadLocked(prim); - } - } - } - - #endregion - - #region Space Separation Calculation - - /// - /// Takes a space pointer and zeros out the array we're using to hold the spaces - /// - /// - private void resetSpaceArrayItemToZero(IntPtr pSpace) - { - for (int x = 0; x < staticPrimspace.GetLength(0); x++) - { - for (int y = 0; y < staticPrimspace.GetLength(1); y++) - { - if (staticPrimspace[x, y] == pSpace) - staticPrimspace[x, y] = IntPtr.Zero; - } - } - } - -// private void resetSpaceArrayItemToZero(int arrayitemX, int arrayitemY) -// { -// staticPrimspace[arrayitemX, arrayitemY] = IntPtr.Zero; -// } - - /// - /// Called when a static prim moves. Allocates a space for the prim based on its position - /// - /// the pointer to the geom that moved - /// the position that the geom moved to - /// a pointer to the space it was in before it was moved. - /// a pointer to the new space it's in - internal IntPtr recalculateSpaceForGeom(IntPtr geom, Vector3 pos, IntPtr currentspace) - { - // Called from setting the Position and Size of an ODEPrim so - // it's already in locked space. - - // we don't want to remove the main space - // we don't need to test physical here because this function should - // never be called if the prim is physical(active) - - // All physical prim end up in the root space - //Thread.Sleep(20); - if (currentspace != space) - { - //m_log.Info("[SPACE]: C:" + currentspace.ToString() + " g:" + geom.ToString()); - //if (currentspace == IntPtr.Zero) - //{ - //int adfadf = 0; - //} - if (d.SpaceQuery(currentspace, geom) && currentspace != IntPtr.Zero) - { - if (d.GeomIsSpace(currentspace)) - { -// waitForSpaceUnlock(currentspace); - d.SpaceRemove(currentspace, geom); - } - else - { - m_log.Info("[ODE SCENE]: Invalid Scene passed to 'recalculatespace':" + currentspace + - " Geom:" + geom); - } - } - else - { - IntPtr sGeomIsIn = d.GeomGetSpace(geom); - if (sGeomIsIn != IntPtr.Zero) - { - if (d.GeomIsSpace(currentspace)) - { -// waitForSpaceUnlock(sGeomIsIn); - d.SpaceRemove(sGeomIsIn, geom); - } - else - { - m_log.Info("[ODE SCENE]: Invalid Scene passed to 'recalculatespace':" + - sGeomIsIn + " Geom:" + geom); - } - } - } - - //If there are no more geometries in the sub-space, we don't need it in the main space anymore - if (d.SpaceGetNumGeoms(currentspace) == 0) - { - if (currentspace != IntPtr.Zero) - { - if (d.GeomIsSpace(currentspace)) - { -// waitForSpaceUnlock(currentspace); -// waitForSpaceUnlock(space); - d.SpaceRemove(space, currentspace); - // free up memory used by the space. - - //d.SpaceDestroy(currentspace); - resetSpaceArrayItemToZero(currentspace); - } - else - { - m_log.Info("[ODE SCENE]: Invalid Scene passed to 'recalculatespace':" + - currentspace + " Geom:" + geom); - } - } - } - } - else - { - // this is a physical object that got disabled. ;.; - if (currentspace != IntPtr.Zero && geom != IntPtr.Zero) - { - if (d.SpaceQuery(currentspace, geom)) - { - if (d.GeomIsSpace(currentspace)) - { -// waitForSpaceUnlock(currentspace); - d.SpaceRemove(currentspace, geom); - } - else - { - m_log.Info("[ODE SCENE]: Invalid Scene passed to 'recalculatespace':" + - currentspace + " Geom:" + geom); - } - } - else - { - IntPtr sGeomIsIn = d.GeomGetSpace(geom); - if (sGeomIsIn != IntPtr.Zero) - { - if (d.GeomIsSpace(sGeomIsIn)) - { -// waitForSpaceUnlock(sGeomIsIn); - d.SpaceRemove(sGeomIsIn, geom); - } - else - { - m_log.Info("[ODE SCENE]: Invalid Scene passed to 'recalculatespace':" + - sGeomIsIn + " Geom:" + geom); - } - } - } - } - } - - // The routines in the Position and Size sections do the 'inserting' into the space, - // so all we have to do is make sure that the space that we're putting the prim into - // is in the 'main' space. - int[] iprimspaceArrItem = calculateSpaceArrayItemFromPos(pos); - IntPtr newspace = calculateSpaceForGeom(pos); - - if (newspace == IntPtr.Zero) - { - newspace = createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]); - d.HashSpaceSetLevels(newspace, smallHashspaceLow, smallHashspaceHigh); - } - - return newspace; - } - - /// - /// Creates a new space at X Y - /// - /// - /// - /// A pointer to the created space - internal IntPtr createprimspace(int iprimspaceArrItemX, int iprimspaceArrItemY) - { - // creating a new space for prim and inserting it into main space. - staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY] = d.HashSpaceCreate(IntPtr.Zero); - d.GeomSetCategoryBits(staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY], (int)CollisionCategories.Space); -// waitForSpaceUnlock(space); - d.SpaceSetSublevel(space, 1); - d.SpaceAdd(space, staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]); - - return staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]; - } - - /// - /// Calculates the space the prim should be in by its position - /// - /// - /// a pointer to the space. This could be a new space or reused space. - internal IntPtr calculateSpaceForGeom(Vector3 pos) - { - int[] xyspace = calculateSpaceArrayItemFromPos(pos); - //m_log.Info("[Physics]: Attempting to use arrayItem: " + xyspace[0].ToString() + "," + xyspace[1].ToString()); - return staticPrimspace[xyspace[0], xyspace[1]]; - } - - /// - /// Holds the space allocation logic - /// - /// - /// an array item based on the position - internal int[] calculateSpaceArrayItemFromPos(Vector3 pos) - { - int[] returnint = new int[2]; - - returnint[0] = (int) (pos.X/metersInSpace); - - if (returnint[0] > ((int) (259f/metersInSpace))) - returnint[0] = ((int) (259f/metersInSpace)); - if (returnint[0] < 0) - returnint[0] = 0; - - returnint[1] = (int) (pos.Y/metersInSpace); - if (returnint[1] > ((int) (259f/metersInSpace))) - returnint[1] = ((int) (259f/metersInSpace)); - if (returnint[1] < 0) - returnint[1] = 0; - - return returnint; - } - - #endregion - - /// - /// Routine to figure out if we need to mesh this prim with our mesher - /// - /// - /// - internal 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... - - // //if (pbs.PathCurve == (byte)Primitive.PathCurve.Circle && pbs.ProfileCurve == (byte)Primitive.ProfileCurve.Circle && pbs.PathScaleY <= 0.75f) - // //m_log.Debug("needsMeshing: " + " pathCurve: " + pbs.PathCurve.ToString() + " profileCurve: " + pbs.ProfileCurve.ToString() + " pathScaleY: " + Primitive.UnpackPathScale(pbs.PathScaleY).ToString()); - int iPropertiesNotSupportedDefault = 0; - - if (pbs.SculptEntry && !meshSculptedPrim) - { -#if SPAM - m_log.Warn("NonMesh"); -#endif - return false; - } - - // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim - if (!forceSimplePrimMeshing && !pbs.SculptEntry) - { - 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) - { -#if SPAM - m_log.Warn("NonMesh"); -#endif - return false; - } - } - } - - 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 (pbs.SculptEntry && meshSculptedPrim) - iPropertiesNotSupportedDefault++; - - if (iPropertiesNotSupportedDefault == 0) - { -#if SPAM - m_log.Warn("NonMesh"); -#endif - return false; - } -#if SPAM - m_log.Debug("Mesh"); -#endif - return true; - } - - /// - /// Called after our prim properties are set Scale, position etc. - /// - /// - /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex - /// This assures us that we have no race conditions - /// - /// - public override void AddPhysicsActorTaint(PhysicsActor actor) - { - if (actor is OdePrim) - { - OdePrim taintedprim = ((OdePrim)actor); - lock (_taintedPrims) - _taintedPrims.Add(taintedprim); - } - else if (actor is OdeCharacter) - { - OdeCharacter taintedchar = ((OdeCharacter)actor); - lock (_taintedActors) - { - _taintedActors.Add(taintedchar); - if (taintedchar.bad) - m_log.ErrorFormat("[ODE SCENE]: Added BAD actor {0} to tainted actors", taintedchar.m_uuid); - } - } - } - - /// - /// This is our main simulate loop - /// - /// - /// It's thread locked by a Mutex in the scene. - /// It holds Collisions, it instructs ODE to step through the physical reactions - /// It moves the objects around in memory - /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup) - /// - /// - /// The number of frames simulated over that period. - public override float Simulate(float timeStep) - { - if (!_worldInitialized) return 11f; - - int startFrameTick = CollectStats ? Util.EnvironmentTickCount() : 0; - int tempTick = 0, tempTick2 = 0; - - if (framecount >= int.MaxValue) - framecount = 0; - - framecount++; - - float fps = 0; - - float timeLeft = timeStep; - - //m_log.Info(timeStep.ToString()); -// step_time += timeSte -// -// // If We're loaded down by something else, -// // or debugging with the Visual Studio project on pause -// // skip a few frames to catch up gracefully. -// // without shooting the physicsactors all over the place -// -// if (step_time >= m_SkipFramesAtms) -// { -// // Instead of trying to catch up, it'll do 5 physics frames only -// step_time = ODE_STEPSIZE; -// m_physicsiterations = 5; -// } -// else -// { -// m_physicsiterations = 10; -// } - - // We change _collisionEventPrimChanges to avoid locking _collisionEventPrim itself and causing potential - // deadlock if the collision event tries to lock something else later on which is already locked by a - // caller that is adding or removing the collision event. - lock (m_collisionEventActorsChanges) - { - foreach (KeyValuePair kvp in m_collisionEventActorsChanges) - { - if (kvp.Value == null) - m_collisionEventActors.Remove(kvp.Key); - else - m_collisionEventActors[kvp.Key] = kvp.Value; - } - - m_collisionEventActorsChanges.Clear(); - } - - if (SupportsNINJAJoints) - { - DeleteRequestedJoints(); // this must be outside of the lock (OdeLock) to avoid deadlocks - CreateRequestedJoints(); // this must be outside of the lock (OdeLock) to avoid deadlocks - } - - lock (OdeLock) - { - // Process 10 frames if the sim is running normal.. - // process 5 frames if the sim is running slow - //try - //{ - //d.WorldSetQuickStepNumIterations(world, m_physicsiterations); - //} - //catch (StackOverflowException) - //{ - // m_log.Error("[PHYSICS]: The operating system wasn't able to allocate enough memory for the simulation. Restarting the sim."); - // ode.drelease(world); - //base.TriggerPhysicsBasedRestart(); - //} - - // Figure out the Frames Per Second we're going at. - //(step_time == 0.004f, there's 250 of those per second. Times the step time/step size - - fps = (timeStep / ODE_STEPSIZE) * 1000; - // HACK: Using a time dilation of 1.0 to debug rubberbanding issues - //m_timeDilation = Math.Min((step_time / ODE_STEPSIZE) / (0.09375f / ODE_STEPSIZE), 1.0f); - - while (timeLeft > 0.0f) - { - try - { - if (CollectStats) - tempTick = Util.EnvironmentTickCount(); - - lock (_taintedActors) - { - foreach (OdeCharacter character in _taintedActors) - character.ProcessTaints(); - - _taintedActors.Clear(); - } - - if (CollectStats) - { - tempTick2 = Util.EnvironmentTickCount(); - m_stats[ODEAvatarTaintMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick); - tempTick = tempTick2; - } - - lock (_taintedPrims) - { - foreach (OdePrim prim in _taintedPrims) - { - if (prim.m_taintremove) - { -// Console.WriteLine("Simulate calls RemovePrimThreadLocked for {0}", prim.Name); - RemovePrimThreadLocked(prim); - } - else - { -// Console.WriteLine("Simulate calls ProcessTaints for {0}", prim.Name); - prim.ProcessTaints(); - } - - prim.m_collisionscore = 0; - - // This loop can block up the Heartbeat for a very long time on large regions. - // We need to let the Watchdog know that the Heartbeat is not dead - // NOTE: This is currently commented out, but if things like OAR loading are - // timing the heartbeat out we will need to uncomment it - //Watchdog.UpdateThread(); - } - - if (SupportsNINJAJoints) - SimulatePendingNINJAJoints(); - - _taintedPrims.Clear(); - } - - if (CollectStats) - { - tempTick2 = Util.EnvironmentTickCount(); - m_stats[ODEPrimTaintMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick); - tempTick = tempTick2; - } - - // Move characters - foreach (OdeCharacter actor in _characters) - actor.Move(defects); - - if (defects.Count != 0) - { - foreach (OdeCharacter actor in defects) - { - m_log.ErrorFormat( - "[ODE SCENE]: Removing physics character {0} {1} from physics scene {2} due to defect found when moving", - actor.Name, actor.LocalID, Name); - - RemoveCharacter(actor); - actor.DestroyOdeStructures(); - } - - defects.Clear(); - } - - if (CollectStats) - { - tempTick2 = Util.EnvironmentTickCount(); - m_stats[ODEAvatarForcesFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick); - tempTick = tempTick2; - } - - // Move other active objects - foreach (OdePrim prim in _activeprims) - { - prim.m_collisionscore = 0; - prim.Move(timeStep); - } - - if (CollectStats) - { - tempTick2 = Util.EnvironmentTickCount(); - m_stats[ODEPrimForcesFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick); - tempTick = tempTick2; - } - - //if ((framecount % m_randomizeWater) == 0) - // randomizeWater(waterlevel); - - //int RayCastTimeMS = m_rayCastManager.ProcessQueuedRequests(); - m_rayCastManager.ProcessQueuedRequests(); - - if (CollectStats) - { - tempTick2 = Util.EnvironmentTickCount(); - m_stats[ODERaycastingFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick); - tempTick = tempTick2; - } - - collision_optimized(); - - if (CollectStats) - { - tempTick2 = Util.EnvironmentTickCount(); - m_stats[ODEOtherCollisionFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick); - tempTick = tempTick2; - } - - foreach (PhysicsActor obj in m_collisionEventActors.Values) - { -// m_log.DebugFormat("[PHYSICS]: Assessing {0} {1} for collision events", obj.SOPName, obj.LocalID); - - switch ((ActorTypes)obj.PhysicsActorType) - { - case ActorTypes.Agent: - OdeCharacter cobj = (OdeCharacter)obj; - cobj.AddCollisionFrameTime(100); - cobj.SendCollisions(); - break; - - case ActorTypes.Prim: - OdePrim pobj = (OdePrim)obj; - pobj.SendCollisions(); - break; - } - } - -// if (m_global_contactcount > 0) -// m_log.DebugFormat( -// "[PHYSICS]: Collision contacts to process this frame = {0}", m_global_contactcount); - - m_global_contactcount = 0; - - if (CollectStats) - { - tempTick2 = Util.EnvironmentTickCount(); - m_stats[ODECollisionNotificationFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick); - tempTick = tempTick2; - } - - d.WorldQuickStep(world, ODE_STEPSIZE); - - if (CollectStats) - m_stats[ODENativeStepFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick); - - d.JointGroupEmpty(contactgroup); - } - catch (Exception e) - { - m_log.ErrorFormat("[ODE SCENE]: {0}, {1}, {2}", e.Message, e.TargetSite, e); - } - - timeLeft -= ODE_STEPSIZE; - } - - if (CollectStats) - tempTick = Util.EnvironmentTickCount(); - - foreach (OdeCharacter actor in _characters) - { - if (actor.bad) - m_log.ErrorFormat("[ODE SCENE]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid); - - actor.UpdatePositionAndVelocity(defects); - } - - if (defects.Count != 0) - { - foreach (OdeCharacter actor in defects) - { - m_log.ErrorFormat( - "[ODE SCENE]: Removing physics character {0} {1} from physics scene {2} due to defect found when updating position and velocity", - actor.Name, actor.LocalID, Name); - - RemoveCharacter(actor); - actor.DestroyOdeStructures(); - } - - defects.Clear(); - } - - if (CollectStats) - { - tempTick2 = Util.EnvironmentTickCount(); - m_stats[ODEAvatarUpdateFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick); - tempTick = tempTick2; - } - - //if (timeStep < 0.2f) - - foreach (OdePrim prim in _activeprims) - { - if (prim.IsPhysical && (d.BodyIsEnabled(prim.Body) || !prim._zeroFlag)) - { - prim.UpdatePositionAndVelocity(); - - if (SupportsNINJAJoints) - SimulateActorPendingJoints(prim); - } - } - - if (CollectStats) - m_stats[ODEPrimUpdateFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick); - - //DumpJointInfo(); - - // Finished with all sim stepping. If requested, dump world state to file for debugging. - // TODO: This call to the export function is already inside lock (OdeLock) - but is an extra lock needed? - // TODO: This overwrites all dump files in-place. Should this be a growing logfile, or separate snapshots? - if (physics_logging && (physics_logging_interval > 0) && (framecount % physics_logging_interval == 0)) - { - string fname = "state-" + world.ToString() + ".DIF"; // give each physics world a separate filename - string prefix = "world" + world.ToString(); // prefix for variable names in exported .DIF file - - if (physics_logging_append_existing_logfile) - { - string header = "-------------- START OF PHYSICS FRAME " + framecount.ToString() + " --------------"; - TextWriter fwriter = File.AppendText(fname); - fwriter.WriteLine(header); - fwriter.Close(); - } - - d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix); - } - - latertickcount = Util.EnvironmentTickCountSubtract(tickCountFrameRun); - - // OpenSimulator above does 10 fps. 10 fps = means that the main thread loop and physics - // has a max of 100 ms to run theoretically. - // If the main loop stalls, it calls Simulate later which makes the tick count ms larger. - // If Physics stalls, it takes longer which makes the tick count ms larger. - - if (latertickcount < 100) - { - m_timeDilation = 1.0f; - } - else - { - m_timeDilation = 100f / latertickcount; - //m_timeDilation = Math.Min((Math.Max(100 - (Util.EnvironmentTickCount() - tickCountFrameRun), 1) / 100f), 1.0f); - } - - tickCountFrameRun = Util.EnvironmentTickCount(); - - if (CollectStats) - m_stats[ODETotalFrameMsStatName] += Util.EnvironmentTickCountSubtract(startFrameTick); - } - - return fps; - } - - /// - /// Simulate pending NINJA joints. - /// - /// - /// Called by the main Simulate() loop if NINJA joints are active. Should not be called from anywhere else. - /// - private void SimulatePendingNINJAJoints() - { - // Create pending joints, if possible - - // joints can only be processed after ALL bodies are processed (and exist in ODE), since creating - // a joint requires specifying the body id of both involved bodies - if (pendingJoints.Count > 0) - { - List successfullyProcessedPendingJoints = new List(); - //DoJointErrorMessage(joints_connecting_actor, "taint: " + pendingJoints.Count + " pending joints"); - foreach (PhysicsJoint joint in pendingJoints) - { - //DoJointErrorMessage(joint, "taint: time to create joint with parms: " + joint.RawParams); - string[] jointParams = joint.RawParams.Split(" ".ToCharArray(), System.StringSplitOptions.RemoveEmptyEntries); - List jointBodies = new List(); - bool allJointBodiesAreReady = true; - foreach (string jointParam in jointParams) - { - if (jointParam == "NULL") - { - //DoJointErrorMessage(joint, "attaching NULL joint to world"); - jointBodies.Add(IntPtr.Zero); - } - else - { - //DoJointErrorMessage(joint, "looking for prim name: " + jointParam); - bool foundPrim = false; - lock (_prims) - { - foreach (OdePrim prim in _prims) // FIXME: inefficient - { - if (prim.SOPName == jointParam) - { - //DoJointErrorMessage(joint, "found for prim name: " + jointParam); - if (prim.IsPhysical && prim.Body != IntPtr.Zero) - { - jointBodies.Add(prim.Body); - foundPrim = true; - break; - } - else - { - DoJointErrorMessage(joint, "prim name " + jointParam + - " exists but is not (yet) physical; deferring joint creation. " + - "IsPhysical property is " + prim.IsPhysical + - " and body is " + prim.Body); - foundPrim = false; - break; - } - } - } - } - if (foundPrim) - { - // all is fine - } - else - { - allJointBodiesAreReady = false; - break; - } - } - } - - if (allJointBodiesAreReady) - { - //DoJointErrorMessage(joint, "allJointBodiesAreReady for " + joint.ObjectNameInScene + " with parms " + joint.RawParams); - if (jointBodies[0] == jointBodies[1]) - { - DoJointErrorMessage(joint, "ERROR: joint cannot be created; the joint bodies are the same, body1==body2. Raw body is " + jointBodies[0] + ". raw parms: " + joint.RawParams); - } - else - { - switch (joint.Type) - { - case PhysicsJointType.Ball: - { - IntPtr odeJoint; - //DoJointErrorMessage(joint, "ODE creating ball joint "); - odeJoint = d.JointCreateBall(world, IntPtr.Zero); - //DoJointErrorMessage(joint, "ODE attaching ball joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]); - d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]); - //DoJointErrorMessage(joint, "ODE setting ball anchor: " + odeJoint + " to vec:" + joint.Position); - d.JointSetBallAnchor(odeJoint, - joint.Position.X, - joint.Position.Y, - joint.Position.Z); - //DoJointErrorMessage(joint, "ODE joint setting OK"); - //DoJointErrorMessage(joint, "The ball joint's bodies are here: b0: "); - //DoJointErrorMessage(joint, "" + (jointBodies[0] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[0]) : "fixed environment")); - //DoJointErrorMessage(joint, "The ball joint's bodies are here: b1: "); - //DoJointErrorMessage(joint, "" + (jointBodies[1] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[1]) : "fixed environment")); - - if (joint is OdePhysicsJoint) - { - ((OdePhysicsJoint)joint).jointID = odeJoint; - } - else - { - DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!"); - } - } - break; - case PhysicsJointType.Hinge: - { - IntPtr odeJoint; - //DoJointErrorMessage(joint, "ODE creating hinge joint "); - odeJoint = d.JointCreateHinge(world, IntPtr.Zero); - //DoJointErrorMessage(joint, "ODE attaching hinge joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]); - d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]); - //DoJointErrorMessage(joint, "ODE setting hinge anchor: " + odeJoint + " to vec:" + joint.Position); - d.JointSetHingeAnchor(odeJoint, - joint.Position.X, - joint.Position.Y, - joint.Position.Z); - // We use the orientation of the x-axis of the joint's coordinate frame - // as the axis for the hinge. - - // Therefore, we must get the joint's coordinate frame based on the - // joint.Rotation field, which originates from the orientation of the - // joint's proxy object in the scene. - - // The joint's coordinate frame is defined as the transformation matrix - // that converts a vector from joint-local coordinates into world coordinates. - // World coordinates are defined as the XYZ coordinate system of the sim, - // as shown in the top status-bar of the viewer. - - // Once we have the joint's coordinate frame, we extract its X axis (AtAxis) - // and use that as the hinge axis. - - //joint.Rotation.Normalize(); - Matrix4 proxyFrame = Matrix4.CreateFromQuaternion(joint.Rotation); - - // Now extract the X axis of the joint's coordinate frame. - - // Do not try to use proxyFrame.AtAxis or you will become mired in the - // tar pit of transposed, inverted, and generally messed-up orientations. - // (In other words, Matrix4.AtAxis() is borked.) - // Vector3 jointAxis = proxyFrame.AtAxis; <--- this path leadeth to madness - - // Instead, compute the X axis of the coordinate frame by transforming - // the (1,0,0) vector. At least that works. - - //m_log.Debug("PHY: making axis: complete matrix is " + proxyFrame); - Vector3 jointAxis = Vector3.Transform(Vector3.UnitX, proxyFrame); - //m_log.Debug("PHY: making axis: hinge joint axis is " + jointAxis); - //DoJointErrorMessage(joint, "ODE setting hinge axis: " + odeJoint + " to vec:" + jointAxis); - d.JointSetHingeAxis(odeJoint, - jointAxis.X, - jointAxis.Y, - jointAxis.Z); - //d.JointSetHingeParam(odeJoint, (int)dParam.CFM, 0.1f); - if (joint is OdePhysicsJoint) - { - ((OdePhysicsJoint)joint).jointID = odeJoint; - } - else - { - DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!"); - } - } - break; - } - successfullyProcessedPendingJoints.Add(joint); - } - } - else - { - DoJointErrorMessage(joint, "joint could not yet be created; still pending"); - } - } - - foreach (PhysicsJoint successfullyProcessedJoint in successfullyProcessedPendingJoints) - { - //DoJointErrorMessage(successfullyProcessedJoint, "finalizing succesfully procsssed joint " + successfullyProcessedJoint.ObjectNameInScene + " parms " + successfullyProcessedJoint.RawParams); - //DoJointErrorMessage(successfullyProcessedJoint, "removing from pending"); - InternalRemovePendingJoint(successfullyProcessedJoint); - //DoJointErrorMessage(successfullyProcessedJoint, "adding to active"); - InternalAddActiveJoint(successfullyProcessedJoint); - //DoJointErrorMessage(successfullyProcessedJoint, "done"); - } - } - } - - /// - /// Simulate the joint proxies of a NINJA actor. - /// - /// - /// Called as part of the Simulate() loop if NINJA physics is active. Must only be called from there. - /// - /// - private void SimulateActorPendingJoints(OdePrim actor) - { - // If an actor moved, move its joint proxy objects as well. - // There seems to be an event PhysicsActor.OnPositionUpdate that could be used - // for this purpose but it is never called! So we just do the joint - // movement code here. - - if (actor.SOPName != null && - joints_connecting_actor.ContainsKey(actor.SOPName) && - joints_connecting_actor[actor.SOPName] != null && - joints_connecting_actor[actor.SOPName].Count > 0) - { - foreach (PhysicsJoint affectedJoint in joints_connecting_actor[actor.SOPName]) - { - if (affectedJoint.IsInPhysicsEngine) - { - DoJointMoved(affectedJoint); - } - else - { - DoJointErrorMessage(affectedJoint, "a body connected to a joint was moved, but the joint doesn't exist yet! this will lead to joint error. joint was: " + affectedJoint.ObjectNameInScene + " parms:" + affectedJoint.RawParams); - } - } - } - } - - public override void GetResults() - { - } - - public override bool IsThreaded - { - // for now we won't be multithreaded - get { return false; } - } - - #region ODE Specific Terrain Fixes - private float[] ResizeTerrain512NearestNeighbour(float[] heightMap) - { - float[] returnarr = new float[262144]; - float[,] resultarr = new float[(int)WorldExtents.X, (int)WorldExtents.Y]; - - // Filling out the array into its multi-dimensional components - for (int y = 0; y < WorldExtents.Y; y++) - { - for (int x = 0; x < WorldExtents.X; x++) - { - resultarr[y, x] = heightMap[y * (int)WorldExtents.Y + x]; - } - } - - // Resize using Nearest Neighbour - - // This particular way is quick but it only works on a multiple of the original - - // The idea behind this method can be described with the following diagrams - // second pass and third pass happen in the same loop really.. just separated - // them to show what this does. - - // First Pass - // ResultArr: - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - - // Second Pass - // ResultArr2: - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - - // Third pass fills in the blanks - // ResultArr2: - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - - // X,Y = . - // X+1,y = ^ - // X,Y+1 = * - // X+1,Y+1 = # - - // Filling in like this; - // .* - // ^# - // 1st . - // 2nd * - // 3rd ^ - // 4th # - // on single loop. - - float[,] resultarr2 = new float[512, 512]; - for (int y = 0; y < WorldExtents.Y; y++) - { - for (int x = 0; x < WorldExtents.X; x++) - { - resultarr2[y * 2, x * 2] = resultarr[y, x]; - - if (y < WorldExtents.Y) - { - resultarr2[(y * 2) + 1, x * 2] = resultarr[y, x]; - } - if (x < WorldExtents.X) - { - resultarr2[y * 2, (x * 2) + 1] = resultarr[y, x]; - } - if (x < WorldExtents.X && y < WorldExtents.Y) - { - resultarr2[(y * 2) + 1, (x * 2) + 1] = resultarr[y, x]; - } - } - } - - //Flatten out the array - int i = 0; - for (int y = 0; y < 512; y++) - { - for (int x = 0; x < 512; x++) - { - if (resultarr2[y, x] <= 0) - returnarr[i] = 0.0000001f; - else - returnarr[i] = resultarr2[y, x]; - - i++; - } - } - - return returnarr; - } - - private float[] ResizeTerrain512Interpolation(float[] heightMap) - { - float[] returnarr = new float[262144]; - float[,] resultarr = new float[512,512]; - - // Filling out the array into its multi-dimensional components - for (int y = 0; y < 256; y++) - { - for (int x = 0; x < 256; x++) - { - resultarr[y, x] = heightMap[y * 256 + x]; - } - } - - // Resize using interpolation - - // This particular way is quick but it only works on a multiple of the original - - // The idea behind this method can be described with the following diagrams - // second pass and third pass happen in the same loop really.. just separated - // them to show what this does. - - // First Pass - // ResultArr: - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - - // Second Pass - // ResultArr2: - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - - // Third pass fills in the blanks - // ResultArr2: - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - - // X,Y = . - // X+1,y = ^ - // X,Y+1 = * - // X+1,Y+1 = # - - // Filling in like this; - // .* - // ^# - // 1st . - // 2nd * - // 3rd ^ - // 4th # - // on single loop. - - float[,] resultarr2 = new float[512,512]; - for (int y = 0; y < (int)Constants.RegionSize; y++) - { - for (int x = 0; x < (int)Constants.RegionSize; x++) - { - resultarr2[y*2, x*2] = resultarr[y, x]; - - if (y < (int)Constants.RegionSize) - { - if (y + 1 < (int)Constants.RegionSize) - { - if (x + 1 < (int)Constants.RegionSize) - { - resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x] + - resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4); - } - else - { - resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x])/2); - } - } - else - { - resultarr2[(y*2) + 1, x*2] = resultarr[y, x]; - } - } - if (x < (int)Constants.RegionSize) - { - if (x + 1 < (int)Constants.RegionSize) - { - if (y + 1 < (int)Constants.RegionSize) - { - resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] + - resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4); - } - else - { - resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y, x + 1])/2); - } - } - else - { - resultarr2[y*2, (x*2) + 1] = resultarr[y, x]; - } - } - if (x < (int)Constants.RegionSize && y < (int)Constants.RegionSize) - { - if ((x + 1 < (int)Constants.RegionSize) && (y + 1 < (int)Constants.RegionSize)) - { - resultarr2[(y*2) + 1, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] + - resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4); - } - else - { - resultarr2[(y*2) + 1, (x*2) + 1] = resultarr[y, x]; - } - } - } - } - //Flatten out the array - int i = 0; - for (int y = 0; y < 512; y++) - { - for (int x = 0; x < 512; x++) - { - if (Single.IsNaN(resultarr2[y, x]) || Single.IsInfinity(resultarr2[y, x])) - { - m_log.Warn("[ODE SCENE]: Non finite heightfield element detected. Setting it to 0"); - resultarr2[y, x] = 0; - } - returnarr[i] = resultarr2[y, x]; - i++; - } - } - - return returnarr; - } - - #endregion - - public override void SetTerrain(float[] heightMap) - { - if (m_worldOffset != Vector3.Zero && m_parentScene != null) - { - if (m_parentScene is OdeScene) - { - ((OdeScene)m_parentScene).SetTerrain(heightMap, m_worldOffset); - } - } - else - { - SetTerrain(heightMap, m_worldOffset); - } - } - - private void SetTerrain(float[] heightMap, Vector3 pOffset) - { - int startTime = Util.EnvironmentTickCount(); - m_log.DebugFormat("[ODE SCENE]: Setting terrain for {0} with offset {1}", Name, pOffset); - - // this._heightmap[i] = (double)heightMap[i]; - // dbm (danx0r) -- creating a buffer zone of one extra sample all around - //_origheightmap = heightMap; - - float[] _heightmap; - - // zero out a heightmap array float array (single dimension [flattened])) - //if ((int)Constants.RegionSize == 256) - // _heightmap = new float[514 * 514]; - //else - - _heightmap = new float[(((int)Constants.RegionSize + 2) * ((int)Constants.RegionSize + 2))]; - - uint heightmapWidth = Constants.RegionSize + 1; - uint heightmapHeight = Constants.RegionSize + 1; - - uint heightmapWidthSamples; - - uint heightmapHeightSamples; - - //if (((int)Constants.RegionSize) == 256) - //{ - // heightmapWidthSamples = 2 * (uint)Constants.RegionSize + 2; - // heightmapHeightSamples = 2 * (uint)Constants.RegionSize + 2; - // heightmapWidth++; - // heightmapHeight++; - //} - //else - //{ - - heightmapWidthSamples = (uint)Constants.RegionSize + 1; - heightmapHeightSamples = (uint)Constants.RegionSize + 1; - //} - - const float scale = 1.0f; - const float offset = 0.0f; - const float thickness = 0.2f; - const int wrap = 0; - - int regionsize = (int) Constants.RegionSize + 2; - //Double resolution - //if (((int)Constants.RegionSize) == 256) - // heightMap = ResizeTerrain512Interpolation(heightMap); - - - // if (((int)Constants.RegionSize) == 256 && (int)Constants.RegionSize == 256) - // regionsize = 512; - - float hfmin = 2000; - float hfmax = -2000; - - for (int x = 0; x < heightmapWidthSamples; x++) - { - for (int y = 0; y < heightmapHeightSamples; y++) - { - int xx = Util.Clip(x - 1, 0, regionsize - 1); - int yy = Util.Clip(y - 1, 0, regionsize - 1); - - - float val= heightMap[yy * (int)Constants.RegionSize + xx]; - _heightmap[x * ((int)Constants.RegionSize + 2) + y] = val; - - hfmin = (val < hfmin) ? val : hfmin; - hfmax = (val > hfmax) ? val : hfmax; - } - } - - lock (OdeLock) - { - IntPtr GroundGeom = IntPtr.Zero; - if (RegionTerrain.TryGetValue(pOffset, out GroundGeom)) - { - RegionTerrain.Remove(pOffset); - if (GroundGeom != IntPtr.Zero) - { - if (TerrainHeightFieldHeights.ContainsKey(GroundGeom)) - { - TerrainHeightFieldHeights.Remove(GroundGeom); - } - d.SpaceRemove(space, GroundGeom); - d.GeomDestroy(GroundGeom); - } - - } - IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); - d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0, heightmapWidth + 1, heightmapHeight + 1, - (int)heightmapWidthSamples + 1, (int)heightmapHeightSamples + 1, scale, - offset, thickness, wrap); - d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1); - GroundGeom = d.CreateHeightfield(space, HeightmapData, 1); - if (GroundGeom != IntPtr.Zero) - { - d.GeomSetCategoryBits(GroundGeom, (int)(CollisionCategories.Land)); - d.GeomSetCollideBits(GroundGeom, (int)(CollisionCategories.Space)); - - } - geom_name_map[GroundGeom] = "Terrain"; - - d.Matrix3 R = new d.Matrix3(); - - Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f); - Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f); - //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1)); - - q1 = q1 * q2; - //q1 = q1 * q3; - Vector3 v3; - float angle; - q1.GetAxisAngle(out v3, out angle); - - d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle); - d.GeomSetRotation(GroundGeom, ref R); - d.GeomSetPosition(GroundGeom, (pOffset.X + ((int)Constants.RegionSize * 0.5f)), (pOffset.Y + ((int)Constants.RegionSize * 0.5f)), 0); - IntPtr testGround = IntPtr.Zero; - if (RegionTerrain.TryGetValue(pOffset, out testGround)) - { - RegionTerrain.Remove(pOffset); - } - RegionTerrain.Add(pOffset, GroundGeom, GroundGeom); - TerrainHeightFieldHeights.Add(GroundGeom,_heightmap); - } - - m_log.DebugFormat( - "[ODE SCENE]: Setting terrain for {0} took {1}ms", Name, Util.EnvironmentTickCountSubtract(startTime)); - } - - public override void DeleteTerrain() - { - } - - internal float GetWaterLevel() - { - return waterlevel; - } - - public override bool SupportsCombining() - { - return true; - } - -// public override void UnCombine(PhysicsScene pScene) -// { -// IntPtr localGround = IntPtr.Zero; -//// float[] localHeightfield; -// bool proceed = false; -// List geomDestroyList = new List(); -// -// lock (OdeLock) -// { -// if (RegionTerrain.TryGetValue(Vector3.Zero, out localGround)) -// { -// foreach (IntPtr geom in TerrainHeightFieldHeights.Keys) -// { -// if (geom == localGround) -// { -//// localHeightfield = TerrainHeightFieldHeights[geom]; -// proceed = true; -// } -// else -// { -// geomDestroyList.Add(geom); -// } -// } -// -// if (proceed) -// { -// m_worldOffset = Vector3.Zero; -// WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize); -// m_parentScene = null; -// -// foreach (IntPtr g in geomDestroyList) -// { -// // removingHeightField needs to be done or the garbage collector will -// // collect the terrain data before we tell ODE to destroy it causing -// // memory corruption -// if (TerrainHeightFieldHeights.ContainsKey(g)) -// { -//// float[] removingHeightField = TerrainHeightFieldHeights[g]; -// TerrainHeightFieldHeights.Remove(g); -// -// if (RegionTerrain.ContainsKey(g)) -// { -// RegionTerrain.Remove(g); -// } -// -// d.GeomDestroy(g); -// //removingHeightField = new float[0]; -// } -// } -// -// } -// else -// { -// m_log.Warn("[PHYSICS]: Couldn't proceed with UnCombine. Region has inconsistant data."); -// } -// } -// } -// } - - public override void SetWaterLevel(float baseheight) - { - waterlevel = baseheight; - randomizeWater(waterlevel); - } - - private void randomizeWater(float baseheight) - { - const uint heightmapWidth = m_regionWidth + 2; - const uint heightmapHeight = m_regionHeight + 2; - const uint heightmapWidthSamples = m_regionWidth + 2; - const uint heightmapHeightSamples = m_regionHeight + 2; - const float scale = 1.0f; - const float offset = 0.0f; - const float thickness = 2.9f; - const int wrap = 0; - - for (int i = 0; i < (258 * 258); i++) - { - _watermap[i] = (baseheight-0.1f) + ((float)fluidRandomizer.Next(1,9) / 10f); - // m_log.Info((baseheight - 0.1f) + ((float)fluidRandomizer.Next(1, 9) / 10f)); - } - - lock (OdeLock) - { - if (WaterGeom != IntPtr.Zero) - { - d.SpaceRemove(space, WaterGeom); - } - IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); - d.GeomHeightfieldDataBuildSingle(HeightmapData, _watermap, 0, heightmapWidth, heightmapHeight, - (int)heightmapWidthSamples, (int)heightmapHeightSamples, scale, - offset, thickness, wrap); - d.GeomHeightfieldDataSetBounds(HeightmapData, m_regionWidth, m_regionHeight); - WaterGeom = d.CreateHeightfield(space, HeightmapData, 1); - if (WaterGeom != IntPtr.Zero) - { - d.GeomSetCategoryBits(WaterGeom, (int)(CollisionCategories.Water)); - d.GeomSetCollideBits(WaterGeom, (int)(CollisionCategories.Space)); - } - - geom_name_map[WaterGeom] = "Water"; - - d.Matrix3 R = new d.Matrix3(); - - Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f); - Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f); - //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1)); - - q1 = q1 * q2; - //q1 = q1 * q3; - Vector3 v3; - float angle; - q1.GetAxisAngle(out v3, out angle); - - d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle); - d.GeomSetRotation(WaterGeom, ref R); - d.GeomSetPosition(WaterGeom, 128, 128, 0); - } - } - - public override void Dispose() - { - _worldInitialized = false; - - m_rayCastManager.Dispose(); - m_rayCastManager = null; - - lock (OdeLock) - { - lock (_prims) - { - foreach (OdePrim prm in _prims) - { - RemovePrim(prm); - } - } - - //foreach (OdeCharacter act in _characters) - //{ - //RemoveAvatar(act); - //} - d.WorldDestroy(world); - //d.CloseODE(); - } - - } - - public override Dictionary GetTopColliders() - { - Dictionary topColliders; - - lock (_prims) - { - List orderedPrims = new List(_prims); - orderedPrims.OrderByDescending(p => p.CollisionScore).Take(25); - topColliders = orderedPrims.ToDictionary(p => p.LocalID, p => p.CollisionScore); - - foreach (OdePrim p in _prims) - p.CollisionScore = 0; - } - - return topColliders; - } - - public override bool SupportsRayCast() - { - return true; - } - - public override void RaycastWorld(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod) - { - if (retMethod != null) - { - m_rayCastManager.QueueRequest(position, direction, length, retMethod); - } - } - - public override void RaycastWorld(Vector3 position, Vector3 direction, float length, int Count, RayCallback retMethod) - { - if (retMethod != null) - { - m_rayCastManager.QueueRequest(position, direction, length, Count, retMethod); - } - } - - public override List RaycastWorld(Vector3 position, Vector3 direction, float length, int Count) - { - ContactResult[] ourResults = null; - RayCallback retMethod = delegate(List results) - { - ourResults = new ContactResult[results.Count]; - results.CopyTo(ourResults, 0); - }; - int waitTime = 0; - m_rayCastManager.QueueRequest(position, direction, length, Count, retMethod); - while (ourResults == null && waitTime < 1000) - { - Thread.Sleep(1); - waitTime++; - } - if (ourResults == null) - return new List (); - return new List(ourResults); - } - -#if USE_DRAWSTUFF - // Keyboard callback - public void command(int cmd) - { - IntPtr geom; - d.Mass mass; - d.Vector3 sides = new d.Vector3(d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f); - - - - Char ch = Char.ToLower((Char)cmd); - switch ((Char)ch) - { - case 'w': - try - { - Vector3 rotate = (new Vector3(1, 0, 0) * Quaternion.CreateFromEulers(hpr.Z * Utils.DEG_TO_RAD, hpr.Y * Utils.DEG_TO_RAD, hpr.X * Utils.DEG_TO_RAD)); - - xyz.X += rotate.X; xyz.Y += rotate.Y; xyz.Z += rotate.Z; - ds.SetViewpoint(ref xyz, ref hpr); - } - catch (ArgumentException) - { hpr.X = 0; } - break; - - case 'a': - hpr.X++; - ds.SetViewpoint(ref xyz, ref hpr); - break; - - case 's': - try - { - Vector3 rotate2 = (new Vector3(-1, 0, 0) * Quaternion.CreateFromEulers(hpr.Z * Utils.DEG_TO_RAD, hpr.Y * Utils.DEG_TO_RAD, hpr.X * Utils.DEG_TO_RAD)); - - xyz.X += rotate2.X; xyz.Y += rotate2.Y; xyz.Z += rotate2.Z; - ds.SetViewpoint(ref xyz, ref hpr); - } - catch (ArgumentException) - { hpr.X = 0; } - break; - case 'd': - hpr.X--; - ds.SetViewpoint(ref xyz, ref hpr); - break; - case 'r': - xyz.Z++; - ds.SetViewpoint(ref xyz, ref hpr); - break; - case 'f': - xyz.Z--; - ds.SetViewpoint(ref xyz, ref hpr); - break; - case 'e': - xyz.Y++; - ds.SetViewpoint(ref xyz, ref hpr); - break; - case 'q': - xyz.Y--; - ds.SetViewpoint(ref xyz, ref hpr); - break; - } - } - - public void step(int pause) - { - - ds.SetColor(1.0f, 1.0f, 0.0f); - ds.SetTexture(ds.Texture.Wood); - lock (_prims) - { - foreach (OdePrim prm in _prims) - { - //IntPtr body = d.GeomGetBody(prm.prim_geom); - if (prm.prim_geom != IntPtr.Zero) - { - d.Vector3 pos; - d.GeomCopyPosition(prm.prim_geom, out pos); - //d.BodyCopyPosition(body, out pos); - - d.Matrix3 R; - d.GeomCopyRotation(prm.prim_geom, out R); - //d.BodyCopyRotation(body, out R); - - - d.Vector3 sides = new d.Vector3(); - sides.X = prm.Size.X; - sides.Y = prm.Size.Y; - sides.Z = prm.Size.Z; - - ds.DrawBox(ref pos, ref R, ref sides); - } - } - } - ds.SetColor(1.0f, 0.0f, 0.0f); - - foreach (OdeCharacter chr in _characters) - { - if (chr.Shell != IntPtr.Zero) - { - IntPtr body = d.GeomGetBody(chr.Shell); - - d.Vector3 pos; - d.GeomCopyPosition(chr.Shell, out pos); - //d.BodyCopyPosition(body, out pos); - - d.Matrix3 R; - d.GeomCopyRotation(chr.Shell, out R); - //d.BodyCopyRotation(body, out R); - - ds.DrawCapsule(ref pos, ref R, chr.Size.Z, 0.35f); - d.Vector3 sides = new d.Vector3(); - sides.X = 0.5f; - sides.Y = 0.5f; - sides.Z = 0.5f; - - ds.DrawBox(ref pos, ref R, ref sides); - } - } - } - - public void start(int unused) - { - ds.SetViewpoint(ref xyz, ref hpr); - } -#endif - - public override Dictionary GetStats() - { - if (!CollectStats) - return null; - - Dictionary returnStats; - - lock (OdeLock) - { - returnStats = new Dictionary(m_stats); - - // FIXME: This is a SUPER DUMB HACK until we can establish stats that aren't subject to a division by - // 3 from the SimStatsReporter. - returnStats[ODETotalAvatarsStatName] = _characters.Count * 3; - returnStats[ODETotalPrimsStatName] = _prims.Count * 3; - returnStats[ODEActivePrimsStatName] = _activeprims.Count * 3; - - InitializeExtraStats(); - } - - returnStats[ODEOtherCollisionFrameMsStatName] - = returnStats[ODEOtherCollisionFrameMsStatName] - - returnStats[ODENativeSpaceCollisionFrameMsStatName] - - returnStats[ODENativeGeomCollisionFrameMsStatName]; - - return returnStats; - } - - private void InitializeExtraStats() - { - m_stats[ODETotalFrameMsStatName] = 0; - m_stats[ODEAvatarTaintMsStatName] = 0; - m_stats[ODEPrimTaintMsStatName] = 0; - m_stats[ODEAvatarForcesFrameMsStatName] = 0; - m_stats[ODEPrimForcesFrameMsStatName] = 0; - m_stats[ODERaycastingFrameMsStatName] = 0; - m_stats[ODENativeStepFrameMsStatName] = 0; - m_stats[ODENativeSpaceCollisionFrameMsStatName] = 0; - m_stats[ODENativeGeomCollisionFrameMsStatName] = 0; - m_stats[ODEOtherCollisionFrameMsStatName] = 0; - m_stats[ODECollisionNotificationFrameMsStatName] = 0; - m_stats[ODEAvatarContactsStatsName] = 0; - m_stats[ODEPrimContactsStatName] = 0; - m_stats[ODEAvatarUpdateFrameMsStatName] = 0; - m_stats[ODEPrimUpdateFrameMsStatName] = 0; - } - } -} diff --git a/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs b/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs deleted file mode 100644 index 16404c6..0000000 --- a/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; -using OpenSim.Region.Physics.OdePlugin; -using OpenSim.Tests.Common; -using log4net; -using System.Reflection; - -namespace OpenSim.Region.Physics.OdePlugin.Tests -{ - [TestFixture] - public class ODETestClass : OpenSimTestCase - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private OpenSim.Region.Physics.OdePlugin.OdePlugin cbt; - private PhysicsScene ps; - private IMeshingPlugin imp; - - [SetUp] - public void Initialize() - { - IConfigSource TopConfig = new IniConfigSource(); - IConfig config = TopConfig.AddConfig("Startup"); - config.Set("DecodedSculptMapPath","j2kDecodeCache"); - - // Loading ODEPlugin - cbt = new OdePlugin(); - // Loading Zero Mesher - imp = new ZeroMesherPlugin(); - // Getting Physics Scene - ps = cbt.GetScene("test"); - // Initializing Physics Scene. - ps.Initialise(imp.GetMesher(TopConfig),null); - float[] _heightmap = new float[(int)Constants.RegionSize * (int)Constants.RegionSize]; - for (int i = 0; i < ((int)Constants.RegionSize * (int)Constants.RegionSize); i++) - { - _heightmap[i] = 21f; - } - ps.SetTerrain(_heightmap); - } - - [TearDown] - public void Terminate() - { - ps.DeleteTerrain(); - ps.Dispose(); - - } - - [Test] - public void CreateAndDropPhysicalCube() - { - PrimitiveBaseShape newcube = PrimitiveBaseShape.CreateBox(); - Vector3 position = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 128f); - Vector3 size = new Vector3(0.5f, 0.5f, 0.5f); - Quaternion rot = Quaternion.Identity; - PhysicsActor prim = ps.AddPrimShape("CoolShape", newcube, position, size, rot, true, 0); - OdePrim oprim = (OdePrim)prim; - OdeScene pscene = (OdeScene) ps; - - Assert.That(oprim.m_taintadd); - - prim.LocalID = 5; - - for (int i = 0; i < 58; i++) - { - ps.Simulate(0.133f); - - Assert.That(oprim.prim_geom != (IntPtr)0); - - Assert.That(oprim.m_targetSpace != (IntPtr)0); - - //Assert.That(oprim.m_targetSpace == pscene.space); - m_log.Info("TargetSpace: " + oprim.m_targetSpace + " - SceneMainSpace: " + pscene.space); - - Assert.That(!oprim.m_taintadd); - m_log.Info("Prim Position (" + oprim.LocalID + "): " + prim.Position); - - // Make sure we're above the ground - //Assert.That(prim.Position.Z > 20f); - //m_log.Info("PrimCollisionScore (" + oprim.m_localID + "): " + oprim.m_collisionscore); - - // Make sure we've got a Body - Assert.That(oprim.Body != (IntPtr)0); - //m_log.Info( - } - - // Make sure we're not somewhere above the ground - Assert.That(prim.Position.Z < 21.5f); - - ps.RemovePrim(prim); - Assert.That(oprim.m_taintremove); - ps.Simulate(0.133f); - Assert.That(oprim.Body == (IntPtr)0); - } - } -} diff --git a/OpenSim/Region/Physics/OdePlugin/drawstuff.cs b/OpenSim/Region/Physics/OdePlugin/drawstuff.cs deleted file mode 100644 index 87ca446..0000000 --- a/OpenSim/Region/Physics/OdePlugin/drawstuff.cs +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright ODE - * Ode.NET - .NET bindings for ODE - * Jason Perkins (starkos@industriousone.com) - * Licensed under the New BSD - * Part of the OpenDynamicsEngine -Open Dynamics Engine -Copyright (c) 2001-2007, Russell L. Smith. -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 names of ODE's copyright owner 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 Ode.NET; - -namespace Drawstuff.NET -{ -#if dDOUBLE - using dReal = System.Double; -#else - using dReal = System.Single; -#endif - - public static class ds - { - public const int VERSION = 2; - - public enum Texture - { - None, - Wood - } - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void CallbackFunction(int arg); - - [StructLayout(LayoutKind.Sequential)] - public struct Functions - { - public int version; - public CallbackFunction start; - public CallbackFunction step; - public CallbackFunction command; - public CallbackFunction stop; - public string path_to_textures; - } - - [DllImport("drawstuff", EntryPoint = "dsDrawBox")] - public static extern void DrawBox(ref d.Vector3 pos, ref d.Matrix3 R, ref d.Vector3 sides); - - [DllImport("drawstuff", EntryPoint = "dsDrawCapsule")] - public static extern void DrawCapsule(ref d.Vector3 pos, ref d.Matrix3 R, dReal length, dReal radius); - - [DllImport("drawstuff", EntryPoint = "dsDrawConvex")] - public static extern void DrawConvex(ref d.Vector3 pos, ref d.Matrix3 R, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons); - - [DllImport("drawstuff", EntryPoint = "dsSetColor")] - public static extern void SetColor(float red, float green, float blue); - - [DllImport("drawstuff", EntryPoint = "dsSetTexture")] - public static extern void SetTexture(Texture texture); - - [DllImport("drawstuff", EntryPoint = "dsSetViewpoint")] - public static extern void SetViewpoint(ref d.Vector3 xyz, ref d.Vector3 hpr); - - [DllImport("drawstuff", EntryPoint = "dsSimulationLoop")] - public static extern void SimulationLoop(int argc, string[] argv, int window_width, int window_height, ref Functions fn); - } -} diff --git a/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs deleted file mode 100644 index d07df02..0000000 --- a/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Reflection; -using System.Runtime.InteropServices; - -// Information about this assembly is defined by the following -// attributes. -// -// change them to the information which is associated with the assembly -// you compile. - -[assembly : AssemblyTitle("POSPlugin")] -[assembly : AssemblyDescription("")] -[assembly : AssemblyConfiguration("")] -[assembly : AssemblyCompany("http://opensimulator.org")] -[assembly : AssemblyProduct("POSPlugin")] -[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers")] -[assembly : AssemblyTrademark("")] -[assembly : AssemblyCulture("")] - -// This sets the default COM visibility of types in the assembly to invisible. -// If you need to expose a type to COM, use [ComVisible(true)] on that type. - -[assembly : ComVisible(false)] - -// The assembly version has following format : -// -// Major.Minor.Build.Revision -// -// You can specify all values by your own or you can build default build and revision -// numbers with the '*' character (the default): - -[assembly : AssemblyVersion("0.7.5.*")] diff --git a/OpenSim/Region/Physics/POSPlugin/POSCharacter.cs b/OpenSim/Region/Physics/POSPlugin/POSCharacter.cs deleted file mode 100644 index ae534ea..0000000 --- a/OpenSim/Region/Physics/POSPlugin/POSCharacter.cs +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using Nini.Config; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.POSPlugin -{ - public class POSCharacter : PhysicsActor - { - private Vector3 _position; - public Vector3 _velocity; - public Vector3 _target_velocity = Vector3.Zero; - public Vector3 _size = Vector3.Zero; - private Vector3 _acceleration; - private Vector3 m_rotationalVelocity = Vector3.Zero; - private bool flying; - private bool isColliding; - - public POSCharacter() - { - } - - public override int PhysicsActorType - { - get { return (int) ActorTypes.Agent; } - set { return; } - } - - public override Vector3 RotationalVelocity - { - get { return m_rotationalVelocity; } - set { m_rotationalVelocity = value; } - } - - public override bool SetAlwaysRun - { - get { return false; } - set { return; } - } - - public override uint LocalID - { - set { return; } - } - - public override bool Grabbed - { - set { return; } - } - - public override bool Selected - { - set { return; } - } - - public override float Buoyancy - { - get { return 0f; } - set { return; } - } - - public override bool FloatOnWater - { - set { return; } - } - - public override bool IsPhysical - { - get { return false; } - set { return; } - } - - public override bool ThrottleUpdates - { - get { return false; } - set { return; } - } - - public override bool Flying - { - get { return flying; } - set { flying = value; } - } - - public override bool IsColliding - { - get { return isColliding; } - set { isColliding = value; } - } - - public override bool CollidingGround - { - get { return false; } - set { return; } - } - - public override bool CollidingObj - { - get { return false; } - set { return; } - } - - public override bool Stopped - { - get { return false; } - } - - public override Vector3 Position - { - get { return _position; } - set { _position = value; } - } - - public override Vector3 Size - { - get { return _size; } - set - { - _size = value; - _size.Z = _size.Z / 2.0f; - } - } - - public override float Mass - { - get { return 0f; } - } - - public override Vector3 Force - { - get { return Vector3.Zero; } - set { return; } - } - - 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) { } - - public override void SetVolumeDetect(int param) - { - - } - - public override Vector3 CenterOfMass - { - get { return Vector3.Zero; } - } - - public override Vector3 GeometricCenter - { - get { return Vector3.Zero; } - } - - public override PrimitiveBaseShape Shape - { - set { return; } - } - - public override Vector3 Velocity - { - get { return _velocity; } - set { _target_velocity = value; } - } - - public override Vector3 Torque - { - get { return Vector3.Zero; } - set { return; } - } - - public override float CollisionScore - { - get { return 0f; } - set { } - } - - public override Quaternion Orientation - { - get { return Quaternion.Identity; } - set { } - } - - public override Vector3 Acceleration - { - get { return _acceleration; } - set { _acceleration = value; } - } - - public override bool Kinematic - { - get { return true; } - set { } - } - - public override void link(PhysicsActor obj) - { - } - - public override void delink() - { - } - - public override void LockAngularMotion(Vector3 axis) - { - } - - public override void AddForce(Vector3 force, bool pushforce) - { - } - - public override void AddAngularForce(Vector3 force, bool pushforce) - { - } - - public override void SetMomentum(Vector3 momentum) - { - } - - public override void CrossingFailure() - { - } - - public override Vector3 PIDTarget - { - set { return; } - } - - public override bool PIDActive - { - set { return; } - } - - public override float PIDTau - { - set { return; } - } - - public override float PIDHoverHeight - { - set { return; } - } - - public override bool PIDHoverActive - { - set { return; } - } - - public override PIDHoverType PIDHoverType - { - set { return; } - } - - public override float PIDHoverTau - { - set { return; } - } - - 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 SubscribeEvents(int ms) - { - } - - public override void UnSubscribeEvents() - { - } - - public override bool SubscribedEvents() - { - return false; - } - } -} diff --git a/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs b/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs deleted file mode 100644 index e6b42e6..0000000 --- a/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.POSPlugin -{ - /// - /// for now will be a very POS physics engine - /// - public class POSPlugin : IPhysicsPlugin - { - public POSPlugin() - { - } - - public bool Init() - { - return true; - } - - public PhysicsScene GetScene(string sceneIdentifier) - { - return new POSScene(sceneIdentifier); - } - - public string GetName() - { - return ("POS"); - } - - public void Dispose() - { - } - } -} diff --git a/OpenSim/Region/Physics/POSPlugin/POSPrim.cs b/OpenSim/Region/Physics/POSPlugin/POSPrim.cs deleted file mode 100644 index e4fd7eb..0000000 --- a/OpenSim/Region/Physics/POSPlugin/POSPrim.cs +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using Nini.Config; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.POSPlugin -{ - public class POSPrim : PhysicsActor - { - private Vector3 _position; - private Vector3 _velocity; - private Vector3 _acceleration; - private Vector3 _size; - private Vector3 m_rotationalVelocity = Vector3.Zero; - private Quaternion _orientation; - private bool iscolliding; - - public POSPrim() - { - } - - public override int PhysicsActorType - { - get { return (int) ActorTypes.Prim; } - set { return; } - } - - public override Vector3 RotationalVelocity - { - get { return m_rotationalVelocity; } - set { m_rotationalVelocity = value; } - } - - public override bool IsPhysical - { - get { return false; } - set { return; } - } - - public override bool ThrottleUpdates - { - get { return false; } - set { return; } - } - - public override bool IsColliding - { - get { return iscolliding; } - set { iscolliding = value; } - } - - public override bool CollidingGround - { - get { return false; } - set { return; } - } - - public override bool CollidingObj - { - get { return false; } - set { return; } - } - - public override bool Stopped - { - get { return false; } - } - - public override Vector3 Position - { - get { return _position; } - set { _position = value; } - } - - public override Vector3 Size - { - get { return _size; } - set { _size = value; } - } - - public override float Mass - { - get { return 0f; } - } - - public override Vector3 Force - { - get { return Vector3.Zero; } - set { return; } - } - - 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) { } - - public override void SetVolumeDetect(int param) - { - - } - - public override Vector3 CenterOfMass - { - get { return Vector3.Zero; } - } - - public override Vector3 GeometricCenter - { - get { return Vector3.Zero; } - } - - public override PrimitiveBaseShape Shape - { - set { return; } - } - - public override float Buoyancy - { - get { return 0f; } - set { return; } - } - - public override bool FloatOnWater - { - set { return; } - } - - public override Vector3 Velocity - { - get { return _velocity; } - set { _velocity = value; } - } - - public override float CollisionScore - { - get { return 0f; } - set { } - } - - public override Quaternion Orientation - { - get { return _orientation; } - set { _orientation = value; } - } - - public override Vector3 Acceleration - { - get { return _acceleration; } - set { _acceleration = value; } - } - - public override bool Kinematic - { - get { return true; } - set { } - } - - public override void AddForce(Vector3 force, bool pushforce) - { - } - - public override void AddAngularForce(Vector3 force, bool pushforce) - { - } - - public override Vector3 Torque - { - get { return Vector3.Zero; } - set { return; } - } - - public override void SetMomentum(Vector3 momentum) - { - } - - public override bool Flying - { - get { return false; } - set { } - } - - public override bool SetAlwaysRun - { - get { return false; } - set { return; } - } - - public override uint LocalID - { - set { return; } - } - - public override bool Grabbed - { - set { return; } - } - - public override void link(PhysicsActor obj) - { - } - - public override void delink() - { - } - - public override void LockAngularMotion(Vector3 axis) - { - } - - public override bool Selected - { - set { return; } - } - - public override void CrossingFailure() - { - } - - public override Vector3 PIDTarget - { - set { return; } - } - - public override bool PIDActive - { - set { return; } - } - - public override float PIDTau - { - set { return; } - } - - public override float PIDHoverHeight - { - set { return; } - } - - public override bool PIDHoverActive - { - set { return; } - } - - public override PIDHoverType PIDHoverType - { - set { return; } - } - - public override float PIDHoverTau - { - set { return; } - } - - 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 SubscribeEvents(int ms) - { - } - - public override void UnSubscribeEvents() - { - } - - public override bool SubscribedEvents() - { - return false; - } - } -} diff --git a/OpenSim/Region/Physics/POSPlugin/POSScene.cs b/OpenSim/Region/Physics/POSPlugin/POSScene.cs deleted file mode 100644 index 2f24a50..0000000 --- a/OpenSim/Region/Physics/POSPlugin/POSScene.cs +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above 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 OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using Nini.Config; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.POSPlugin -{ - public class POSScene : PhysicsScene - { - private List _characters = new List(); - private List _prims = new List(); - private float[] _heightMap; - private const float gravity = -9.8f; - - //protected internal string sceneIdentifier; - - public POSScene(String _sceneIdentifier) - { - //sceneIdentifier = _sceneIdentifier; - } - - public override void Initialise(IMesher meshmerizer, IConfigSource config) - { - } - - public override void Dispose() - { - } - - public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) - { - POSCharacter act = new POSCharacter(); - act.Position = position; - act.Flying = isFlying; - _characters.Add(act); - return act; - } - - public override void RemovePrim(PhysicsActor prim) - { - POSPrim p = (POSPrim) prim; - if (_prims.Contains(p)) - { - _prims.Remove(p); - } - } - - public override void RemoveAvatar(PhysicsActor character) - { - POSCharacter act = (POSCharacter) character; - if (_characters.Contains(act)) - { - _characters.Remove(act); - } - } - -/* - public override PhysicsActor AddPrim(Vector3 position, Vector3 size, Quaternion rotation) - { - return null; - } -*/ - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, - Vector3 size, Quaternion rotation, bool isPhysical, uint localid) - { - POSPrim prim = new POSPrim(); - prim.Position = position; - prim.Orientation = rotation; - prim.Size = size; - _prims.Add(prim); - return prim; - } - - private bool isColliding(POSCharacter c, POSPrim p) - { - Vector3 rotatedPos = new Vector3(c.Position.X - p.Position.X, c.Position.Y - p.Position.Y, - c.Position.Z - p.Position.Z) * Quaternion.Inverse(p.Orientation); - Vector3 avatarSize = new Vector3(c.Size.X, c.Size.Y, c.Size.Z) * Quaternion.Inverse(p.Orientation); - - return (Math.Abs(rotatedPos.X) < (p.Size.X*0.5 + Math.Abs(avatarSize.X)) && - Math.Abs(rotatedPos.Y) < (p.Size.Y*0.5 + Math.Abs(avatarSize.Y)) && - Math.Abs(rotatedPos.Z) < (p.Size.Z*0.5 + Math.Abs(avatarSize.Z))); - } - - private bool isCollidingWithPrim(POSCharacter c) - { - foreach (POSPrim p in _prims) - { - if (isColliding(c, p)) - { - return true; - } - } - - return false; - } - - public override void AddPhysicsActorTaint(PhysicsActor prim) - { - } - - public override float Simulate(float timeStep) - { - float fps = 0; - for (int i = 0; i < _characters.Count; ++i) - { - fps++; - POSCharacter character = _characters[i]; - - float oldposX = character.Position.X; - float oldposY = character.Position.Y; - float oldposZ = character.Position.Z; - - if (!character.Flying) - { - character._target_velocity.Z += gravity * timeStep; - } - - Vector3 characterPosition = character.Position; - - characterPosition.X += character._target_velocity.X * timeStep; - characterPosition.Y += character._target_velocity.Y * timeStep; - - characterPosition.X = Util.Clamp(character.Position.X, 0.01f, Constants.RegionSize - 0.01f); - characterPosition.Y = Util.Clamp(character.Position.Y, 0.01f, Constants.RegionSize - 0.01f); - - bool forcedZ = false; - - float terrainheight = _heightMap[(int)character.Position.Y * Constants.RegionSize + (int)character.Position.X]; - if (character.Position.Z + (character._target_velocity.Z * timeStep) < terrainheight + 2) - { - characterPosition.Z = terrainheight + character.Size.Z; - forcedZ = true; - } - else - { - characterPosition.Z += character._target_velocity.Z*timeStep; - } - - /// this is it -- the magic you've all been waiting for! Ladies and gentlemen -- - /// Completely Bogus Collision Detection!!! - /// better known as the CBCD algorithm - - if (isCollidingWithPrim(character)) - { - characterPosition.Z = oldposZ; // first try Z axis - if (isCollidingWithPrim(character)) - { - characterPosition.Z = oldposZ + character.Size.Z / 4.4f; // try harder - if (isCollidingWithPrim(character)) - { - characterPosition.Z = oldposZ + character.Size.Z / 2.2f; // try very hard - if (isCollidingWithPrim(character)) - { - characterPosition.X = oldposX; - characterPosition.Y = oldposY; - characterPosition.Z = oldposZ; - - characterPosition.X += character._target_velocity.X * timeStep; - if (isCollidingWithPrim(character)) - { - characterPosition.X = oldposX; - } - - characterPosition.Y += character._target_velocity.Y * timeStep; - if (isCollidingWithPrim(character)) - { - characterPosition.Y = oldposY; - } - } - else - { - forcedZ = true; - } - } - else - { - forcedZ = true; - } - } - else - { - forcedZ = true; - } - } - - characterPosition.X = Util.Clamp(character.Position.X, 0.01f, Constants.RegionSize - 0.01f); - characterPosition.Y = Util.Clamp(character.Position.Y, 0.01f, Constants.RegionSize - 0.01f); - - character.Position = characterPosition; - - character._velocity.X = (character.Position.X - oldposX)/timeStep; - character._velocity.Y = (character.Position.Y - oldposY)/timeStep; - - if (forcedZ) - { - character._velocity.Z = 0; - character._target_velocity.Z = 0; - ((PhysicsActor)character).IsColliding = true; - character.RequestPhysicsterseUpdate(); - } - else - { - ((PhysicsActor)character).IsColliding = false; - character._velocity.Z = (character.Position.Z - oldposZ)/timeStep; - } - } - return fps; - } - - public override void GetResults() - { - } - - public override bool IsThreaded - { - // for now we won't be multithreaded - get { return (false); } - } - - public override void SetTerrain(float[] heightMap) - { - _heightMap = heightMap; - } - - public override void DeleteTerrain() - { - } - - public override void SetWaterLevel(float baseheight) - { - } - - public override Dictionary GetTopColliders() - { - Dictionary returncolliders = new Dictionary(); - return returncolliders; - } - } -} -- cgit v1.1