diff options
Diffstat (limited to 'OpenSim/Region/Physics/OdePlugin/OdePlugin.cs')
-rw-r--r-- | OpenSim/Region/Physics/OdePlugin/OdePlugin.cs | 187 |
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 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.Threading; | 29 | using System.Threading; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | |||
32 | using libsecondlife; | ||
33 | using libsecondlife.Utilities; | ||
34 | |||
31 | using Axiom.Math; | 35 | using Axiom.Math; |
32 | using Ode.NET; | 36 | using Ode.NET; |
37 | using OpenSim.Framework.Types; | ||
38 | using OpenSim.Framework.Console; | ||
33 | using OpenSim.Region.Physics.Manager; | 39 | using OpenSim.Region.Physics.Manager; |
34 | 40 | ||
41 | |||
35 | namespace OpenSim.Region.Physics.OdePlugin | 42 | namespace 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 | } |