From cb07ba0d68eeb57bae1cb60f387483ff720cc29d Mon Sep 17 00:00:00 2001 From: Teravus Ovares Date: Sat, 10 Nov 2007 19:13:52 +0000 Subject: * Moves the Meshmerizer to a separate plugin * Experimental. Linux Prebuild needs testing. * One more update after this to remove the ODEMeshing directory.... --- OpenSim/Region/Application/OpenSimMain.cs | 6 +- .../Region/ClientStack/RegionApplicationBase.cs | 7 +- OpenSim/Region/Examples/SimpleApp/Program.cs | 4 +- .../BasicPhysicsPlugin/BasicPhysicsPlugin.cs | 7 +- .../Region/Physics/BulletXPlugin/BulletXPlugin.cs | 145 ++++++-- .../BulletXPlugin/TriangleIndexVertexArray.cs | 161 +++++++++ OpenSim/Region/Physics/Manager/IMesher.cs | 26 ++ .../Region/Physics/Manager/PhysicsPluginManager.cs | 67 +++- OpenSim/Region/Physics/Manager/PhysicsScene.cs | 11 +- OpenSim/Region/Physics/Meshing/Extruder.cs | 83 +++++ OpenSim/Region/Physics/Meshing/HelperTypes.cs | 306 ++++++++++++++++ OpenSim/Region/Physics/Meshing/Mesh.cs | 213 +++++++++++ OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 393 +++++++++++++++++++++ OpenSim/Region/Physics/Meshing/SimpleHull.cs | 363 +++++++++++++++++++ OpenSim/Region/Physics/Meshing/Simplex.cs | 198 +++++++++++ OpenSim/Region/Physics/OdePlugin/OdePlugin.cs | 31 +- OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs | 6 + prebuild.xml | 37 +- 18 files changed, 1996 insertions(+), 68 deletions(-) create mode 100644 OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs create mode 100644 OpenSim/Region/Physics/Manager/IMesher.cs create mode 100644 OpenSim/Region/Physics/Meshing/Extruder.cs create mode 100644 OpenSim/Region/Physics/Meshing/HelperTypes.cs create mode 100644 OpenSim/Region/Physics/Meshing/Mesh.cs create mode 100644 OpenSim/Region/Physics/Meshing/Meshmerizer.cs create mode 100644 OpenSim/Region/Physics/Meshing/SimpleHull.cs create mode 100644 OpenSim/Region/Physics/Meshing/Simplex.cs diff --git a/OpenSim/Region/Application/OpenSimMain.cs b/OpenSim/Region/Application/OpenSimMain.cs index 684a9a8..42f1b94 100644 --- a/OpenSim/Region/Application/OpenSimMain.cs +++ b/OpenSim/Region/Application/OpenSimMain.cs @@ -54,6 +54,7 @@ namespace OpenSim private const string DEFAULT_PRIM_BACKUP_FILENAME = "prim-backup.xml"; public string m_physicsEngine; + public string m_meshEngineName; public string m_scriptEngine; public bool m_sandbox; public bool user_accounts; @@ -210,6 +211,7 @@ namespace OpenSim { m_sandbox = !startupConfig.GetBoolean("gridmode", false); m_physicsEngine = startupConfig.GetString("physics", "basicphysics"); + m_meshEngineName = startupConfig.GetString("meshing", "Meshmerizer"); m_verbose = startupConfig.GetBoolean("verbose", true); m_permissions = startupConfig.GetBoolean("serverside_object_permissions", false); @@ -404,7 +406,7 @@ namespace OpenSim protected override PhysicsScene GetPhysicsScene() { - return GetPhysicsScene(m_physicsEngine); + return GetPhysicsScene(m_physicsEngine, m_meshEngineName); } private class SimStatusHandler : IStreamedRequestHandler @@ -767,4 +769,4 @@ namespace OpenSim #endregion } -} \ No newline at end of file +} diff --git a/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/OpenSim/Region/ClientStack/RegionApplicationBase.cs index 6071dcd..b0e6419 100644 --- a/OpenSim/Region/ClientStack/RegionApplicationBase.cs +++ b/OpenSim/Region/ClientStack/RegionApplicationBase.cs @@ -29,6 +29,7 @@ using System; using System.Collections.Generic; using System.Net; using libsecondlife; +using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Communications; using OpenSim.Framework.Communications.Cache; @@ -89,12 +90,12 @@ namespace OpenSim.Region.ClientStack protected abstract PhysicsScene GetPhysicsScene(); protected abstract StorageManager CreateStorageManager(RegionInfo regionInfo); - protected PhysicsScene GetPhysicsScene(string engine) + protected PhysicsScene GetPhysicsScene(string engine, string meshEngine) { PhysicsPluginManager physicsPluginManager; physicsPluginManager = new PhysicsPluginManager(); physicsPluginManager.LoadPlugins(); - return physicsPluginManager.GetPhysicsScene(engine); + return physicsPluginManager.GetPhysicsScene(engine, meshEngine); } protected Scene SetupScene(RegionInfo regionInfo, out UDPServer udpServer) @@ -150,4 +151,4 @@ namespace OpenSim.Region.ClientStack protected abstract Scene CreateScene(RegionInfo regionInfo, StorageManager storageManager, AgentCircuitManager circuitManager); } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Examples/SimpleApp/Program.cs b/OpenSim/Region/Examples/SimpleApp/Program.cs index 875bc4c..49fae93 100644 --- a/OpenSim/Region/Examples/SimpleApp/Program.cs +++ b/OpenSim/Region/Examples/SimpleApp/Program.cs @@ -182,7 +182,7 @@ namespace SimpleApp protected override PhysicsScene GetPhysicsScene() { - return GetPhysicsScene("basicphysics"); + return GetPhysicsScene("basicphysics", "Meshmerizer"); } #region conscmd_callback Members @@ -206,4 +206,4 @@ namespace SimpleApp app.Run(); } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs index 6377392..1d1c14f 100644 --- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs +++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs @@ -70,6 +70,11 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin { } + public override void Initialise(IMesher meshmerizer) + { + // Does nothing right now + } + public override PhysicsActor AddAvatar(string avName, PhysicsVector position) { BasicActor act = new BasicActor(); @@ -274,4 +279,4 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin { } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs index c733adb..2db7a54 100644 --- a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs +++ b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs @@ -64,6 +64,7 @@ using System; using System.Collections.Generic; using MonoXnaCompactMaths; using OpenSim.Framework; +using OpenSim.Framework.Console; using OpenSim.Region.Physics.Manager; using XnaDevRu.BulletX; using XnaDevRu.BulletX.Dynamics; @@ -74,15 +75,6 @@ using BoxShape=XnaDevRu.BulletX.BoxShape; namespace OpenSim.Region.Physics.BulletXPlugin { - /// - /// This class is only here for compilations reasons - /// - public class Mesh - { - public Mesh() - { - } - } /// /// BulletXConversions are called now BulletXMaths @@ -268,6 +260,65 @@ namespace OpenSim.Region.Physics.BulletXPlugin } } + + // Class to detect and debug collisions + // Mainly used for debugging purposes + class CollisionDispatcherLocal : CollisionDispatcher + { + + BulletXScene relatedScene; + + public CollisionDispatcherLocal(BulletXScene s) + : base() + { + relatedScene=s; + } + + public override bool NeedsCollision(CollisionObject bodyA, CollisionObject bodyB) + { + RigidBody rb; + BulletXCharacter bxcA=null; + BulletXPrim bxpA = null; + Type t = bodyA.GetType(); + if (t==typeof(RigidBody)) { + rb = (RigidBody)bodyA; + relatedScene._characters.TryGetValue(rb, out bxcA); + relatedScene._prims.TryGetValue(rb, out bxpA); + } + String nameA; + if (bxcA != null) + nameA = bxcA._name; + else if (bxpA != null) + nameA = bxpA._name; + else + nameA = "null"; + + BulletXCharacter bxcB = null; + BulletXPrim bxpB = null; + t = bodyB.GetType(); + if (t == typeof(RigidBody)) + { + rb = (RigidBody)bodyB; + relatedScene._characters.TryGetValue(rb, out bxcB); + relatedScene._prims.TryGetValue(rb, out bxpB); + } + String nameB; + if (bxcB != null) + nameB = bxcB._name; + else if (bxpB != null) + nameB = bxpB._name; + else + nameB = "null"; + + bool needsCollision=base.NeedsCollision(bodyA, bodyB); + + MainLog.Instance.Debug("BulletX", "A collision was detected between {0} and {1} --> {2}", nameA, nameB, needsCollision); + + + return needsCollision; + } + } + /// /// PhysicsScene Class for BulletX /// @@ -294,8 +345,11 @@ namespace OpenSim.Region.Physics.BulletXPlugin private const int simulationSubSteps = 10; //private float[] _heightmap; private BulletXPlanet _simFlatPlanet; - private List _characters = new List(); - private List _prims = new List(); + internal Dictionary _characters = new Dictionary(); + internal Dictionary _prims = new Dictionary(); + + public IMesher mesher; + public static float Gravity { @@ -334,7 +388,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin public BulletXScene() { - cDispatcher = new CollisionDispatcher(); + cDispatcher = new CollisionDispatcherLocal(this); Vector3 worldMinDim = new Vector3((float) minXY, (float) minXY, (float) minZ); Vector3 worldMaxDim = new Vector3((float) maxXY, (float) maxXY, (float) maxZ); opCache = new AxisSweep3(worldMinDim, worldMaxDim, maxHandles); @@ -348,6 +402,12 @@ namespace OpenSim.Region.Physics.BulletXPlugin //this._heightmap = new float[65536]; } + public override void Initialise(IMesher meshmerizer) + { + mesher = meshmerizer; + } + + public override PhysicsActor AddAvatar(string avName, PhysicsVector position) { PhysicsVector pos = new PhysicsVector(); @@ -358,7 +418,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin lock (BulletXLock) { newAv = new BulletXCharacter(avName, this, pos); - _characters.Add(newAv); + _characters.Add(newAv.RigidBody, newAv); } return newAv; } @@ -379,7 +439,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin ((BulletXCharacter) actor).RigidBody.ActivationState = ActivationState.DisableSimulation; AddForgottenRigidBody(((BulletXCharacter) actor).RigidBody); } - _characters.Remove((BulletXCharacter) actor); + _characters.Remove(((BulletXCharacter)actor).RigidBody); } GC.Collect(); } @@ -405,7 +465,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin } else { - Mesh mesh = null; + IMesh mesh = mesher.CreateMesh(primName, pbs, size); result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical); } break; @@ -419,13 +479,13 @@ namespace OpenSim.Region.Physics.BulletXPlugin } public PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, AxiomQuaternion rotation, - Mesh mesh, PrimitiveBaseShape pbs, bool isPhysical) + IMesh mesh, PrimitiveBaseShape pbs, bool isPhysical) { BulletXPrim newPrim = null; lock (BulletXLock) { newPrim = new BulletXPrim(name, this, position, size, rotation, mesh, pbs, isPhysical); - _prims.Add(newPrim); + _prims.Add(newPrim.RigidBody, newPrim); } return newPrim; } @@ -446,7 +506,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin ((BulletXPrim) prim).RigidBody.ActivationState = ActivationState.DisableSimulation; AddForgottenRigidBody(((BulletXPrim) prim).RigidBody); } - _prims.Remove((BulletXPrim) prim); + _prims.Remove(((BulletXPrim) prim).RigidBody); } GC.Collect(); } @@ -470,11 +530,11 @@ namespace OpenSim.Region.Physics.BulletXPlugin private void MoveAllObjects(float timeStep) { - foreach (BulletXCharacter actor in _characters) + foreach (BulletXCharacter actor in _characters.Values) { actor.Move(timeStep); } - foreach (BulletXPrim prim in _prims) + foreach (BulletXPrim prim in _prims.Values) { } } @@ -482,14 +542,14 @@ namespace OpenSim.Region.Physics.BulletXPlugin private void ValidateHeightForAll() { float _height; - foreach (BulletXCharacter actor in _characters) + foreach (BulletXCharacter actor in _characters.Values) { //_height = HeightValue(actor.RigidBodyPosition); _height = _simFlatPlanet.HeightValue(actor.RigidBodyPosition); actor.ValidateHeight(_height); //if (_simFlatPlanet.heightIsNotValid(actor.RigidBodyPosition, out _height)) actor.ValidateHeight(_height); } - foreach (BulletXPrim prim in _prims) + foreach (BulletXPrim prim in _prims.Values) { //_height = HeightValue(prim.RigidBodyPosition); _height = _simFlatPlanet.HeightValue(prim.RigidBodyPosition); @@ -510,11 +570,11 @@ namespace OpenSim.Region.Physics.BulletXPlugin { //UpdatePosition > UpdateKinetics. //Not only position will be updated, also velocity cause acceleration. - foreach (BulletXCharacter actor in _characters) + foreach (BulletXCharacter actor in _characters.Values) { actor.UpdateKinetics(); } - foreach (BulletXPrim prim in _prims) + foreach (BulletXPrim prim in _prims.Values) { prim.UpdateKinetics(); } @@ -646,9 +706,11 @@ namespace OpenSim.Region.Physics.BulletXPlugin protected PhysicsVector m_rotationalVelocity = PhysicsVector.Zero; protected RigidBody rigidBody; private Boolean iscolliding = false; + internal string _name; - public BulletXActor() + public BulletXActor(String name) { + _name = name; } public override PhysicsVector Position @@ -847,6 +909,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin } public BulletXCharacter(String avName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector velocity, PhysicsVector size, PhysicsVector acceleration, AxiomQuaternion orientation) + : base(avName) { //This fields will be removed. They're temporal float _sizeX = 0.5f; @@ -1016,14 +1079,15 @@ namespace OpenSim.Region.Physics.BulletXPlugin private bool m_lastUpdateSent = false; public BulletXPrim(String primName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector size, - AxiomQuaternion rotation, Mesh mesh, PrimitiveBaseShape pbs, bool isPhysical) + AxiomQuaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool isPhysical) : this(primName, parent_scene, pos, new PhysicsVector(), size, new PhysicsVector(), rotation, mesh, pbs, isPhysical) { } public BulletXPrim(String primName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector velocity, PhysicsVector size, - PhysicsVector acceleration, AxiomQuaternion rotation, Mesh mesh, PrimitiveBaseShape pbs, + PhysicsVector acceleration, AxiomQuaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool isPhysical) + : base(primName) { if ((size.X == 0) || (size.Y == 0) || (size.Z == 0)) throw new Exception("Size 0"); if (rotation.Norm == 0f) rotation = AxiomQuaternion.Identity; @@ -1037,7 +1101,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin _parent_scene = parent_scene; - CreateRigidBody(parent_scene, pos, size); + CreateRigidBody(parent_scene, mesh, pos, size); } public override PhysicsVector Position @@ -1191,7 +1255,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin } #region Methods for updating values of RigidBody - internal protected void CreateRigidBody(BulletXScene parent_scene, PhysicsVector pos, PhysicsVector size) + internal protected void CreateRigidBody(BulletXScene parent_scene, IMesh mesh, PhysicsVector pos, PhysicsVector size) { //For RigidBody Constructor. The next values might change float _linearDamping = 0.0f; @@ -1204,7 +1268,26 @@ namespace OpenSim.Region.Physics.BulletXPlugin { _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(pos); //For now all prims are boxes - CollisionShape _collisionShape = new XnaDevRu.BulletX.BoxShape(BulletXMaths.PhysicsVectorToXnaVector3(size) / 2.0f); + CollisionShape _collisionShape; + if (mesh == null) + { + _collisionShape = new XnaDevRu.BulletX.BoxShape(BulletXMaths.PhysicsVectorToXnaVector3(size) / 2.0f); + } else { + int iVertexCount = mesh.getVertexList().Count; + int[] indices = mesh.getIndexListAsInt(); + Vector3[] v3Vertices = new Vector3[iVertexCount]; + for (int i = 0; i < iVertexCount; i++) + { + PhysicsVector v=mesh.getVertexList()[i]; + if (v != null) // Note, null has special meaning. See meshing code for details + v3Vertices[i] = BulletXMaths.PhysicsVectorToXnaVector3(v); + else + v3Vertices[i] = MonoXnaCompactMaths.Vector3.Zero; + } + TriangleIndexVertexArray triMesh = new TriangleIndexVertexArray(indices, v3Vertices); + + _collisionShape = new XnaDevRu.BulletX.TriangleMeshShape(triMesh); + } DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset); Vector3 _localInertia = new Vector3(); if (_physical) _collisionShape.CalculateLocalInertia(Mass, out _localInertia); //Always when mass > 0 @@ -1231,7 +1314,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin rigidBody.ActivationState = ActivationState.DisableSimulation; this._parent_scene.AddForgottenRigidBody(rigidBody); } - CreateRigidBody(this._parent_scene, this._position, size); + CreateRigidBody(this._parent_scene, null, this._position, size); // Note, null for the meshing definitely is wrong. It's here for the moment to apease the compiler if (_physical) Speed();//Static objects don't have linear velocity ReOrient(); GC.Collect(); diff --git a/OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs b/OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs new file mode 100644 index 0000000..fb30296 --- /dev/null +++ b/OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs @@ -0,0 +1,161 @@ +/* + Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru + Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* + + This file contains a class TriangleIndexVertexArray. I tried using the class with the same name + from the BulletX implementation and found it unusable for the purpose of using triangle meshes + within BulletX as the implementation was painfully incomplete. + The attempt to derive from the original class failed as viable members were hidden. + Fiddling around with BulletX itself was not my intention. + So I copied the class to the BulletX-plugin and modified it. + If you want to fiddle around with it it's up to you to move all this to BulletX. + If someone someday implements the missing functionality in BulletX, feel free to remove this class. + It's just an ugly hack. + + */ +using System; +using System.Collections.Generic; +using System.Text; +using MonoXnaCompactMaths; + +namespace OpenSim.Region.Physics.BulletXPlugin +{ + /// + /// IndexedMesh indexes into existing vertex and index arrays, in a similar way OpenGL glDrawElements + /// instead of the number of indices, we pass the number of triangles + /// + public struct IndexedMesh + { + private int _numTriangles; + private int[] _triangleIndexBase; + private int _triangleIndexStride; + private int _numVertices; + private Vector3[] _vertexBase; + private int _vertexStride; + + public IndexedMesh(int numTriangleIndices, int[] triangleIndexBase, int triangleIndexStride, int numVertices, Vector3[] vertexBase, int vertexStride) + { + _numTriangles = numTriangleIndices; + _triangleIndexBase = triangleIndexBase; + _triangleIndexStride = triangleIndexStride; + _vertexBase = vertexBase; + _numVertices = numVertices; + _vertexStride = vertexStride; + } + + public IndexedMesh(int[] triangleIndexBase, Vector3[] vertexBase) + { + _numTriangles = triangleIndexBase.Length; + _triangleIndexBase = triangleIndexBase; + _triangleIndexStride = 32; + _vertexBase = vertexBase; + _numVertices = vertexBase.Length; + _vertexStride = 24; + } + + public int TriangleCount { get { return _numTriangles; } set { _numTriangles = value; } } + public int[] TriangleIndexBase { get { return _triangleIndexBase; } set { _triangleIndexBase = value; } } + public int TriangleIndexStride { get { return _triangleIndexStride; } set { _triangleIndexStride = value; } } + public int VertexCount { get { return _numVertices; } set { _numVertices = value; } } + public Vector3[] VertexBase { get { return _vertexBase; } set { _vertexBase = value; } } + public int VertexStride { get { return _vertexStride; } set { _vertexStride = value; } } + } + + /// + /// TriangleIndexVertexArray allows to use multiple meshes, by indexing into existing triangle/index arrays. + /// Additional meshes can be added using addIndexedMesh + /// + public class TriangleIndexVertexArray : XnaDevRu.BulletX.StridingMeshInterface + { + List _indexedMeshes = new List(); + + public TriangleIndexVertexArray() { } + + public TriangleIndexVertexArray(int numTriangleIndices, int[] triangleIndexBase, int triangleIndexStride, int numVertices, Vector3[] vertexBase, int vertexStride) + { + IndexedMesh mesh = new IndexedMesh(); + mesh.TriangleCount = numTriangleIndices; + mesh.TriangleIndexBase = triangleIndexBase; + mesh.TriangleIndexStride = triangleIndexStride; + mesh.VertexBase = vertexBase; + mesh.VertexCount = numVertices; + mesh.VertexStride = vertexStride; + + AddIndexedMesh(mesh); + } + + public TriangleIndexVertexArray(int[] triangleIndexBase, Vector3[] vertexBase) + : this(triangleIndexBase.Length, triangleIndexBase, 32, vertexBase.Length, vertexBase, 24) { } + + public void AddIndexedMesh(IndexedMesh indexedMesh) + { + _indexedMeshes.Add(indexedMesh); + } + + public override void GetLockedVertexIndexBase(out List verts, out List indicies, out int numfaces, int subpart) + { + throw new Exception("The method or operation is not implemented."); + } + + public override void GetLockedReadOnlyVertexIndexBase(out List verts, out List indicies, out int numfaces, int subpart) + { + IndexedMesh m = _indexedMeshes[0]; + Vector3[] vertexBase = m.VertexBase; + verts = new List(); + foreach (Vector3 v in vertexBase) + { + verts.Add(v); + } + int[] indexBase = m.TriangleIndexBase; + indicies = new List(); + foreach (int i in indexBase) + { + indicies.Add(i); + } + numfaces = vertexBase.GetLength(0); + } + + public override void UnLockVertexBase(int subpart) + { + throw new Exception("The method or operation is not implemented."); + } + + public override void UnLockReadOnlyVertexBase(int subpart) + { + } + + public override int SubPartsCount() + { + return _indexedMeshes.Count; + } + + public override void PreallocateVertices(int numverts) + { + throw new Exception("The method or operation is not implemented."); + } + + public override void PreallocateIndices(int numindices) + { + throw new Exception("The method or operation is not implemented."); + } + } +} diff --git a/OpenSim/Region/Physics/Manager/IMesher.cs b/OpenSim/Region/Physics/Manager/IMesher.cs new file mode 100644 index 0000000..037616c --- /dev/null +++ b/OpenSim/Region/Physics/Manager/IMesher.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; + +using OpenSim.Framework; + +namespace OpenSim.Region.Physics.Manager +{ + public interface IMesher + { + IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size); + } + + public interface IVertex { + } + + public interface IMesh + { + List getVertexList(); + int[] getIndexListAsInt(); + int[] getIndexListAsIntLocked(); + float[] getVertexListAsFloatLocked(); + + + } +} diff --git a/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs b/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs index 09ebf29..47c8ae0 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs @@ -30,6 +30,7 @@ using System.Collections.Generic; using System.IO; using System.Reflection; using OpenSim.Framework.Console; +using Nini.Config; namespace OpenSim.Region.Physics.Manager { @@ -38,28 +39,50 @@ namespace OpenSim.Region.Physics.Manager /// public class PhysicsPluginManager { - private Dictionary _plugins = new Dictionary(); + private Dictionary _PhysPlugins = new Dictionary(); + private Dictionary _MeshPlugins = new Dictionary(); public PhysicsPluginManager() { } - public PhysicsScene GetPhysicsScene(string engineName) + public PhysicsScene GetPhysicsScene(string physEngineName, string meshEngineName) { - if (String.IsNullOrEmpty(engineName)) + + if (String.IsNullOrEmpty(physEngineName)) + { + return PhysicsScene.Null; + } + + if (String.IsNullOrEmpty(meshEngineName)) { return PhysicsScene.Null; } - if (_plugins.ContainsKey(engineName)) + + IMesher meshEngine = null; + if (_MeshPlugins.ContainsKey(meshEngineName)) { - MainLog.Instance.Verbose("PHYSICS", "creating " + engineName); - return _plugins[engineName].GetScene(); + MainLog.Instance.Verbose("PHYSICS", "creating meshing engine " + meshEngineName); + meshEngine = _MeshPlugins[meshEngineName].GetMesher(); } else { - MainLog.Instance.Warn("PHYSICS", "couldn't find physicsEngine: {0}", engineName); - throw new ArgumentException(String.Format("couldn't find physicsEngine: {0}", engineName)); + MainLog.Instance.Warn("PHYSICS", "couldn't find meshingEngine: {0}", meshEngineName); + throw new ArgumentException(String.Format("couldn't find meshingEngine: {0}", meshEngineName)); + } + + if (_PhysPlugins.ContainsKey(physEngineName)) + { + MainLog.Instance.Verbose("PHYSICS", "creating " + physEngineName); + PhysicsScene result = _PhysPlugins[physEngineName].GetScene(); + result.Initialise(meshEngine); + return result; + } + else + { + MainLog.Instance.Warn("PHYSICS", "couldn't find physicsEngine: {0}", physEngineName); + throw new ArgumentException(String.Format("couldn't find physicsEngine: {0}", physEngineName)); } } @@ -85,18 +108,29 @@ namespace OpenSim.Region.Physics.Manager { if (!pluginType.IsAbstract) { - Type typeInterface = pluginType.GetInterface("IPhysicsPlugin", true); + Type physTypeInterface = pluginType.GetInterface("IPhysicsPlugin", true); - if (typeInterface != null) + if (physTypeInterface != null) { IPhysicsPlugin plug = (IPhysicsPlugin) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); plug.Init(); - _plugins.Add(plug.GetName(), plug); + _PhysPlugins.Add(plug.GetName(), plug); MainLog.Instance.Verbose("PHYSICS", "Added physics engine: " + plug.GetName()); } - typeInterface = null; + Type meshTypeInterface = pluginType.GetInterface("IMeshingPlugin", true); + + if (meshTypeInterface != null) + { + IMeshingPlugin plug = + (IMeshingPlugin)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); + _MeshPlugins.Add(plug.GetName(), plug); + MainLog.Instance.Verbose("PHYSICS", "Added meshing engine: " + plug.GetName()); + } + + physTypeInterface = null; + meshTypeInterface = null; } } } @@ -127,4 +161,11 @@ namespace OpenSim.Region.Physics.Manager string GetName(); void Dispose(); } -} \ No newline at end of file + + public interface IMeshingPlugin + { + string GetName(); + IMesher GetMesher(); + } + +} diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs index 13591ea..6f19e72 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs @@ -28,6 +28,7 @@ using Axiom.Math; using OpenSim.Framework; using OpenSim.Framework.Console; +using OpenSim.Region.Physics.Manager; namespace OpenSim.Region.Physics.Manager { @@ -38,6 +39,8 @@ namespace OpenSim.Region.Physics.Manager get { return new NullPhysicsScene(); } } + public abstract void Initialise(IMesher meshmerizer); + public abstract PhysicsActor AddAvatar(string avName, PhysicsVector position); public abstract void RemoveAvatar(PhysicsActor actor); @@ -63,6 +66,12 @@ namespace OpenSim.Region.Physics.Manager { private static int m_workIndicator; + + public override void Initialise(IMesher meshmerizer) + { + // Does nothing right now + } + public override PhysicsActor AddAvatar(string avName, PhysicsVector position) { MainLog.Instance.Verbose("NullPhysicsScene : AddAvatar({0})", position); @@ -123,4 +132,4 @@ namespace OpenSim.Region.Physics.Manager } } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Physics/Meshing/Extruder.cs b/OpenSim/Region/Physics/Meshing/Extruder.cs new file mode 100644 index 0000000..63d727f --- /dev/null +++ b/OpenSim/Region/Physics/Meshing/Extruder.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Region.Physics.Meshing +{ + class Extruder + { + public float startParameter; + public float stopParameter; + public Manager.PhysicsVector size; + + public Mesh Extrude(Mesh m) + { + // Currently only works for iSteps=1; + Mesh result = new Mesh(); + + Mesh workingPlus = m.Clone(); + Mesh workingMinus = m.Clone(); + + foreach (Vertex v in workingPlus.vertices) + { + if (v == null) + continue; + + v.Z = +.5f; + v.X *= size.X; + v.Y *= size.Y; + v.Z *= size.Z; + } + + foreach (Vertex v in workingMinus.vertices) + { + if (v == null) + continue; + + v.Z = -.5f; + v.X *= size.X; + v.Y *= size.Y; + v.Z *= size.Z; + } + + foreach (Triangle t in workingMinus.triangles) + { + t.invertNormal(); + } + + result.Append(workingMinus); + result.Append(workingPlus); + + int iLastNull = 0; + for (int i = 0; i < workingPlus.vertices.Count; i++) + { + int iNext = (i + 1); + + if (workingPlus.vertices[i] == null) // Can't make a simplex here + { + iLastNull = i+1; + continue; + } + + if (i == workingPlus.vertices.Count-1) // End of list + { + iNext = iLastNull; + } + + if (workingPlus.vertices[iNext] == null) // Null means wrap to begin of last segment + { + iNext = iLastNull; + } + + Triangle tSide; + tSide = new Triangle(workingPlus.vertices[i], workingMinus.vertices[i], workingPlus.vertices[iNext]); + result.Add(tSide); + + tSide = new Triangle(workingPlus.vertices[iNext], workingMinus.vertices[i], workingMinus.vertices[iNext]); + result.Add(tSide); + } + + return result; + } + } +} diff --git a/OpenSim/Region/Physics/Meshing/HelperTypes.cs b/OpenSim/Region/Physics/Meshing/HelperTypes.cs new file mode 100644 index 0000000..9e75826 --- /dev/null +++ b/OpenSim/Region/Physics/Meshing/HelperTypes.cs @@ -0,0 +1,306 @@ +/* +* 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 OpenSim 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 OpenSim.Framework.Console; +using OpenSim.Region.Physics.Manager; + +using OpenSim.Region.Physics.Meshing; + +public class Vertex : PhysicsVector, IComparable +{ + public Vertex(float x, float y, float z) + : base(x, y, z) + { + } + + public Vertex(PhysicsVector v) + : base(v.X, v.Y, v.Z) + { + } + + 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 virtual bool Equals(Vertex v, float tolerance) + { + PhysicsVector 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 List GetSimplices() + { + List result = new List(); + Simplex s1 = new Simplex(v1, v2); + Simplex s2 = new Simplex(v2, v3); + Simplex s3 = new Simplex(v3, v1); + + result.Add(s1); + result.Add(s2); + result.Add(s3); + + return result; + } + + 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 PhysicsVector getNormal() + { + // Vertices + + // Vectors for edges + PhysicsVector e1; + PhysicsVector e2; + + e1 = new PhysicsVector(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z); + e2 = new PhysicsVector(v1.X - v3.X, v1.Y - v3.Y, v1.Z - v3.Z); + + // Cross product for normal + PhysicsVector n = PhysicsVector.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; + } +} \ No newline at end of file diff --git a/OpenSim/Region/Physics/Meshing/Mesh.cs b/OpenSim/Region/Physics/Meshing/Mesh.cs new file mode 100644 index 0000000..fd4ce4e --- /dev/null +++ b/OpenSim/Region/Physics/Meshing/Mesh.cs @@ -0,0 +1,213 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Text; + +using System.Runtime.InteropServices; + + +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Physics.Meshing +{ + public class Mesh : IMesh + { + public List vertices; + public List triangles; + + public float[] normals; + + public Mesh() + { + vertices = new List(); + triangles = new List(); + } + + public Mesh Clone() + { + Mesh result = new Mesh(); + + foreach (Vertex v in vertices) + { + if (v == null) + result.vertices.Add(null); + else + result.vertices.Add(v.Clone()); + } + + foreach (Triangle t in triangles) + { + int iV1, iV2, iV3; + iV1 = this.vertices.IndexOf(t.v1); + iV2 = this.vertices.IndexOf(t.v2); + iV3 = this.vertices.IndexOf(t.v3); + + Triangle newT = new Triangle(result.vertices[iV1], result.vertices[iV2], result.vertices[iV3]); + result.Add(newT); + } + + return result; + } + + + + public void Add(Triangle triangle) + { + int i; + i = vertices.IndexOf(triangle.v1); + if (i < 0) + throw new ArgumentException("Vertex v1 not known to mesh"); + i = vertices.IndexOf(triangle.v2); + if (i < 0) + throw new ArgumentException("Vertex v2 not known to mesh"); + i = vertices.IndexOf(triangle.v3); + if (i < 0) + throw new ArgumentException("Vertex v3 not known to mesh"); + + triangles.Add(triangle); + } + + public void Add(Vertex v) + { + vertices.Add(v); + } + + public void Remove(Vertex v) + { + int i; + + // First, remove all triangles that are build on v + for (i = 0; i < triangles.Count; i++) + { + Triangle t = triangles[i]; + if (t.v1 == v || t.v2 == v || t.v3 == v) + { + triangles.RemoveAt(i); + i--; + } + } + + // Second remove v itself + vertices.Remove(v); + } + + public void RemoveTrianglesOutside(SimpleHull hull) + { + int i; + + for (i = 0; i < triangles.Count; i++) + { + Triangle t = triangles[i]; + Vertex v1 = t.v1; + Vertex v2 = t.v2; + Vertex v3 = t.v3; + PhysicsVector m = v1 + v2 + v3; + m /= 3.0f; + if (!hull.IsPointIn(new Vertex(m))) + { + triangles.RemoveAt(i); + i--; + } + } + } + + + public void Add(List lv) + { + foreach (Vertex v in lv) + { + vertices.Add(v); + } + } + + public List getVertexList() + { + List result = new List(); + foreach (Vertex v in vertices) + { + result.Add(v); + } + return result; + } + + public float[] getVertexListAsFloatLocked() + { + float[] result = new float[vertices.Count * 3]; + for (int i = 0; i < vertices.Count; i++) + { + Vertex v = vertices[i]; + if (v == null) + continue; + result[3 * i + 0] = v.X; + result[3 * i + 1] = v.Y; + result[3 * i + 2] = v.Z; + } + GCHandle.Alloc(result, GCHandleType.Pinned); + return result; + } + + public int[] getIndexListAsInt() + { + int[] result = new int[triangles.Count * 3]; + for (int i = 0; i < triangles.Count; i++) + { + Triangle t = triangles[i]; + result[3 * i + 0] = vertices.IndexOf(t.v1); + result[3 * i + 1] = vertices.IndexOf(t.v2); + result[3 * i + 2] = vertices.IndexOf(t.v3); + } + return result; + } + + public int[] getIndexListAsIntLocked() + { + int[] result = getIndexListAsInt(); + GCHandle.Alloc(result, GCHandleType.Pinned); + return result; + } + + + public void Append(Mesh newMesh) + { + foreach (Vertex v in newMesh.vertices) + vertices.Add(v); + + foreach (Triangle t in newMesh.triangles) + Add(t); + + } + + // Do a linear transformation of mesh. + public void TransformLinear(float[,] matrix, float[] offset) + { + foreach (Vertex v in vertices) + { + 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 = Path.Combine(path, fileName); + StreamWriter sw = new StreamWriter(completePath); + foreach (Triangle t in triangles) + { + String s = t.ToStringRaw(); + sw.WriteLine(s); + } + sw.Close(); + } + } + +} diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs new file mode 100644 index 0000000..da4ee58 --- /dev/null +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -0,0 +1,393 @@ +/* +* 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 OpenSim 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.IO; +using System.Globalization; +using System.Diagnostics; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Physics.Meshing +{ + + public class MeshmerizerPlugin : IMeshingPlugin + { + public MeshmerizerPlugin() + { + } + + public string GetName() + { + return "Meshmerizer"; + } + + public IMesher GetMesher() + { + return new Meshmerizer(); + } + } + + public class Meshmerizer : IMesher + { + // 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 + // const string baseDir = "rawFiles"; + const string baseDir = null; + + static void IntersectionParameterPD(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2, PhysicsVector r2, ref float lambda, ref float mu) + { + // p1, p2, points on the straight + // r1, r2, directional vectors of the straight. Not necessarily of length 1! + // note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points, + // thus allowing to decide whether an intersection is between two points + + float r1x = r1.X; + float r1y = r1.Y; + float r2x = r2.X; + float r2y = r2.Y; + + float denom = r1y*r2x - r1x*r2y; + + if (denom == 0.0) + { + lambda = Single.NaN; + mu = Single.NaN; + return; + } + + float p1x = p1.X; + float p1y = p1.Y; + float p2x = p2.X; + float p2y = p2.Y; + lambda = (-p2x * r2y + p1x * r2y + (p2y - p1y) * r2x) / denom; + mu = (-p2x * r1y + p1x * r1y + (p2y - p1y) * r1x) / denom; + + } + + private static List FindInfluencedTriangles(List triangles, Vertex v) + { + List influenced = new List(); + foreach (Triangle t in triangles) + { + if (t.isInCircle(v.X, v.Y)) + { + influenced.Add(t); + } + } + return influenced; + } + + + private static void InsertVertices(List vertices, int usedForSeed, List triangles) + { + // This is a variant of the delaunay algorithm + // each time a new vertex is inserted, all triangles that are influenced by it are deleted + // and replaced by new ones including the new vertex + // It is not very time efficient but easy to implement. + + int iCurrentVertex; + int iMaxVertex = vertices.Count; + for (iCurrentVertex = usedForSeed; iCurrentVertex < iMaxVertex; iCurrentVertex++) + { + // Background: A triangle mesh fulfills the delaunay condition if (iff!) + // each circumlocutory circle (i.e. the circle that touches all three corners) + // of each triangle is empty of other vertices. + // Obviously a single (seeding) triangle fulfills this condition. + // If we now add one vertex, we need to reconstruct all triangles, that + // do not fulfill this condition with respect to the new triangle + + // Find the triangles that are influenced by the new vertex + Vertex v=vertices[iCurrentVertex]; + if (v == null) + continue; // Null is polygon stop marker. Ignore it + List influencedTriangles=FindInfluencedTriangles(triangles, v); + + List simplices = new List(); + + // Reconstruction phase. First step, dissolve each triangle into it's simplices, + // i.e. it's "border lines" + // Goal is to find "inner" borders and delete them, while the hull gets conserved. + // Inner borders are special in the way that they always come twice, which is how we detect them + foreach (Triangle t in influencedTriangles) + { + List newSimplices = t.GetSimplices(); + simplices.AddRange(newSimplices); + triangles.Remove(t); + } + // Now sort the simplices. That will make identical ones reside side by side in the list + simplices.Sort(); + + // Look for duplicate simplices here. + // Remember, they are directly side by side in the list right now, + // So we only check directly neighbours + int iSimplex; + List innerSimplices = new List(); + for (iSimplex = 1; iSimplex < simplices.Count; iSimplex++) // Startindex=1, so we can refer backwards + { + if (simplices[iSimplex - 1].CompareTo(simplices[iSimplex]) == 0) + { + innerSimplices.Add(simplices[iSimplex - 1]); + innerSimplices.Add(simplices[iSimplex]); + } + } + + foreach (Simplex s in innerSimplices) + { + simplices.Remove(s); + } + + // each simplex still in the list belongs to the hull of the region in question + // The new vertex (yes, we still deal with verices here :-) ) forms a triangle + // with each of these simplices. Build the new triangles and add them to the list + foreach (Simplex s in simplices) + { + Triangle t = new Triangle(s.v1, s.v2, vertices[iCurrentVertex]); + if (!t.isDegraded()) + { + triangles.Add(t); + } + } + } + + } + + + static Mesh CreateBoxMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) + // Builds the z (+ and -) surfaces of a box shaped prim + { + UInt16 hollowFactor = primShape.ProfileHollow; + UInt16 profileBegin = primShape.ProfileBegin; + UInt16 profileEnd = primShape.ProfileEnd; + + // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface + // of a block are basically the same + // They may be warped differently but the shape is identical + // So we only create one surface as a model and derive both plus and minus surface of the block from it + // This is done in a model space where the block spans from -.5 to +.5 in X and Y + // The mapping to Scene space is done later during the "extrusion" phase + + // Base + Vertex MM = new Vertex(-0.5f, -0.5f, 0.0f); + Vertex PM = new Vertex(+0.5f, -0.5f, 0.0f); + Vertex MP = new Vertex(-0.5f, +0.5f, 0.0f); + Vertex PP = new Vertex(+0.5f, +0.5f, 0.0f); + + Meshing.SimpleHull outerHull = new SimpleHull(); + outerHull.AddVertex(MM); + outerHull.AddVertex(PM); + outerHull.AddVertex(PP); + outerHull.AddVertex(MP); + + // Deal with cuts now + if ((profileBegin != 0) || (profileEnd != 0)) + { + double fProfileBeginAngle = profileBegin / 50000.0 * 360.0; // In degree, for easier debugging and understanding + fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y + double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0 + fProfileEndAngle -= (90.0 + 45.0); + if (fProfileBeginAngle < fProfileEndAngle) + fProfileEndAngle -= 360.0; + + // Note, that we don't want to cut out a triangle, even if this is a + // good approximation for small cuts. Indeed we want to cut out an arc + // and we approximate this arc by a polygon chain + // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space + // So it can easily be subtracted from the outer hull + int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5); // how many steps do we need with approximately 45 degree + double dStepWidth=(fProfileBeginAngle-fProfileEndAngle)/iSteps; + + Vertex origin = new Vertex(0.0f, 0.0f, 0.0f); + + // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull + SimpleHull cutHull = new SimpleHull(); + cutHull.AddVertex(origin); + for (int i=0; i 0) + { + float hollowFactorF = (float) hollowFactor/(float) 50000; + Vertex IMM = new Vertex(-0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f); + Vertex IPM = new Vertex(+0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f); + Vertex IMP = new Vertex(-0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f); + Vertex IPP = new Vertex(+0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f); + + SimpleHull holeHull = new SimpleHull(); + + holeHull.AddVertex(IMM); + holeHull.AddVertex(IMP); + holeHull.AddVertex(IPP); + holeHull.AddVertex(IPM); + + SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull); + + outerHull = hollowedHull; + + } + + Mesh m = new Mesh(); + + Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f); + Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f); + Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f); + + m.Add(Seed1); + m.Add(Seed2); + m.Add(Seed3); + + m.Add(new Triangle(Seed1, Seed2, Seed3)); + m.Add(outerHull.getVertices()); + + InsertVertices(m.vertices, 3, m.triangles); + m.DumpRaw(baseDir, primName, "Proto first Mesh"); + + m.Remove(Seed1); + m.Remove(Seed2); + m.Remove(Seed3); + m.DumpRaw(baseDir, primName, "Proto seeds removed"); + + m.RemoveTrianglesOutside(outerHull); + m.DumpRaw(baseDir, primName, "Proto outsides removed"); + + foreach (Triangle t in m.triangles) + { + PhysicsVector n = t.getNormal(); + if (n.Z < 0.0) + t.invertNormal(); + } + + Extruder extr = new Extruder(); + + extr.size = size; + + Mesh result = extr.Extrude(m); + result.DumpRaw(baseDir, primName, "Z extruded"); + return result; + } + + public static void CalcNormals(Mesh mesh) + { + int iTriangles = mesh.triangles.Count; + + mesh.normals = new float[iTriangles*3]; + + int i = 0; + foreach (Triangle t in mesh.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); + + // Normalized "normal" + nx /= l; + ny /= l; + nz /= l; + + mesh.normals[i] = nx; + mesh.normals[i + 1] = ny; + mesh.normals[i + 2] = nz; + + i += 3; + } + } + + public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) + { + Mesh mesh = null; + + switch (primShape.ProfileShape) + { + case ProfileShape.Square: + mesh=CreateBoxMesh(primName, primShape, size); + CalcNormals(mesh); + break; + default: + mesh = CreateBoxMesh(primName, primShape, size); + CalcNormals(mesh); + //Set default mesh to cube otherwise it'll return + // null and crash on the 'setMesh' method in the physics plugins. + //mesh = null; + break; + } + + return mesh; + } + } + +} diff --git a/OpenSim/Region/Physics/Meshing/SimpleHull.cs b/OpenSim/Region/Physics/Meshing/SimpleHull.cs new file mode 100644 index 0000000..c199949 --- /dev/null +++ b/OpenSim/Region/Physics/Meshing/SimpleHull.cs @@ -0,0 +1,363 @@ +using System; +using System.Collections.Generic; +using System.Text; + +using OpenSim.Framework.Console; + +namespace OpenSim.Region.Physics.Meshing +{ + // A simple hull is a set of vertices building up to simplices that border a region + // The word simple referes to the fact, that this class assumes, that all simplices + // do not intersect + // Simple hulls can be added and subtracted. + // Vertices can be checked to lie inside a hull + // Also note, that the sequence of the vertices is important and defines if the region that + // is defined by the hull lies inside or outside the simplex chain + public class SimpleHull + { + List vertices = new List(); + List holeVertices = new List(); // Only used, when the hull is hollow + + // Adds a vertex to the end of the list + public void AddVertex(Vertex v) { + vertices.Add(v); + } + + override public String ToString() + { + String result=""; + foreach (Vertex v in vertices) + { + result += "b:" + v.ToString() + "\n"; + } + + return result; + } + + + public List getVertices() { + List newVertices = new List(); + + newVertices.AddRange(vertices); + newVertices.Add(null); + newVertices.AddRange(holeVertices); + + return newVertices; + } + + public SimpleHull Clone() + { + SimpleHull result = new SimpleHull(); + foreach (Vertex v in vertices) + { + result.AddVertex(v.Clone()); + } + + foreach (Vertex v in this.holeVertices) + { + result.holeVertices.Add(v.Clone()); + } + + return result; + } + + public bool IsPointIn(Vertex v1) + { + int iCounter=0; + List simplices=buildSimplexList(); + foreach (Simplex s in simplices) + { + // Send a ray along the positive X-Direction + // Note, that this direction must correlate with the "below" interpretation + // of handling for the special cases below + Manager.PhysicsVector intersection = s.RayIntersect(v1, new Manager.PhysicsVector(1.0f, 0.0f, 0.0f), true); + + if (intersection == null) + continue; // No intersection. Done. More tests to follow otherwise + + // Did we hit the end of a simplex? + // Then this can be one of two special cases: + // 1. we go through a border exactly at a joint + // 2. we have just marginally touched a corner + // 3. we can slide along a border + // Solution: If the other vertex is "below" the ray, we don't count it + // Thus corners pointing down are counted twice, corners pointing up are not counted + // borders are counted once + if (intersection.IsIdentical(s.v1, 0.001f)) { + if (s.v2.Y < v1.Y) + continue; + } + // Do this for the other vertex two + if (intersection.IsIdentical(s.v2, 0.001f)) { + if (s.v1.Y buildSimplexList() { + + List result = new List(); + + // Not asserted but assumed: at least three vertices + for (int i=0; i simple = buildSimplexList(); + foreach (Simplex sTest in simple) + { + Manager.PhysicsVector vvTemp = Simplex.Intersect(sTest, s, -.001f, -.001f, 0.999f, .999f); + + Vertex vTemp=null; + if (vvTemp != null) + vTemp = new Vertex(vvTemp); + + if (vTemp!=null) { + + Manager.PhysicsVector diff=(s.v1-vTemp); + float distTemp=diff.length(); + + if (bestIntersection==null || distTemp + { + public Vertex v1; + public Vertex v2; + + public Simplex(Vertex _v1, Vertex _v2) + { + v1 = _v1; + v2 = _v2; + } + + public int CompareTo(Simplex other) + { + + Vertex lv1, lv2, ov1, ov2, temp; + + lv1 = v1; + lv2 = v2; + ov1 = other.v1; + ov2 = other.v2; + + if (lv1 > lv2) + { + temp = lv1; + lv1 = lv2; + lv2 = temp; + } + + if (ov1 > ov2) + { + temp = ov1; + ov1 = ov2; + ov2 = temp; + } + + if (lv1 > ov1) + { + return 1; + } + if (lv1 < ov1) + { + return -1; + } + + if (lv2 > ov2) + { + return 1; + } + if (lv2 < ov2) + { + return -1; + } + + return 0; + } + + private static void intersectParameter(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2, PhysicsVector r2, ref float lambda, ref float mu) + { + // Intersects two straights + // p1, p2, points on the straight + // r1, r2, directional vectors of the straight. Not necessarily of length 1! + // note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points, + // thus allowing to decide whether an intersection is between two points + + float r1x = r1.X; + float r1y = r1.Y; + float r2x = r2.X; + float r2y = r2.Y; + + float denom = r1y*r2x - r1x*r2y; + + float p1x = p1.X; + float p1y = p1.Y; + float p2x = p2.X; + float p2y = p2.Y; + + float z1=-p2x * r2y + p1x * r2y + (p2y - p1y) * r2x; + float z2=-p2x * r1y + p1x * r1y + (p2y - p1y) * r1x; + + if (denom == 0.0f) // Means the straights are parallel. Either no intersection or an infinite number of them + { + if (z1==0.0f) {// Means they are identical -> many, many intersections + lambda = Single.NaN; + mu = Single.NaN; + } else { + lambda = Single.PositiveInfinity; + mu = Single.PositiveInfinity; + } + return; + + } + + + + lambda = z1 / denom; + mu = z2 / denom; + + } + + + // Intersects the simplex with another one. + // the borders are used to deal with float inaccuracies + // As a rule of thumb, the borders are + // lowerBorder1 : 0.0 + // lowerBorder2 : 0.0 + // upperBorder1 : 1.0 + // upperBorder2 : 1.0 + // Set these to values near the given parameters (e.g. 0.001 instead of 1 to exclude simplex starts safely, or to -0.001 to include them safely) + public static PhysicsVector Intersect( + Simplex s1, + Simplex s2, + float lowerBorder1, + float lowerBorder2, + float upperBorder1, + float upperBorder2) + { + PhysicsVector firstSimplexDirection = s1.v2 - s1.v1; + PhysicsVector secondSimplexDirection = s2.v2 - s2.v1; + + float lambda = 0.0f; + float mu = 0.0f; + + // Give us the parameters of an intersection. This subroutine does *not* take the constraints + // (intersection must be between v1 and v2 and it must be in the positive direction of the ray) + // into account. We do that afterwards. + intersectParameter(s1.v1, firstSimplexDirection, s2.v1, secondSimplexDirection, ref lambda, ref mu); + + if (Single.IsInfinity(lambda)) // Special case. No intersection at all. directions parallel. + return null; + + if (Single.IsNaN(lambda)) // Special case. many, many intersections. + return null; + + if (lambda > upperBorder1) // We're behind v2 + return null; + + if (lambda < lowerBorder1) + return null; + + if (mu < lowerBorder2) // outside simplex 2 + return null; + + if (mu > upperBorder2) // outside simplex 2 + return null; + + return s1.v1 + lambda * firstSimplexDirection; + + } + + // Intersects the simplex with a ray. The ray is defined as all p=origin + lambda*direction + // where lambda >= 0 + public PhysicsVector RayIntersect(Vertex origin, PhysicsVector direction, bool bEndsIncluded) + { + PhysicsVector simplexDirection = v2 - v1; + + float lambda = 0.0f; + float mu = 0.0f; + + // Give us the parameters of an intersection. This subroutine does *not* take the constraints + // (intersection must be between v1 and v2 and it must be in the positive direction of the ray) + // into account. We do that afterwards. + intersectParameter(v1, simplexDirection, origin, direction, ref lambda, ref mu); + + if (Single.IsInfinity(lambda)) // Special case. No intersection at all. directions parallel. + return null; + + if (Single.IsNaN(lambda)) // Special case. many, many intersections. + return null; + + if (mu < 0.0) // We're on the wrong side of the ray + return null; + + if (lambda > 1.0) // We're behind v2 + return null; + + if (lambda == 1.0 && !bEndsIncluded) + return null; // The end of the simplices are not included + + if (lambda < 0.0f) // we're before v1; + return null; + + return this.v1 + lambda * simplexDirection; + + } + + + } +} \ No newline at end of file diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs index 4e69175..646ccb5 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs @@ -32,7 +32,7 @@ using Axiom.Math; using Ode.NET; using OpenSim.Framework; using OpenSim.Region.Physics.Manager; -using OpenSim.Region.Physics.OdePlugin.Meshing; +//using OpenSim.Region.Physics.OdePlugin.Meshing; namespace OpenSim.Region.Physics.OdePlugin { @@ -98,6 +98,8 @@ namespace OpenSim.Region.Physics.OdePlugin public IntPtr space; public static Object OdeLock = new Object(); + public IMesher mesher; + public OdeScene() { nearCallback = near; @@ -137,6 +139,12 @@ namespace OpenSim.Region.Physics.OdePlugin } + public override void Initialise(IMesher meshmerizer) + { + mesher = meshmerizer; + } + + // This function blatantly ripped off from BoxStack.cs private void near(IntPtr space, IntPtr g1, IntPtr g2) { @@ -308,7 +316,7 @@ namespace OpenSim.Region.Physics.OdePlugin } private PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, Quaternion rotation, - Mesh mesh, PrimitiveBaseShape pbs, bool isphysical) + IMesh mesh, PrimitiveBaseShape pbs, bool isphysical) { PhysicsVector pos = new PhysicsVector(); pos.X = position.X; @@ -409,11 +417,12 @@ namespace OpenSim.Region.Physics.OdePlugin { return this.AddPrimShape(primName, pbs, position, size, rotation, false); } + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, Quaternion rotation, bool isPhysical) { PhysicsActor result; - Mesh mesh = null; + IMesh mesh = null; switch (pbs.ProfileShape) { @@ -421,7 +430,7 @@ namespace OpenSim.Region.Physics.OdePlugin /// support simple box & hollow box now; later, more shapes if (needsMeshing(pbs)) { - mesh = Meshmerizer.CreateMesh(primName, pbs, size); + mesh = mesher.CreateMesh(primName, pbs, size); } break; @@ -931,7 +940,7 @@ namespace OpenSim.Region.Physics.OdePlugin private PhysicsVector _acceleration; public Quaternion _orientation; - private Mesh _mesh; + private IMesh _mesh; private PrimitiveBaseShape _pbs; private OdeScene _parent_scene; public IntPtr prim_geom; @@ -953,7 +962,7 @@ namespace OpenSim.Region.Physics.OdePlugin public OdePrim(String primName, OdeScene parent_scene, PhysicsVector pos, PhysicsVector size, - Quaternion rotation, Mesh mesh, PrimitiveBaseShape pbs, bool pisPhysical) + Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical) { @@ -1036,15 +1045,15 @@ namespace OpenSim.Region.Physics.OdePlugin Body = (IntPtr)0; } } - public void setMesh(OdeScene parent_scene, Mesh mesh) + public void setMesh(OdeScene parent_scene, IMesh mesh) { //Kill Body so that mesh can re-make the geom if (IsPhysical && Body != (IntPtr)0) { disableBody(); } - float[] vertexList = mesh.getVertexListAsFloat(); // Note, that vertextList is pinned in memory - int[] indexList = mesh.getIndexListAsInt(); // Also pinned, needs release after usage + float[] vertexList = mesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory + int[] indexList = mesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage int VertexCount = vertexList.GetLength(0)/3; int IndexCount = indexList.GetLength(0); @@ -1169,7 +1178,7 @@ namespace OpenSim.Region.Physics.OdePlugin // Don't need to re-enable body.. it's done in SetMesh - Mesh mesh = Meshmerizer.CreateMesh(oldname, _pbs, _size); + IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size); // createmesh returns null when it's a shape that isn't a cube. if (mesh != null) setMesh(_parent_scene, mesh); @@ -1218,7 +1227,7 @@ namespace OpenSim.Region.Physics.OdePlugin // Construction of new prim if (this._parent_scene.needsMeshing(_pbs)) { - Mesh mesh = Meshmerizer.CreateMesh(oldname, _pbs, _size); + IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size); setMesh(_parent_scene, mesh); } else { prim_geom = d.CreateBox(_parent_scene.space, _size.X, _size.Y, _size.Z); diff --git a/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs b/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs index 76121ae..7652372 100644 --- a/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs +++ b/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs @@ -84,6 +84,12 @@ namespace OpenSim.Region.Physics.PhysXPlugin scene = mySdk.CreateScene(); } + public override void Initialise(IMesher meshmerizer) + { + // Does nothing right now + } + + public override PhysicsActor AddAvatar(string avName, PhysicsVector position) { Vec3 pos = new Vec3(); diff --git a/prebuild.xml b/prebuild.xml index 404a750..58ec667 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -251,7 +251,8 @@ - + + @@ -346,8 +347,9 @@ - - + + + @@ -356,6 +358,30 @@ + + + + ../../../../bin/Physics/ + + + + + ../../../../bin/Physics/ + + + + ../../../../bin/ + + + + + + + + + + + @@ -564,8 +590,10 @@ + - + + @@ -1108,3 +1136,4 @@ + -- cgit v1.1