aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/OdePlugin
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/OdePlugin')
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdePlugin.cs187
1 files changed, 176 insertions, 11 deletions
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index 8d142ab..e7592fb 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -28,10 +28,17 @@
28using System; 28using System;
29using System.Threading; 29using System.Threading;
30using System.Collections.Generic; 30using System.Collections.Generic;
31
32using libsecondlife;
33using libsecondlife.Utilities;
34
31using Axiom.Math; 35using Axiom.Math;
32using Ode.NET; 36using Ode.NET;
37using OpenSim.Framework.Types;
38using OpenSim.Framework.Console;
33using OpenSim.Region.Physics.Manager; 39using OpenSim.Region.Physics.Manager;
34 40
41
35namespace OpenSim.Region.Physics.OdePlugin 42namespace OpenSim.Region.Physics.OdePlugin
36{ 43{
37 /// <summary> 44 /// <summary>
@@ -77,8 +84,11 @@ namespace OpenSim.Region.Physics.OdePlugin
77 private IntPtr LandGeom; 84 private IntPtr LandGeom;
78 private double[] _heightmap; 85 private double[] _heightmap;
79 private d.NearCallback nearCallback; 86 private d.NearCallback nearCallback;
87 public d.TriCallback triCallback;
88 public d.TriArrayCallback triArrayCallback;
80 private List<OdeCharacter> _characters = new List<OdeCharacter>(); 89 private List<OdeCharacter> _characters = new List<OdeCharacter>();
81 private List<OdePrim> _prims = new List<OdePrim>(); 90 private List<OdePrim> _prims = new List<OdePrim>();
91 public Dictionary<IntPtr, String> geom_name_map=new Dictionary<IntPtr, String>();
82 private d.ContactGeom[] contacts = new d.ContactGeom[30]; 92 private d.ContactGeom[] contacts = new d.ContactGeom[30];
83 private d.Contact contact; 93 private d.Contact contact;
84 94
@@ -89,6 +99,8 @@ namespace OpenSim.Region.Physics.OdePlugin
89 public OdeScene() 99 public OdeScene()
90 { 100 {
91 nearCallback = near; 101 nearCallback = near;
102 triCallback = TriCallback;
103 triArrayCallback = TriArrayCallback;
92 contact.surface.mode |= d.ContactFlags.Approx1 | d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP; 104 contact.surface.mode |= d.ContactFlags.Approx1 | d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP;
93 contact.surface.mu = 10.0f; 105 contact.surface.mu = 10.0f;
94 contact.surface.bounce = 0.9f; 106 contact.surface.bounce = 0.9f;
@@ -112,12 +124,33 @@ namespace OpenSim.Region.Physics.OdePlugin
112 private void near(IntPtr space, IntPtr g1, IntPtr g2) 124 private void near(IntPtr space, IntPtr g1, IntPtr g2)
113 { 125 {
114 // no lock here! It's invoked from within Simulate(), which is thread-locked 126 // no lock here! It's invoked from within Simulate(), which is thread-locked
127 if (g1 == g2)
128 return; // Can't collide with yourself
129
115 IntPtr b1 = d.GeomGetBody(g1); 130 IntPtr b1 = d.GeomGetBody(g1);
116 IntPtr b2 = d.GeomGetBody(g2); 131 IntPtr b2 = d.GeomGetBody(g2);
132
117 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) 133 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
118 return; 134 return;
119 135
120 int count = d.Collide(g1, g2, 500, contacts, d.ContactGeom.SizeOf); 136 d.GeomClassID id = d.GeomGetClass(g1);
137 if (id==d.GeomClassID.TriMeshClass)
138 {
139 String name1 = null;
140 String name2 = null;
141 if (!geom_name_map.TryGetValue(g1, out name1))
142 {
143 name1 = "null";
144 }
145 if (!geom_name_map.TryGetValue(g2, out name2))
146 {
147 name2 = "null";
148 }
149
150// MainLog.Instance.Verbose("near: A collision was detected between {1} and {2}", 0, name1, name2);
151 }
152
153 int count = d.Collide(g1, g2, contacts.GetLength(0), contacts, d.ContactGeom.SizeOf);
121 for (int i = 0; i < count; i++) 154 for (int i = 0; i < count; i++)
122 { 155 {
123 contact.geom = contacts[i]; 156 contact.geom = contacts[i];
@@ -139,21 +172,24 @@ namespace OpenSim.Region.Physics.OdePlugin
139 } 172 }
140 } 173 }
141 174
142 public override PhysicsActor AddAvatar(PhysicsVector position) 175 public override PhysicsActor AddAvatar(string avName, PhysicsVector position)
143 { 176 {
144 PhysicsVector pos = new PhysicsVector(); 177 PhysicsVector pos = new PhysicsVector();
145 pos.X = position.X; 178 pos.X = position.X;
146 pos.Y = position.Y; 179 pos.Y = position.Y;
147 pos.Z = position.Z; 180 pos.Z = position.Z;
148 OdeCharacter newAv = new OdeCharacter(this, pos); 181 OdeCharacter newAv = new OdeCharacter(avName, this, pos);
149 _characters.Add(newAv); 182 _characters.Add(newAv);
150 return newAv; 183 return newAv;
151 } 184 }
152 185
153 public override void RemoveAvatar(PhysicsActor actor) 186 public override void RemoveAvatar(PhysicsActor actor)
154 { 187 {
155 ((OdeCharacter)actor).Destroy(); 188 lock (OdeLock)
156 _characters.Remove((OdeCharacter)actor); 189 {
190 ((OdeCharacter)actor).Destroy();
191 _characters.Remove((OdeCharacter)actor);
192 }
157 } 193 }
158 194
159 public override void RemovePrim(PhysicsActor prim) 195 public override void RemovePrim(PhysicsActor prim)
@@ -168,7 +204,7 @@ namespace OpenSim.Region.Physics.OdePlugin
168 } 204 }
169 } 205 }
170 206
171 public override PhysicsActor AddPrim(PhysicsVector position, PhysicsVector size, Quaternion rotation) 207 PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, Quaternion rotation, Mesh mesh, PrimitiveBaseShape pbs)
172 { 208 {
173 PhysicsVector pos = new PhysicsVector(); 209 PhysicsVector pos = new PhysicsVector();
174 pos.X = position.X; 210 pos.X = position.X;
@@ -186,12 +222,91 @@ namespace OpenSim.Region.Physics.OdePlugin
186 OdePrim newPrim; 222 OdePrim newPrim;
187 lock (OdeLock) 223 lock (OdeLock)
188 { 224 {
189 newPrim = new OdePrim(this, pos, siz, rot); 225 newPrim = new OdePrim(name, this, pos, siz, rot, mesh, pbs);
190 } 226 }
191 _prims.Add(newPrim); 227 _prims.Add(newPrim);
192 return newPrim; 228 return newPrim;
193 } 229 }
194 230
231
232 public int TriArrayCallback(System.IntPtr trimesh, System.IntPtr refObject, int[] triangleIndex, int triCount)
233 {
234/* String name1 = null;
235 String name2 = null;
236
237 if (!geom_name_map.TryGetValue(trimesh, out name1))
238 {
239 name1 = "null";
240 }
241 if (!geom_name_map.TryGetValue(refObject, out name2))
242 {
243 name2 = "null";
244 }
245
246 MainLog.Instance.Verbose("TriArrayCallback: A collision was detected between {1} and {2}", 0, name1, name2);
247*/
248 return 1;
249 }
250
251 public int TriCallback(System.IntPtr trimesh, System.IntPtr refObject, int triangleIndex)
252 {
253
254 String name1 = null;
255 String name2 = null;
256
257 if (!geom_name_map.TryGetValue(trimesh, out name1))
258 {
259 Console.WriteLine("+++ nulling " + name1);
260 name1 = "null";
261 }
262 if (!geom_name_map.TryGetValue(refObject, out name2))
263 {
264 Console.WriteLine("+++ nulling " + name2);
265 name2 = "null";
266 }
267
268// MainLog.Instance.Verbose("TriCallback: A collision was detected between {1} and {2}. Index was {3}", 0, name1, name2, triangleIndex);
269
270 d.Vector3 v0 = new d.Vector3();
271 d.Vector3 v1 = new d.Vector3();
272 d.Vector3 v2 = new d.Vector3();
273
274 d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2);
275 MainLog.Instance.Debug("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);
276
277 return 1;
278 }
279
280
281 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, Quaternion rotation)
282 {
283 PhysicsActor result;
284
285 switch(pbs.ProfileShape)
286 {
287 case ProfileShape.Square:
288 /// support simple box & hollow box now; later, more shapes
289 if (pbs.ProfileHollow == 0)
290 {
291 result = AddPrim(primName, position, size, rotation, null, null);
292 }
293 else
294 {
295 Mesh mesh = Meshmerizer.CreateMesh(pbs, size);
296 result = AddPrim(primName, position, size, rotation, mesh, pbs);
297 }
298 break;
299
300 default:
301 result = AddPrim(primName, position, size, rotation, null, null);
302 break;
303 }
304
305 return result;
306 }
307
308
309
195 public override void Simulate(float timeStep) 310 public override void Simulate(float timeStep)
196 { 311 {
197 lock (OdeLock) 312 lock (OdeLock)
@@ -247,6 +362,8 @@ namespace OpenSim.Region.Physics.OdePlugin
247 d.GeomHeightfieldDataBuildDouble(HeightmapData, _heightmap, 0, 256, 256, 256, 256, 1.0f, 0.0f, 2.0f, 0); 362 d.GeomHeightfieldDataBuildDouble(HeightmapData, _heightmap, 0, 256, 256, 256, 256, 1.0f, 0.0f, 2.0f, 0);
248 d.GeomHeightfieldDataSetBounds(HeightmapData, 256, 256); 363 d.GeomHeightfieldDataSetBounds(HeightmapData, 256, 256);
249 LandGeom = d.CreateHeightfield(space, HeightmapData, 1); 364 LandGeom = d.CreateHeightfield(space, HeightmapData, 1);
365 this.geom_name_map[LandGeom]="Terrain";
366
250 d.Matrix3 R = new d.Matrix3(); 367 d.Matrix3 R = new d.Matrix3();
251 368
252 Quaternion q1 = Quaternion.FromAngleAxis(1.5707f, new Vector3(1, 0, 0)); 369 Quaternion q1 = Quaternion.FromAngleAxis(1.5707f, new Vector3(1, 0, 0));
@@ -285,7 +402,7 @@ namespace OpenSim.Region.Physics.OdePlugin
285 public IntPtr capsule_geom; 402 public IntPtr capsule_geom;
286 public d.Mass capsule_mass; 403 public d.Mass capsule_mass;
287 404
288 public OdeCharacter(OdeScene parent_scene, PhysicsVector pos) 405 public OdeCharacter(String avName, OdeScene parent_scene, PhysicsVector pos)
289 { 406 {
290 _velocity = new PhysicsVector(); 407 _velocity = new PhysicsVector();
291 _position = pos; 408 _position = pos;
@@ -300,6 +417,8 @@ namespace OpenSim.Region.Physics.OdePlugin
300 d.BodySetPosition(BoundingCapsule, pos.X, pos.Y, pos.Z); 417 d.BodySetPosition(BoundingCapsule, pos.X, pos.Y, pos.Z);
301 d.GeomSetBody(capsule_geom, BoundingCapsule); 418 d.GeomSetBody(capsule_geom, BoundingCapsule);
302 } 419 }
420 parent_scene.geom_name_map[capsule_geom]=avName;
421
303 } 422 }
304 423
305 public override bool Flying 424 public override bool Flying
@@ -454,6 +573,8 @@ namespace OpenSim.Region.Physics.OdePlugin
454 lock (OdeScene.OdeLock) 573 lock (OdeScene.OdeLock)
455 { 574 {
456 d.GeomDestroy(this.capsule_geom); 575 d.GeomDestroy(this.capsule_geom);
576 Console.WriteLine("+++ removing geom");
577 this._parent_scene.geom_name_map.Remove(this.capsule_geom);
457 d.BodyDestroy(this.BoundingCapsule); 578 d.BodyDestroy(this.BoundingCapsule);
458 } 579 }
459 } 580 }
@@ -466,18 +587,35 @@ namespace OpenSim.Region.Physics.OdePlugin
466 private PhysicsVector _size; 587 private PhysicsVector _size;
467 private PhysicsVector _acceleration; 588 private PhysicsVector _acceleration;
468 private Quaternion _orientation; 589 private Quaternion _orientation;
590 private Mesh _mesh;
591 private PrimitiveBaseShape _pbs;
592 private OdeScene _parent_scene;
469 public IntPtr prim_geom; 593 public IntPtr prim_geom;
594 public IntPtr _triMeshData;
470 595
471 public OdePrim(OdeScene parent_scene, PhysicsVector pos, PhysicsVector size, Quaternion rotation) 596 public OdePrim(String primName, OdeScene parent_scene, PhysicsVector pos, PhysicsVector size,
597 Quaternion rotation, Mesh mesh, PrimitiveBaseShape pbs)
472 { 598 {
473 _velocity = new PhysicsVector(); 599 _velocity = new PhysicsVector();
474 _position = pos; 600 _position = pos;
475 _size = size; 601 _size = size;
476 _acceleration = new PhysicsVector(); 602 _acceleration = new PhysicsVector();
477 _orientation = rotation; 603 _orientation = rotation;
604 _mesh = mesh;
605 _pbs = pbs;
606 _parent_scene = parent_scene;
607
478 lock (OdeScene.OdeLock) 608 lock (OdeScene.OdeLock)
479 { 609 {
480 prim_geom = d.CreateBox(parent_scene.space, _size.X, _size.Y, _size.Z); 610 if (mesh!=null)
611 {
612 setMesh(parent_scene, mesh);
613 }
614 else
615 {
616 prim_geom = d.CreateBox(parent_scene.space, _size.X, _size.Y, _size.Z);
617 }
618
481 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 619 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
482 d.Quaternion myrot = new d.Quaternion(); 620 d.Quaternion myrot = new d.Quaternion();
483 myrot.W = rotation.w; 621 myrot.W = rotation.w;
@@ -485,9 +623,25 @@ namespace OpenSim.Region.Physics.OdePlugin
485 myrot.Y = rotation.y; 623 myrot.Y = rotation.y;
486 myrot.Z = rotation.z; 624 myrot.Z = rotation.z;
487 d.GeomSetQuaternion(prim_geom, ref myrot); 625 d.GeomSetQuaternion(prim_geom, ref myrot);
626 parent_scene.geom_name_map[prim_geom] = primName; // don't do .add() here; old geoms get recycled with the same hash
488 } 627 }
489 } 628 }
490 629
630 public void setMesh(OdeScene parent_scene, Mesh mesh)
631 {
632 float[] vertexList = mesh.getVertexListAsFloat(); // Note, that vertextList is pinned in memory
633 int[] indexList = mesh.getIndexListAsInt(); // Also pinned, needs release after usage
634 int VertexCount = vertexList.GetLength(0) / 3;
635 int IndexCount = indexList.GetLength(0);
636
637 _triMeshData = d.GeomTriMeshDataCreate();
638
639 d.GeomTriMeshDataBuildSimple(_triMeshData, vertexList, 3 * sizeof(float), VertexCount, indexList, IndexCount, 3 * sizeof(int));
640 d.GeomTriMeshDataPreprocess(_triMeshData);
641
642 prim_geom = d.CreateTriMesh(parent_scene.space, _triMeshData, parent_scene.triCallback, parent_scene.triArrayCallback, null);
643 }
644
491 public override bool Flying 645 public override bool Flying
492 { 646 {
493 get 647 get
@@ -526,7 +680,18 @@ namespace OpenSim.Region.Physics.OdePlugin
526 _size = value; 680 _size = value;
527 lock (OdeScene.OdeLock) 681 lock (OdeScene.OdeLock)
528 { 682 {
529 d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z); 683 if (_mesh != null) // We deal with a mesh here
684 {
685 string oldname = _parent_scene.geom_name_map[prim_geom];
686 d.GeomDestroy(prim_geom);
687 Mesh mesh = Meshmerizer.CreateMesh(_pbs, _size);
688 setMesh(_parent_scene, mesh);
689 _parent_scene.geom_name_map[prim_geom] = oldname;
690 }
691 else
692 {
693 d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
694 }
530 } 695 }
531 } 696 }
532 } 697 }