diff options
Diffstat (limited to '')
17 files changed, 1963 insertions, 64 deletions
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 | |||
54 | private const string DEFAULT_PRIM_BACKUP_FILENAME = "prim-backup.xml"; | 54 | private const string DEFAULT_PRIM_BACKUP_FILENAME = "prim-backup.xml"; |
55 | 55 | ||
56 | public string m_physicsEngine; | 56 | public string m_physicsEngine; |
57 | public string m_meshEngineName; | ||
57 | public string m_scriptEngine; | 58 | public string m_scriptEngine; |
58 | public bool m_sandbox; | 59 | public bool m_sandbox; |
59 | public bool user_accounts; | 60 | public bool user_accounts; |
@@ -210,6 +211,7 @@ namespace OpenSim | |||
210 | { | 211 | { |
211 | m_sandbox = !startupConfig.GetBoolean("gridmode", false); | 212 | m_sandbox = !startupConfig.GetBoolean("gridmode", false); |
212 | m_physicsEngine = startupConfig.GetString("physics", "basicphysics"); | 213 | m_physicsEngine = startupConfig.GetString("physics", "basicphysics"); |
214 | m_meshEngineName = startupConfig.GetString("meshing", "Meshmerizer"); | ||
213 | m_verbose = startupConfig.GetBoolean("verbose", true); | 215 | m_verbose = startupConfig.GetBoolean("verbose", true); |
214 | m_permissions = startupConfig.GetBoolean("serverside_object_permissions", false); | 216 | m_permissions = startupConfig.GetBoolean("serverside_object_permissions", false); |
215 | 217 | ||
@@ -404,7 +406,7 @@ namespace OpenSim | |||
404 | 406 | ||
405 | protected override PhysicsScene GetPhysicsScene() | 407 | protected override PhysicsScene GetPhysicsScene() |
406 | { | 408 | { |
407 | return GetPhysicsScene(m_physicsEngine); | 409 | return GetPhysicsScene(m_physicsEngine, m_meshEngineName); |
408 | } | 410 | } |
409 | 411 | ||
410 | private class SimStatusHandler : IStreamedRequestHandler | 412 | private class SimStatusHandler : IStreamedRequestHandler |
@@ -767,4 +769,4 @@ namespace OpenSim | |||
767 | 769 | ||
768 | #endregion | 770 | #endregion |
769 | } | 771 | } |
770 | } \ No newline at end of file | 772 | } |
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; | |||
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Net; | 30 | using System.Net; |
31 | using libsecondlife; | 31 | using libsecondlife; |
32 | using Nini.Config; | ||
32 | using OpenSim.Framework; | 33 | using OpenSim.Framework; |
33 | using OpenSim.Framework.Communications; | 34 | using OpenSim.Framework.Communications; |
34 | using OpenSim.Framework.Communications.Cache; | 35 | using OpenSim.Framework.Communications.Cache; |
@@ -89,12 +90,12 @@ namespace OpenSim.Region.ClientStack | |||
89 | protected abstract PhysicsScene GetPhysicsScene(); | 90 | protected abstract PhysicsScene GetPhysicsScene(); |
90 | protected abstract StorageManager CreateStorageManager(RegionInfo regionInfo); | 91 | protected abstract StorageManager CreateStorageManager(RegionInfo regionInfo); |
91 | 92 | ||
92 | protected PhysicsScene GetPhysicsScene(string engine) | 93 | protected PhysicsScene GetPhysicsScene(string engine, string meshEngine) |
93 | { | 94 | { |
94 | PhysicsPluginManager physicsPluginManager; | 95 | PhysicsPluginManager physicsPluginManager; |
95 | physicsPluginManager = new PhysicsPluginManager(); | 96 | physicsPluginManager = new PhysicsPluginManager(); |
96 | physicsPluginManager.LoadPlugins(); | 97 | physicsPluginManager.LoadPlugins(); |
97 | return physicsPluginManager.GetPhysicsScene(engine); | 98 | return physicsPluginManager.GetPhysicsScene(engine, meshEngine); |
98 | } | 99 | } |
99 | 100 | ||
100 | protected Scene SetupScene(RegionInfo regionInfo, out UDPServer udpServer) | 101 | protected Scene SetupScene(RegionInfo regionInfo, out UDPServer udpServer) |
@@ -150,4 +151,4 @@ namespace OpenSim.Region.ClientStack | |||
150 | protected abstract Scene CreateScene(RegionInfo regionInfo, StorageManager storageManager, | 151 | protected abstract Scene CreateScene(RegionInfo regionInfo, StorageManager storageManager, |
151 | AgentCircuitManager circuitManager); | 152 | AgentCircuitManager circuitManager); |
152 | } | 153 | } |
153 | } \ No newline at end of file | 154 | } |
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 | |||
182 | 182 | ||
183 | protected override PhysicsScene GetPhysicsScene() | 183 | protected override PhysicsScene GetPhysicsScene() |
184 | { | 184 | { |
185 | return GetPhysicsScene("basicphysics"); | 185 | return GetPhysicsScene("basicphysics", "Meshmerizer"); |
186 | } | 186 | } |
187 | 187 | ||
188 | #region conscmd_callback Members | 188 | #region conscmd_callback Members |
@@ -206,4 +206,4 @@ namespace SimpleApp | |||
206 | app.Run(); | 206 | app.Run(); |
207 | } | 207 | } |
208 | } | 208 | } |
209 | } \ No newline at end of file | 209 | } |
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 | |||
70 | { | 70 | { |
71 | } | 71 | } |
72 | 72 | ||
73 | public override void Initialise(IMesher meshmerizer) | ||
74 | { | ||
75 | // Does nothing right now | ||
76 | } | ||
77 | |||
73 | public override PhysicsActor AddAvatar(string avName, PhysicsVector position) | 78 | public override PhysicsActor AddAvatar(string avName, PhysicsVector position) |
74 | { | 79 | { |
75 | BasicActor act = new BasicActor(); | 80 | BasicActor act = new BasicActor(); |
@@ -274,4 +279,4 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin | |||
274 | { | 279 | { |
275 | } | 280 | } |
276 | } | 281 | } |
277 | } \ No newline at end of file | 282 | } |
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; | |||
64 | using System.Collections.Generic; | 64 | using System.Collections.Generic; |
65 | using MonoXnaCompactMaths; | 65 | using MonoXnaCompactMaths; |
66 | using OpenSim.Framework; | 66 | using OpenSim.Framework; |
67 | using OpenSim.Framework.Console; | ||
67 | using OpenSim.Region.Physics.Manager; | 68 | using OpenSim.Region.Physics.Manager; |
68 | using XnaDevRu.BulletX; | 69 | using XnaDevRu.BulletX; |
69 | using XnaDevRu.BulletX.Dynamics; | 70 | using XnaDevRu.BulletX.Dynamics; |
@@ -74,15 +75,6 @@ using BoxShape=XnaDevRu.BulletX.BoxShape; | |||
74 | 75 | ||
75 | namespace OpenSim.Region.Physics.BulletXPlugin | 76 | namespace OpenSim.Region.Physics.BulletXPlugin |
76 | { | 77 | { |
77 | /// <summary> | ||
78 | /// This class is only here for compilations reasons | ||
79 | /// </summary> | ||
80 | public class Mesh | ||
81 | { | ||
82 | public Mesh() | ||
83 | { | ||
84 | } | ||
85 | } | ||
86 | 78 | ||
87 | /// <summary> | 79 | /// <summary> |
88 | /// BulletXConversions are called now BulletXMaths | 80 | /// BulletXConversions are called now BulletXMaths |
@@ -268,6 +260,65 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
268 | } | 260 | } |
269 | } | 261 | } |
270 | 262 | ||
263 | |||
264 | // Class to detect and debug collisions | ||
265 | // Mainly used for debugging purposes | ||
266 | class CollisionDispatcherLocal : CollisionDispatcher | ||
267 | { | ||
268 | |||
269 | BulletXScene relatedScene; | ||
270 | |||
271 | public CollisionDispatcherLocal(BulletXScene s) | ||
272 | : base() | ||
273 | { | ||
274 | relatedScene=s; | ||
275 | } | ||
276 | |||
277 | public override bool NeedsCollision(CollisionObject bodyA, CollisionObject bodyB) | ||
278 | { | ||
279 | RigidBody rb; | ||
280 | BulletXCharacter bxcA=null; | ||
281 | BulletXPrim bxpA = null; | ||
282 | Type t = bodyA.GetType(); | ||
283 | if (t==typeof(RigidBody)) { | ||
284 | rb = (RigidBody)bodyA; | ||
285 | relatedScene._characters.TryGetValue(rb, out bxcA); | ||
286 | relatedScene._prims.TryGetValue(rb, out bxpA); | ||
287 | } | ||
288 | String nameA; | ||
289 | if (bxcA != null) | ||
290 | nameA = bxcA._name; | ||
291 | else if (bxpA != null) | ||
292 | nameA = bxpA._name; | ||
293 | else | ||
294 | nameA = "null"; | ||
295 | |||
296 | BulletXCharacter bxcB = null; | ||
297 | BulletXPrim bxpB = null; | ||
298 | t = bodyB.GetType(); | ||
299 | if (t == typeof(RigidBody)) | ||
300 | { | ||
301 | rb = (RigidBody)bodyB; | ||
302 | relatedScene._characters.TryGetValue(rb, out bxcB); | ||
303 | relatedScene._prims.TryGetValue(rb, out bxpB); | ||
304 | } | ||
305 | String nameB; | ||
306 | if (bxcB != null) | ||
307 | nameB = bxcB._name; | ||
308 | else if (bxpB != null) | ||
309 | nameB = bxpB._name; | ||
310 | else | ||
311 | nameB = "null"; | ||
312 | |||
313 | bool needsCollision=base.NeedsCollision(bodyA, bodyB); | ||
314 | |||
315 | MainLog.Instance.Debug("BulletX", "A collision was detected between {0} and {1} --> {2}", nameA, nameB, needsCollision); | ||
316 | |||
317 | |||
318 | return needsCollision; | ||
319 | } | ||
320 | } | ||
321 | |||
271 | /// <summary> | 322 | /// <summary> |
272 | /// PhysicsScene Class for BulletX | 323 | /// PhysicsScene Class for BulletX |
273 | /// </summary> | 324 | /// </summary> |
@@ -294,8 +345,11 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
294 | private const int simulationSubSteps = 10; | 345 | private const int simulationSubSteps = 10; |
295 | //private float[] _heightmap; | 346 | //private float[] _heightmap; |
296 | private BulletXPlanet _simFlatPlanet; | 347 | private BulletXPlanet _simFlatPlanet; |
297 | private List<BulletXCharacter> _characters = new List<BulletXCharacter>(); | 348 | internal Dictionary<RigidBody, BulletXCharacter> _characters = new Dictionary<RigidBody, BulletXCharacter>(); |
298 | private List<BulletXPrim> _prims = new List<BulletXPrim>(); | 349 | internal Dictionary<RigidBody, BulletXPrim> _prims = new Dictionary<RigidBody, BulletXPrim>(); |
350 | |||
351 | public IMesher mesher; | ||
352 | |||
299 | 353 | ||
300 | public static float Gravity | 354 | public static float Gravity |
301 | { | 355 | { |
@@ -334,7 +388,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
334 | 388 | ||
335 | public BulletXScene() | 389 | public BulletXScene() |
336 | { | 390 | { |
337 | cDispatcher = new CollisionDispatcher(); | 391 | cDispatcher = new CollisionDispatcherLocal(this); |
338 | Vector3 worldMinDim = new Vector3((float) minXY, (float) minXY, (float) minZ); | 392 | Vector3 worldMinDim = new Vector3((float) minXY, (float) minXY, (float) minZ); |
339 | Vector3 worldMaxDim = new Vector3((float) maxXY, (float) maxXY, (float) maxZ); | 393 | Vector3 worldMaxDim = new Vector3((float) maxXY, (float) maxXY, (float) maxZ); |
340 | opCache = new AxisSweep3(worldMinDim, worldMaxDim, maxHandles); | 394 | opCache = new AxisSweep3(worldMinDim, worldMaxDim, maxHandles); |
@@ -348,6 +402,12 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
348 | //this._heightmap = new float[65536]; | 402 | //this._heightmap = new float[65536]; |
349 | } | 403 | } |
350 | 404 | ||
405 | public override void Initialise(IMesher meshmerizer) | ||
406 | { | ||
407 | mesher = meshmerizer; | ||
408 | } | ||
409 | |||
410 | |||
351 | public override PhysicsActor AddAvatar(string avName, PhysicsVector position) | 411 | public override PhysicsActor AddAvatar(string avName, PhysicsVector position) |
352 | { | 412 | { |
353 | PhysicsVector pos = new PhysicsVector(); | 413 | PhysicsVector pos = new PhysicsVector(); |
@@ -358,7 +418,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
358 | lock (BulletXLock) | 418 | lock (BulletXLock) |
359 | { | 419 | { |
360 | newAv = new BulletXCharacter(avName, this, pos); | 420 | newAv = new BulletXCharacter(avName, this, pos); |
361 | _characters.Add(newAv); | 421 | _characters.Add(newAv.RigidBody, newAv); |
362 | } | 422 | } |
363 | return newAv; | 423 | return newAv; |
364 | } | 424 | } |
@@ -379,7 +439,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
379 | ((BulletXCharacter) actor).RigidBody.ActivationState = ActivationState.DisableSimulation; | 439 | ((BulletXCharacter) actor).RigidBody.ActivationState = ActivationState.DisableSimulation; |
380 | AddForgottenRigidBody(((BulletXCharacter) actor).RigidBody); | 440 | AddForgottenRigidBody(((BulletXCharacter) actor).RigidBody); |
381 | } | 441 | } |
382 | _characters.Remove((BulletXCharacter) actor); | 442 | _characters.Remove(((BulletXCharacter)actor).RigidBody); |
383 | } | 443 | } |
384 | GC.Collect(); | 444 | GC.Collect(); |
385 | } | 445 | } |
@@ -405,7 +465,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
405 | } | 465 | } |
406 | else | 466 | else |
407 | { | 467 | { |
408 | Mesh mesh = null; | 468 | IMesh mesh = mesher.CreateMesh(primName, pbs, size); |
409 | result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical); | 469 | result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical); |
410 | } | 470 | } |
411 | break; | 471 | break; |
@@ -419,13 +479,13 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
419 | } | 479 | } |
420 | 480 | ||
421 | public PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, AxiomQuaternion rotation, | 481 | public PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, AxiomQuaternion rotation, |
422 | Mesh mesh, PrimitiveBaseShape pbs, bool isPhysical) | 482 | IMesh mesh, PrimitiveBaseShape pbs, bool isPhysical) |
423 | { | 483 | { |
424 | BulletXPrim newPrim = null; | 484 | BulletXPrim newPrim = null; |
425 | lock (BulletXLock) | 485 | lock (BulletXLock) |
426 | { | 486 | { |
427 | newPrim = new BulletXPrim(name, this, position, size, rotation, mesh, pbs, isPhysical); | 487 | newPrim = new BulletXPrim(name, this, position, size, rotation, mesh, pbs, isPhysical); |
428 | _prims.Add(newPrim); | 488 | _prims.Add(newPrim.RigidBody, newPrim); |
429 | } | 489 | } |
430 | return newPrim; | 490 | return newPrim; |
431 | } | 491 | } |
@@ -446,7 +506,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
446 | ((BulletXPrim) prim).RigidBody.ActivationState = ActivationState.DisableSimulation; | 506 | ((BulletXPrim) prim).RigidBody.ActivationState = ActivationState.DisableSimulation; |
447 | AddForgottenRigidBody(((BulletXPrim) prim).RigidBody); | 507 | AddForgottenRigidBody(((BulletXPrim) prim).RigidBody); |
448 | } | 508 | } |
449 | _prims.Remove((BulletXPrim) prim); | 509 | _prims.Remove(((BulletXPrim) prim).RigidBody); |
450 | } | 510 | } |
451 | GC.Collect(); | 511 | GC.Collect(); |
452 | } | 512 | } |
@@ -470,11 +530,11 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
470 | 530 | ||
471 | private void MoveAllObjects(float timeStep) | 531 | private void MoveAllObjects(float timeStep) |
472 | { | 532 | { |
473 | foreach (BulletXCharacter actor in _characters) | 533 | foreach (BulletXCharacter actor in _characters.Values) |
474 | { | 534 | { |
475 | actor.Move(timeStep); | 535 | actor.Move(timeStep); |
476 | } | 536 | } |
477 | foreach (BulletXPrim prim in _prims) | 537 | foreach (BulletXPrim prim in _prims.Values) |
478 | { | 538 | { |
479 | } | 539 | } |
480 | } | 540 | } |
@@ -482,14 +542,14 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
482 | private void ValidateHeightForAll() | 542 | private void ValidateHeightForAll() |
483 | { | 543 | { |
484 | float _height; | 544 | float _height; |
485 | foreach (BulletXCharacter actor in _characters) | 545 | foreach (BulletXCharacter actor in _characters.Values) |
486 | { | 546 | { |
487 | //_height = HeightValue(actor.RigidBodyPosition); | 547 | //_height = HeightValue(actor.RigidBodyPosition); |
488 | _height = _simFlatPlanet.HeightValue(actor.RigidBodyPosition); | 548 | _height = _simFlatPlanet.HeightValue(actor.RigidBodyPosition); |
489 | actor.ValidateHeight(_height); | 549 | actor.ValidateHeight(_height); |
490 | //if (_simFlatPlanet.heightIsNotValid(actor.RigidBodyPosition, out _height)) actor.ValidateHeight(_height); | 550 | //if (_simFlatPlanet.heightIsNotValid(actor.RigidBodyPosition, out _height)) actor.ValidateHeight(_height); |
491 | } | 551 | } |
492 | foreach (BulletXPrim prim in _prims) | 552 | foreach (BulletXPrim prim in _prims.Values) |
493 | { | 553 | { |
494 | //_height = HeightValue(prim.RigidBodyPosition); | 554 | //_height = HeightValue(prim.RigidBodyPosition); |
495 | _height = _simFlatPlanet.HeightValue(prim.RigidBodyPosition); | 555 | _height = _simFlatPlanet.HeightValue(prim.RigidBodyPosition); |
@@ -510,11 +570,11 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
510 | { | 570 | { |
511 | //UpdatePosition > UpdateKinetics. | 571 | //UpdatePosition > UpdateKinetics. |
512 | //Not only position will be updated, also velocity cause acceleration. | 572 | //Not only position will be updated, also velocity cause acceleration. |
513 | foreach (BulletXCharacter actor in _characters) | 573 | foreach (BulletXCharacter actor in _characters.Values) |
514 | { | 574 | { |
515 | actor.UpdateKinetics(); | 575 | actor.UpdateKinetics(); |
516 | } | 576 | } |
517 | foreach (BulletXPrim prim in _prims) | 577 | foreach (BulletXPrim prim in _prims.Values) |
518 | { | 578 | { |
519 | prim.UpdateKinetics(); | 579 | prim.UpdateKinetics(); |
520 | } | 580 | } |
@@ -646,9 +706,11 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
646 | protected PhysicsVector m_rotationalVelocity = PhysicsVector.Zero; | 706 | protected PhysicsVector m_rotationalVelocity = PhysicsVector.Zero; |
647 | protected RigidBody rigidBody; | 707 | protected RigidBody rigidBody; |
648 | private Boolean iscolliding = false; | 708 | private Boolean iscolliding = false; |
709 | internal string _name; | ||
649 | 710 | ||
650 | public BulletXActor() | 711 | public BulletXActor(String name) |
651 | { | 712 | { |
713 | _name = name; | ||
652 | } | 714 | } |
653 | 715 | ||
654 | public override PhysicsVector Position | 716 | public override PhysicsVector Position |
@@ -847,6 +909,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
847 | } | 909 | } |
848 | public BulletXCharacter(String avName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector velocity, | 910 | public BulletXCharacter(String avName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector velocity, |
849 | PhysicsVector size, PhysicsVector acceleration, AxiomQuaternion orientation) | 911 | PhysicsVector size, PhysicsVector acceleration, AxiomQuaternion orientation) |
912 | : base(avName) | ||
850 | { | 913 | { |
851 | //This fields will be removed. They're temporal | 914 | //This fields will be removed. They're temporal |
852 | float _sizeX = 0.5f; | 915 | float _sizeX = 0.5f; |
@@ -1016,14 +1079,15 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
1016 | private bool m_lastUpdateSent = false; | 1079 | private bool m_lastUpdateSent = false; |
1017 | 1080 | ||
1018 | public BulletXPrim(String primName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector size, | 1081 | public BulletXPrim(String primName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector size, |
1019 | AxiomQuaternion rotation, Mesh mesh, PrimitiveBaseShape pbs, bool isPhysical) | 1082 | AxiomQuaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool isPhysical) |
1020 | : this(primName, parent_scene, pos, new PhysicsVector(), size, new PhysicsVector(), rotation, mesh, pbs, isPhysical) | 1083 | : this(primName, parent_scene, pos, new PhysicsVector(), size, new PhysicsVector(), rotation, mesh, pbs, isPhysical) |
1021 | { | 1084 | { |
1022 | } | 1085 | } |
1023 | public BulletXPrim(String primName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector velocity, | 1086 | public BulletXPrim(String primName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector velocity, |
1024 | PhysicsVector size, | 1087 | PhysicsVector size, |
1025 | PhysicsVector acceleration, AxiomQuaternion rotation, Mesh mesh, PrimitiveBaseShape pbs, | 1088 | PhysicsVector acceleration, AxiomQuaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, |
1026 | bool isPhysical) | 1089 | bool isPhysical) |
1090 | : base(primName) | ||
1027 | { | 1091 | { |
1028 | if ((size.X == 0) || (size.Y == 0) || (size.Z == 0)) throw new Exception("Size 0"); | 1092 | if ((size.X == 0) || (size.Y == 0) || (size.Z == 0)) throw new Exception("Size 0"); |
1029 | if (rotation.Norm == 0f) rotation = AxiomQuaternion.Identity; | 1093 | if (rotation.Norm == 0f) rotation = AxiomQuaternion.Identity; |
@@ -1037,7 +1101,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
1037 | 1101 | ||
1038 | _parent_scene = parent_scene; | 1102 | _parent_scene = parent_scene; |
1039 | 1103 | ||
1040 | CreateRigidBody(parent_scene, pos, size); | 1104 | CreateRigidBody(parent_scene, mesh, pos, size); |
1041 | } | 1105 | } |
1042 | 1106 | ||
1043 | public override PhysicsVector Position | 1107 | public override PhysicsVector Position |
@@ -1191,7 +1255,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
1191 | } | 1255 | } |
1192 | 1256 | ||
1193 | #region Methods for updating values of RigidBody | 1257 | #region Methods for updating values of RigidBody |
1194 | internal protected void CreateRigidBody(BulletXScene parent_scene, PhysicsVector pos, PhysicsVector size) | 1258 | internal protected void CreateRigidBody(BulletXScene parent_scene, IMesh mesh, PhysicsVector pos, PhysicsVector size) |
1195 | { | 1259 | { |
1196 | //For RigidBody Constructor. The next values might change | 1260 | //For RigidBody Constructor. The next values might change |
1197 | float _linearDamping = 0.0f; | 1261 | float _linearDamping = 0.0f; |
@@ -1204,7 +1268,26 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
1204 | { | 1268 | { |
1205 | _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(pos); | 1269 | _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(pos); |
1206 | //For now all prims are boxes | 1270 | //For now all prims are boxes |
1207 | CollisionShape _collisionShape = new XnaDevRu.BulletX.BoxShape(BulletXMaths.PhysicsVectorToXnaVector3(size) / 2.0f); | 1271 | CollisionShape _collisionShape; |
1272 | if (mesh == null) | ||
1273 | { | ||
1274 | _collisionShape = new XnaDevRu.BulletX.BoxShape(BulletXMaths.PhysicsVectorToXnaVector3(size) / 2.0f); | ||
1275 | } else { | ||
1276 | int iVertexCount = mesh.getVertexList().Count; | ||
1277 | int[] indices = mesh.getIndexListAsInt(); | ||
1278 | Vector3[] v3Vertices = new Vector3[iVertexCount]; | ||
1279 | for (int i = 0; i < iVertexCount; i++) | ||
1280 | { | ||
1281 | PhysicsVector v=mesh.getVertexList()[i]; | ||
1282 | if (v != null) // Note, null has special meaning. See meshing code for details | ||
1283 | v3Vertices[i] = BulletXMaths.PhysicsVectorToXnaVector3(v); | ||
1284 | else | ||
1285 | v3Vertices[i] = MonoXnaCompactMaths.Vector3.Zero; | ||
1286 | } | ||
1287 | TriangleIndexVertexArray triMesh = new TriangleIndexVertexArray(indices, v3Vertices); | ||
1288 | |||
1289 | _collisionShape = new XnaDevRu.BulletX.TriangleMeshShape(triMesh); | ||
1290 | } | ||
1208 | DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset); | 1291 | DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset); |
1209 | Vector3 _localInertia = new Vector3(); | 1292 | Vector3 _localInertia = new Vector3(); |
1210 | if (_physical) _collisionShape.CalculateLocalInertia(Mass, out _localInertia); //Always when mass > 0 | 1293 | if (_physical) _collisionShape.CalculateLocalInertia(Mass, out _localInertia); //Always when mass > 0 |
@@ -1231,7 +1314,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin | |||
1231 | rigidBody.ActivationState = ActivationState.DisableSimulation; | 1314 | rigidBody.ActivationState = ActivationState.DisableSimulation; |
1232 | this._parent_scene.AddForgottenRigidBody(rigidBody); | 1315 | this._parent_scene.AddForgottenRigidBody(rigidBody); |
1233 | } | 1316 | } |
1234 | CreateRigidBody(this._parent_scene, this._position, size); | 1317 | 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 |
1235 | if (_physical) Speed();//Static objects don't have linear velocity | 1318 | if (_physical) Speed();//Static objects don't have linear velocity |
1236 | ReOrient(); | 1319 | ReOrient(); |
1237 | GC.Collect(); | 1320 | 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 @@ | |||
1 | /* | ||
2 | Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru | ||
3 | Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com | ||
4 | |||
5 | This software is provided 'as-is', without any express or implied | ||
6 | warranty. In no event will the authors be held liable for any damages | ||
7 | arising from the use of this software. | ||
8 | |||
9 | Permission is granted to anyone to use this software for any purpose, | ||
10 | including commercial applications, and to alter it and redistribute it | ||
11 | freely, subject to the following restrictions: | ||
12 | |||
13 | 1. The origin of this software must not be misrepresented; you must not | ||
14 | claim that you wrote the original software. If you use this software | ||
15 | in a product, an acknowledgment in the product documentation would be | ||
16 | appreciated but is not required. | ||
17 | 2. Altered source versions must be plainly marked as such, and must not be | ||
18 | misrepresented as being the original software. | ||
19 | 3. This notice may not be removed or altered from any source distribution. | ||
20 | */ | ||
21 | |||
22 | /* | ||
23 | |||
24 | This file contains a class TriangleIndexVertexArray. I tried using the class with the same name | ||
25 | from the BulletX implementation and found it unusable for the purpose of using triangle meshes | ||
26 | within BulletX as the implementation was painfully incomplete. | ||
27 | The attempt to derive from the original class failed as viable members were hidden. | ||
28 | Fiddling around with BulletX itself was not my intention. | ||
29 | So I copied the class to the BulletX-plugin and modified it. | ||
30 | If you want to fiddle around with it it's up to you to move all this to BulletX. | ||
31 | If someone someday implements the missing functionality in BulletX, feel free to remove this class. | ||
32 | It's just an ugly hack. | ||
33 | |||
34 | */ | ||
35 | using System; | ||
36 | using System.Collections.Generic; | ||
37 | using System.Text; | ||
38 | using MonoXnaCompactMaths; | ||
39 | |||
40 | namespace OpenSim.Region.Physics.BulletXPlugin | ||
41 | { | ||
42 | /// <summary> | ||
43 | /// IndexedMesh indexes into existing vertex and index arrays, in a similar way OpenGL glDrawElements | ||
44 | /// instead of the number of indices, we pass the number of triangles | ||
45 | /// </summary> | ||
46 | public struct IndexedMesh | ||
47 | { | ||
48 | private int _numTriangles; | ||
49 | private int[] _triangleIndexBase; | ||
50 | private int _triangleIndexStride; | ||
51 | private int _numVertices; | ||
52 | private Vector3[] _vertexBase; | ||
53 | private int _vertexStride; | ||
54 | |||
55 | public IndexedMesh(int numTriangleIndices, int[] triangleIndexBase, int triangleIndexStride, int numVertices, Vector3[] vertexBase, int vertexStride) | ||
56 | { | ||
57 | _numTriangles = numTriangleIndices; | ||
58 | _triangleIndexBase = triangleIndexBase; | ||
59 | _triangleIndexStride = triangleIndexStride; | ||
60 | _vertexBase = vertexBase; | ||
61 | _numVertices = numVertices; | ||
62 | _vertexStride = vertexStride; | ||
63 | } | ||
64 | |||
65 | public IndexedMesh(int[] triangleIndexBase, Vector3[] vertexBase) | ||
66 | { | ||
67 | _numTriangles = triangleIndexBase.Length; | ||
68 | _triangleIndexBase = triangleIndexBase; | ||
69 | _triangleIndexStride = 32; | ||
70 | _vertexBase = vertexBase; | ||
71 | _numVertices = vertexBase.Length; | ||
72 | _vertexStride = 24; | ||
73 | } | ||
74 | |||
75 | public int TriangleCount { get { return _numTriangles; } set { _numTriangles = value; } } | ||
76 | public int[] TriangleIndexBase { get { return _triangleIndexBase; } set { _triangleIndexBase = value; } } | ||
77 | public int TriangleIndexStride { get { return _triangleIndexStride; } set { _triangleIndexStride = value; } } | ||
78 | public int VertexCount { get { return _numVertices; } set { _numVertices = value; } } | ||
79 | public Vector3[] VertexBase { get { return _vertexBase; } set { _vertexBase = value; } } | ||
80 | public int VertexStride { get { return _vertexStride; } set { _vertexStride = value; } } | ||
81 | } | ||
82 | |||
83 | /// <summary> | ||
84 | /// TriangleIndexVertexArray allows to use multiple meshes, by indexing into existing triangle/index arrays. | ||
85 | /// Additional meshes can be added using addIndexedMesh | ||
86 | /// </summary> | ||
87 | public class TriangleIndexVertexArray : XnaDevRu.BulletX.StridingMeshInterface | ||
88 | { | ||
89 | List<IndexedMesh> _indexedMeshes = new List<IndexedMesh>(); | ||
90 | |||
91 | public TriangleIndexVertexArray() { } | ||
92 | |||
93 | public TriangleIndexVertexArray(int numTriangleIndices, int[] triangleIndexBase, int triangleIndexStride, int numVertices, Vector3[] vertexBase, int vertexStride) | ||
94 | { | ||
95 | IndexedMesh mesh = new IndexedMesh(); | ||
96 | mesh.TriangleCount = numTriangleIndices; | ||
97 | mesh.TriangleIndexBase = triangleIndexBase; | ||
98 | mesh.TriangleIndexStride = triangleIndexStride; | ||
99 | mesh.VertexBase = vertexBase; | ||
100 | mesh.VertexCount = numVertices; | ||
101 | mesh.VertexStride = vertexStride; | ||
102 | |||
103 | AddIndexedMesh(mesh); | ||
104 | } | ||
105 | |||
106 | public TriangleIndexVertexArray(int[] triangleIndexBase, Vector3[] vertexBase) | ||
107 | : this(triangleIndexBase.Length, triangleIndexBase, 32, vertexBase.Length, vertexBase, 24) { } | ||
108 | |||
109 | public void AddIndexedMesh(IndexedMesh indexedMesh) | ||
110 | { | ||
111 | _indexedMeshes.Add(indexedMesh); | ||
112 | } | ||
113 | |||
114 | public override void GetLockedVertexIndexBase(out List<Vector3> verts, out List<int> indicies, out int numfaces, int subpart) | ||
115 | { | ||
116 | throw new Exception("The method or operation is not implemented."); | ||
117 | } | ||
118 | |||
119 | public override void GetLockedReadOnlyVertexIndexBase(out List<Vector3> verts, out List<int> indicies, out int numfaces, int subpart) | ||
120 | { | ||
121 | IndexedMesh m = _indexedMeshes[0]; | ||
122 | Vector3[] vertexBase = m.VertexBase; | ||
123 | verts = new List<Vector3>(); | ||
124 | foreach (Vector3 v in vertexBase) | ||
125 | { | ||
126 | verts.Add(v); | ||
127 | } | ||
128 | int[] indexBase = m.TriangleIndexBase; | ||
129 | indicies = new List<int>(); | ||
130 | foreach (int i in indexBase) | ||
131 | { | ||
132 | indicies.Add(i); | ||
133 | } | ||
134 | numfaces = vertexBase.GetLength(0); | ||
135 | } | ||
136 | |||
137 | public override void UnLockVertexBase(int subpart) | ||
138 | { | ||
139 | throw new Exception("The method or operation is not implemented."); | ||
140 | } | ||
141 | |||
142 | public override void UnLockReadOnlyVertexBase(int subpart) | ||
143 | { | ||
144 | } | ||
145 | |||
146 | public override int SubPartsCount() | ||
147 | { | ||
148 | return _indexedMeshes.Count; | ||
149 | } | ||
150 | |||
151 | public override void PreallocateVertices(int numverts) | ||
152 | { | ||
153 | throw new Exception("The method or operation is not implemented."); | ||
154 | } | ||
155 | |||
156 | public override void PreallocateIndices(int numindices) | ||
157 | { | ||
158 | throw new Exception("The method or operation is not implemented."); | ||
159 | } | ||
160 | } | ||
161 | } | ||
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 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | |||
5 | using OpenSim.Framework; | ||
6 | |||
7 | namespace OpenSim.Region.Physics.Manager | ||
8 | { | ||
9 | public interface IMesher | ||
10 | { | ||
11 | IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size); | ||
12 | } | ||
13 | |||
14 | public interface IVertex { | ||
15 | } | ||
16 | |||
17 | public interface IMesh | ||
18 | { | ||
19 | List<PhysicsVector> getVertexList(); | ||
20 | int[] getIndexListAsInt(); | ||
21 | int[] getIndexListAsIntLocked(); | ||
22 | float[] getVertexListAsFloatLocked(); | ||
23 | |||
24 | |||
25 | } | ||
26 | } | ||
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; | |||
30 | using System.IO; | 30 | using System.IO; |
31 | using System.Reflection; | 31 | using System.Reflection; |
32 | using OpenSim.Framework.Console; | 32 | using OpenSim.Framework.Console; |
33 | using Nini.Config; | ||
33 | 34 | ||
34 | namespace OpenSim.Region.Physics.Manager | 35 | namespace OpenSim.Region.Physics.Manager |
35 | { | 36 | { |
@@ -38,28 +39,50 @@ namespace OpenSim.Region.Physics.Manager | |||
38 | /// </summary> | 39 | /// </summary> |
39 | public class PhysicsPluginManager | 40 | public class PhysicsPluginManager |
40 | { | 41 | { |
41 | private Dictionary<string, IPhysicsPlugin> _plugins = new Dictionary<string, IPhysicsPlugin>(); | 42 | private Dictionary<string, IPhysicsPlugin> _PhysPlugins = new Dictionary<string, IPhysicsPlugin>(); |
43 | private Dictionary<string, IMeshingPlugin> _MeshPlugins = new Dictionary<string, IMeshingPlugin>(); | ||
42 | 44 | ||
43 | public PhysicsPluginManager() | 45 | public PhysicsPluginManager() |
44 | { | 46 | { |
45 | } | 47 | } |
46 | 48 | ||
47 | public PhysicsScene GetPhysicsScene(string engineName) | 49 | public PhysicsScene GetPhysicsScene(string physEngineName, string meshEngineName) |
48 | { | 50 | { |
49 | if (String.IsNullOrEmpty(engineName)) | 51 | |
52 | if (String.IsNullOrEmpty(physEngineName)) | ||
53 | { | ||
54 | return PhysicsScene.Null; | ||
55 | } | ||
56 | |||
57 | if (String.IsNullOrEmpty(meshEngineName)) | ||
50 | { | 58 | { |
51 | return PhysicsScene.Null; | 59 | return PhysicsScene.Null; |
52 | } | 60 | } |
53 | 61 | ||
54 | if (_plugins.ContainsKey(engineName)) | 62 | |
63 | IMesher meshEngine = null; | ||
64 | if (_MeshPlugins.ContainsKey(meshEngineName)) | ||
55 | { | 65 | { |
56 | MainLog.Instance.Verbose("PHYSICS", "creating " + engineName); | 66 | MainLog.Instance.Verbose("PHYSICS", "creating meshing engine " + meshEngineName); |
57 | return _plugins[engineName].GetScene(); | 67 | meshEngine = _MeshPlugins[meshEngineName].GetMesher(); |
58 | } | 68 | } |
59 | else | 69 | else |
60 | { | 70 | { |
61 | MainLog.Instance.Warn("PHYSICS", "couldn't find physicsEngine: {0}", engineName); | 71 | MainLog.Instance.Warn("PHYSICS", "couldn't find meshingEngine: {0}", meshEngineName); |
62 | throw new ArgumentException(String.Format("couldn't find physicsEngine: {0}", engineName)); | 72 | throw new ArgumentException(String.Format("couldn't find meshingEngine: {0}", meshEngineName)); |
73 | } | ||
74 | |||
75 | if (_PhysPlugins.ContainsKey(physEngineName)) | ||
76 | { | ||
77 | MainLog.Instance.Verbose("PHYSICS", "creating " + physEngineName); | ||
78 | PhysicsScene result = _PhysPlugins[physEngineName].GetScene(); | ||
79 | result.Initialise(meshEngine); | ||
80 | return result; | ||
81 | } | ||
82 | else | ||
83 | { | ||
84 | MainLog.Instance.Warn("PHYSICS", "couldn't find physicsEngine: {0}", physEngineName); | ||
85 | throw new ArgumentException(String.Format("couldn't find physicsEngine: {0}", physEngineName)); | ||
63 | } | 86 | } |
64 | } | 87 | } |
65 | 88 | ||
@@ -85,18 +108,29 @@ namespace OpenSim.Region.Physics.Manager | |||
85 | { | 108 | { |
86 | if (!pluginType.IsAbstract) | 109 | if (!pluginType.IsAbstract) |
87 | { | 110 | { |
88 | Type typeInterface = pluginType.GetInterface("IPhysicsPlugin", true); | 111 | Type physTypeInterface = pluginType.GetInterface("IPhysicsPlugin", true); |
89 | 112 | ||
90 | if (typeInterface != null) | 113 | if (physTypeInterface != null) |
91 | { | 114 | { |
92 | IPhysicsPlugin plug = | 115 | IPhysicsPlugin plug = |
93 | (IPhysicsPlugin) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); | 116 | (IPhysicsPlugin) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); |
94 | plug.Init(); | 117 | plug.Init(); |
95 | _plugins.Add(plug.GetName(), plug); | 118 | _PhysPlugins.Add(plug.GetName(), plug); |
96 | MainLog.Instance.Verbose("PHYSICS", "Added physics engine: " + plug.GetName()); | 119 | MainLog.Instance.Verbose("PHYSICS", "Added physics engine: " + plug.GetName()); |
97 | } | 120 | } |
98 | 121 | ||
99 | typeInterface = null; | 122 | Type meshTypeInterface = pluginType.GetInterface("IMeshingPlugin", true); |
123 | |||
124 | if (meshTypeInterface != null) | ||
125 | { | ||
126 | IMeshingPlugin plug = | ||
127 | (IMeshingPlugin)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); | ||
128 | _MeshPlugins.Add(plug.GetName(), plug); | ||
129 | MainLog.Instance.Verbose("PHYSICS", "Added meshing engine: " + plug.GetName()); | ||
130 | } | ||
131 | |||
132 | physTypeInterface = null; | ||
133 | meshTypeInterface = null; | ||
100 | } | 134 | } |
101 | } | 135 | } |
102 | } | 136 | } |
@@ -127,4 +161,11 @@ namespace OpenSim.Region.Physics.Manager | |||
127 | string GetName(); | 161 | string GetName(); |
128 | void Dispose(); | 162 | void Dispose(); |
129 | } | 163 | } |
130 | } \ No newline at end of file | 164 | |
165 | public interface IMeshingPlugin | ||
166 | { | ||
167 | string GetName(); | ||
168 | IMesher GetMesher(); | ||
169 | } | ||
170 | |||
171 | } | ||
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 @@ | |||
28 | using Axiom.Math; | 28 | using Axiom.Math; |
29 | using OpenSim.Framework; | 29 | using OpenSim.Framework; |
30 | using OpenSim.Framework.Console; | 30 | using OpenSim.Framework.Console; |
31 | using OpenSim.Region.Physics.Manager; | ||
31 | 32 | ||
32 | namespace OpenSim.Region.Physics.Manager | 33 | namespace OpenSim.Region.Physics.Manager |
33 | { | 34 | { |
@@ -38,6 +39,8 @@ namespace OpenSim.Region.Physics.Manager | |||
38 | get { return new NullPhysicsScene(); } | 39 | get { return new NullPhysicsScene(); } |
39 | } | 40 | } |
40 | 41 | ||
42 | public abstract void Initialise(IMesher meshmerizer); | ||
43 | |||
41 | public abstract PhysicsActor AddAvatar(string avName, PhysicsVector position); | 44 | public abstract PhysicsActor AddAvatar(string avName, PhysicsVector position); |
42 | 45 | ||
43 | public abstract void RemoveAvatar(PhysicsActor actor); | 46 | public abstract void RemoveAvatar(PhysicsActor actor); |
@@ -63,6 +66,12 @@ namespace OpenSim.Region.Physics.Manager | |||
63 | { | 66 | { |
64 | private static int m_workIndicator; | 67 | private static int m_workIndicator; |
65 | 68 | ||
69 | |||
70 | public override void Initialise(IMesher meshmerizer) | ||
71 | { | ||
72 | // Does nothing right now | ||
73 | } | ||
74 | |||
66 | public override PhysicsActor AddAvatar(string avName, PhysicsVector position) | 75 | public override PhysicsActor AddAvatar(string avName, PhysicsVector position) |
67 | { | 76 | { |
68 | MainLog.Instance.Verbose("NullPhysicsScene : AddAvatar({0})", position); | 77 | MainLog.Instance.Verbose("NullPhysicsScene : AddAvatar({0})", position); |
@@ -123,4 +132,4 @@ namespace OpenSim.Region.Physics.Manager | |||
123 | } | 132 | } |
124 | } | 133 | } |
125 | } | 134 | } |
126 | } \ No newline at end of file | 135 | } |
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 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | |||
5 | namespace OpenSim.Region.Physics.Meshing | ||
6 | { | ||
7 | class Extruder | ||
8 | { | ||
9 | public float startParameter; | ||
10 | public float stopParameter; | ||
11 | public Manager.PhysicsVector size; | ||
12 | |||
13 | public Mesh Extrude(Mesh m) | ||
14 | { | ||
15 | // Currently only works for iSteps=1; | ||
16 | Mesh result = new Mesh(); | ||
17 | |||
18 | Mesh workingPlus = m.Clone(); | ||
19 | Mesh workingMinus = m.Clone(); | ||
20 | |||
21 | foreach (Vertex v in workingPlus.vertices) | ||
22 | { | ||
23 | if (v == null) | ||
24 | continue; | ||
25 | |||
26 | v.Z = +.5f; | ||
27 | v.X *= size.X; | ||
28 | v.Y *= size.Y; | ||
29 | v.Z *= size.Z; | ||
30 | } | ||
31 | |||
32 | foreach (Vertex v in workingMinus.vertices) | ||
33 | { | ||
34 | if (v == null) | ||
35 | continue; | ||
36 | |||
37 | v.Z = -.5f; | ||
38 | v.X *= size.X; | ||
39 | v.Y *= size.Y; | ||
40 | v.Z *= size.Z; | ||
41 | } | ||
42 | |||
43 | foreach (Triangle t in workingMinus.triangles) | ||
44 | { | ||
45 | t.invertNormal(); | ||
46 | } | ||
47 | |||
48 | result.Append(workingMinus); | ||
49 | result.Append(workingPlus); | ||
50 | |||
51 | int iLastNull = 0; | ||
52 | for (int i = 0; i < workingPlus.vertices.Count; i++) | ||
53 | { | ||
54 | int iNext = (i + 1); | ||
55 | |||
56 | if (workingPlus.vertices[i] == null) // Can't make a simplex here | ||
57 | { | ||
58 | iLastNull = i+1; | ||
59 | continue; | ||
60 | } | ||
61 | |||
62 | if (i == workingPlus.vertices.Count-1) // End of list | ||
63 | { | ||
64 | iNext = iLastNull; | ||
65 | } | ||
66 | |||
67 | if (workingPlus.vertices[iNext] == null) // Null means wrap to begin of last segment | ||
68 | { | ||
69 | iNext = iLastNull; | ||
70 | } | ||
71 | |||
72 | Triangle tSide; | ||
73 | tSide = new Triangle(workingPlus.vertices[i], workingMinus.vertices[i], workingPlus.vertices[iNext]); | ||
74 | result.Add(tSide); | ||
75 | |||
76 | tSide = new Triangle(workingPlus.vertices[iNext], workingMinus.vertices[i], workingMinus.vertices[iNext]); | ||
77 | result.Add(tSide); | ||
78 | } | ||
79 | |||
80 | return result; | ||
81 | } | ||
82 | } | ||
83 | } | ||
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 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | using System; | ||
30 | using System.Collections.Generic; | ||
31 | using System.Diagnostics; | ||
32 | using System.Globalization; | ||
33 | using OpenSim.Framework.Console; | ||
34 | using OpenSim.Region.Physics.Manager; | ||
35 | |||
36 | using OpenSim.Region.Physics.Meshing; | ||
37 | |||
38 | public class Vertex : PhysicsVector, IComparable<Vertex> | ||
39 | { | ||
40 | public Vertex(float x, float y, float z) | ||
41 | : base(x, y, z) | ||
42 | { | ||
43 | } | ||
44 | |||
45 | public Vertex(PhysicsVector v) | ||
46 | : base(v.X, v.Y, v.Z) | ||
47 | { | ||
48 | } | ||
49 | |||
50 | public Vertex Clone() | ||
51 | { | ||
52 | return new Vertex(X, Y, Z); | ||
53 | } | ||
54 | |||
55 | public static Vertex FromAngle(double angle) | ||
56 | { | ||
57 | return new Vertex((float)Math.Cos(angle), (float)Math.Sin(angle), 0.0f); | ||
58 | } | ||
59 | |||
60 | |||
61 | public virtual bool Equals(Vertex v, float tolerance) | ||
62 | { | ||
63 | PhysicsVector diff = this - v; | ||
64 | float d = diff.length(); | ||
65 | if (d < tolerance) | ||
66 | return true; | ||
67 | |||
68 | return false; | ||
69 | } | ||
70 | |||
71 | |||
72 | public int CompareTo(Vertex other) | ||
73 | { | ||
74 | if (X < other.X) | ||
75 | return -1; | ||
76 | |||
77 | if (X > other.X) | ||
78 | return 1; | ||
79 | |||
80 | if (Y < other.Y) | ||
81 | return -1; | ||
82 | |||
83 | if (Y > other.Y) | ||
84 | return 1; | ||
85 | |||
86 | if (Z < other.Z) | ||
87 | return -1; | ||
88 | |||
89 | if (Z > other.Z) | ||
90 | return 1; | ||
91 | |||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | public static bool operator >(Vertex me, Vertex other) | ||
96 | { | ||
97 | return me.CompareTo(other) > 0; | ||
98 | } | ||
99 | |||
100 | public static bool operator <(Vertex me, Vertex other) | ||
101 | { | ||
102 | return me.CompareTo(other) < 0; | ||
103 | } | ||
104 | public String ToRaw() | ||
105 | { | ||
106 | // Why this stuff with the number formatter? | ||
107 | // Well, the raw format uses the english/US notation of numbers | ||
108 | // where the "," separates groups of 1000 while the "." marks the border between 1 and 10E-1. | ||
109 | // The german notation uses these characters exactly vice versa! | ||
110 | // The Float.ToString() routine is a localized one, giving different results depending on the country | ||
111 | // settings your machine works with. Unusable for a machine readable file format :-( | ||
112 | NumberFormatInfo nfi = new NumberFormatInfo(); | ||
113 | nfi.NumberDecimalSeparator = "."; | ||
114 | nfi.NumberDecimalDigits = 3; | ||
115 | |||
116 | String s1 = X.ToString("N2", nfi) + " " + Y.ToString("N2", nfi) + " " + Z.ToString("N2", nfi); | ||
117 | |||
118 | return s1; | ||
119 | } | ||
120 | |||
121 | } | ||
122 | |||
123 | public class Triangle | ||
124 | { | ||
125 | public Vertex v1; | ||
126 | public Vertex v2; | ||
127 | public Vertex v3; | ||
128 | |||
129 | private float radius_square; | ||
130 | private float cx; | ||
131 | private float cy; | ||
132 | |||
133 | public Triangle(Vertex _v1, Vertex _v2, Vertex _v3) | ||
134 | { | ||
135 | v1 = _v1; | ||
136 | v2 = _v2; | ||
137 | v3 = _v3; | ||
138 | |||
139 | CalcCircle(); | ||
140 | } | ||
141 | |||
142 | public bool isInCircle(float x, float y) | ||
143 | { | ||
144 | float dx, dy; | ||
145 | float dd; | ||
146 | |||
147 | dx = x - cx; | ||
148 | dy = y - cy; | ||
149 | |||
150 | dd = dx*dx + dy*dy; | ||
151 | if (dd < radius_square) | ||
152 | return true; | ||
153 | else | ||
154 | return false; | ||
155 | } | ||
156 | |||
157 | public bool isDegraded() | ||
158 | { | ||
159 | // This means, the vertices of this triangle are somewhat strange. | ||
160 | // They either line up or at least two of them are identical | ||
161 | return (radius_square == 0.0); | ||
162 | } | ||
163 | |||
164 | private void CalcCircle() | ||
165 | { | ||
166 | // Calculate the center and the radius of a circle given by three points p1, p2, p3 | ||
167 | // It is assumed, that the triangles vertices are already set correctly | ||
168 | double p1x, p2x, p1y, p2y, p3x, p3y; | ||
169 | |||
170 | // Deviation of this routine: | ||
171 | // A circle has the general equation (M-p)^2=r^2, where M and p are vectors | ||
172 | // this gives us three equations f(p)=r^2, each for one point p1, p2, p3 | ||
173 | // putting respectively two equations together gives two equations | ||
174 | // f(p1)=f(p2) and f(p1)=f(p3) | ||
175 | // bringing all constant terms to one side brings them to the form | ||
176 | // M*v1=c1 resp.M*v2=c2 where v1=(p1-p2) and v2=(p1-p3) (still vectors) | ||
177 | // and c1, c2 are scalars (Naming conventions like the variables below) | ||
178 | // Now using the equations that are formed by the components of the vectors | ||
179 | // and isolate Mx lets you make one equation that only holds My | ||
180 | // The rest is straight forward and eaasy :-) | ||
181 | // | ||
182 | |||
183 | /* helping variables for temporary results */ | ||
184 | double c1, c2; | ||
185 | double v1x, v1y, v2x, v2y; | ||
186 | |||
187 | double z, n; | ||
188 | |||
189 | double rx, ry; | ||
190 | |||
191 | // Readout the three points, the triangle consists of | ||
192 | p1x = v1.X; | ||
193 | p1y = v1.Y; | ||
194 | |||
195 | p2x = v2.X; | ||
196 | p2y = v2.Y; | ||
197 | |||
198 | p3x = v3.X; | ||
199 | p3y = v3.Y; | ||
200 | |||
201 | /* calc helping values first */ | ||
202 | c1 = (p1x*p1x + p1y*p1y - p2x*p2x - p2y*p2y)/2; | ||
203 | c2 = (p1x*p1x + p1y*p1y - p3x*p3x - p3y*p3y)/2; | ||
204 | |||
205 | v1x = p1x - p2x; | ||
206 | v1y = p1y - p2y; | ||
207 | |||
208 | v2x = p1x - p3x; | ||
209 | v2y = p1y - p3y; | ||
210 | |||
211 | z = (c1*v2x - c2*v1x); | ||
212 | n = (v1y*v2x - v2y*v1x); | ||
213 | |||
214 | if (n == 0.0) // This is no triangle, i.e there are (at least) two points at the same location | ||
215 | { | ||
216 | radius_square = 0.0f; | ||
217 | return; | ||
218 | } | ||
219 | |||
220 | cy = (float) (z/n); | ||
221 | |||
222 | if (v2x != 0.0) | ||
223 | { | ||
224 | cx = (float) ((c2 - v2y*cy)/v2x); | ||
225 | } | ||
226 | else if (v1x != 0.0) | ||
227 | { | ||
228 | cx = (float) ((c1 - v1y*cy)/v1x); | ||
229 | } | ||
230 | else | ||
231 | { | ||
232 | Debug.Assert(false, "Malformed triangle"); /* Both terms zero means nothing good */ | ||
233 | } | ||
234 | |||
235 | rx = (p1x - cx); | ||
236 | ry = (p1y - cy); | ||
237 | |||
238 | radius_square = (float) (rx*rx + ry*ry); | ||
239 | } | ||
240 | |||
241 | public List<Simplex> GetSimplices() | ||
242 | { | ||
243 | List<Simplex> result = new List<Simplex>(); | ||
244 | Simplex s1 = new Simplex(v1, v2); | ||
245 | Simplex s2 = new Simplex(v2, v3); | ||
246 | Simplex s3 = new Simplex(v3, v1); | ||
247 | |||
248 | result.Add(s1); | ||
249 | result.Add(s2); | ||
250 | result.Add(s3); | ||
251 | |||
252 | return result; | ||
253 | } | ||
254 | |||
255 | public override String ToString() | ||
256 | { | ||
257 | NumberFormatInfo nfi = new NumberFormatInfo(); | ||
258 | nfi.CurrencyDecimalDigits = 2; | ||
259 | nfi.CurrencyDecimalSeparator = "."; | ||
260 | |||
261 | String s1 = "<" + v1.X.ToString(nfi) + "," + v1.Y.ToString(nfi) + "," + v1.Z.ToString(nfi) + ">"; | ||
262 | String s2 = "<" + v2.X.ToString(nfi) + "," + v2.Y.ToString(nfi) + "," + v2.Z.ToString(nfi) + ">"; | ||
263 | String s3 = "<" + v3.X.ToString(nfi) + "," + v3.Y.ToString(nfi) + "," + v3.Z.ToString(nfi) + ">"; | ||
264 | |||
265 | return s1 + ";" + s2 + ";" + s3; | ||
266 | } | ||
267 | |||
268 | public PhysicsVector getNormal() | ||
269 | { | ||
270 | // Vertices | ||
271 | |||
272 | // Vectors for edges | ||
273 | PhysicsVector e1; | ||
274 | PhysicsVector e2; | ||
275 | |||
276 | e1 = new PhysicsVector(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z); | ||
277 | e2 = new PhysicsVector(v1.X - v3.X, v1.Y - v3.Y, v1.Z - v3.Z); | ||
278 | |||
279 | // Cross product for normal | ||
280 | PhysicsVector n = PhysicsVector.cross(e1, e2); | ||
281 | |||
282 | // Length | ||
283 | float l = n.length(); | ||
284 | |||
285 | // Normalized "normal" | ||
286 | n = n / l; | ||
287 | |||
288 | return n; | ||
289 | } | ||
290 | |||
291 | public void invertNormal() | ||
292 | { | ||
293 | Vertex vt; | ||
294 | vt = v1; | ||
295 | v1 = v2; | ||
296 | v2 = vt; | ||
297 | } | ||
298 | |||
299 | // Dumps a triangle in the "raw faces" format, blender can import. This is for visualisation and | ||
300 | // debugging purposes | ||
301 | public String ToStringRaw() | ||
302 | { | ||
303 | String output = v1.ToRaw() + " " + v2.ToRaw() + " " +v3.ToRaw(); | ||
304 | return output; | ||
305 | } | ||
306 | } \ 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 @@ | |||
1 | using System; | ||
2 | using System.IO; | ||
3 | using System.Collections.Generic; | ||
4 | using System.Text; | ||
5 | |||
6 | using System.Runtime.InteropServices; | ||
7 | |||
8 | |||
9 | using OpenSim.Region.Physics.Manager; | ||
10 | |||
11 | namespace OpenSim.Region.Physics.Meshing | ||
12 | { | ||
13 | public class Mesh : IMesh | ||
14 | { | ||
15 | public List<Vertex> vertices; | ||
16 | public List<Triangle> triangles; | ||
17 | |||
18 | public float[] normals; | ||
19 | |||
20 | public Mesh() | ||
21 | { | ||
22 | vertices = new List<Vertex>(); | ||
23 | triangles = new List<Triangle>(); | ||
24 | } | ||
25 | |||
26 | public Mesh Clone() | ||
27 | { | ||
28 | Mesh result = new Mesh(); | ||
29 | |||
30 | foreach (Vertex v in vertices) | ||
31 | { | ||
32 | if (v == null) | ||
33 | result.vertices.Add(null); | ||
34 | else | ||
35 | result.vertices.Add(v.Clone()); | ||
36 | } | ||
37 | |||
38 | foreach (Triangle t in triangles) | ||
39 | { | ||
40 | int iV1, iV2, iV3; | ||
41 | iV1 = this.vertices.IndexOf(t.v1); | ||
42 | iV2 = this.vertices.IndexOf(t.v2); | ||
43 | iV3 = this.vertices.IndexOf(t.v3); | ||
44 | |||
45 | Triangle newT = new Triangle(result.vertices[iV1], result.vertices[iV2], result.vertices[iV3]); | ||
46 | result.Add(newT); | ||
47 | } | ||
48 | |||
49 | return result; | ||
50 | } | ||
51 | |||
52 | |||
53 | |||
54 | public void Add(Triangle triangle) | ||
55 | { | ||
56 | int i; | ||
57 | i = vertices.IndexOf(triangle.v1); | ||
58 | if (i < 0) | ||
59 | throw new ArgumentException("Vertex v1 not known to mesh"); | ||
60 | i = vertices.IndexOf(triangle.v2); | ||
61 | if (i < 0) | ||
62 | throw new ArgumentException("Vertex v2 not known to mesh"); | ||
63 | i = vertices.IndexOf(triangle.v3); | ||
64 | if (i < 0) | ||
65 | throw new ArgumentException("Vertex v3 not known to mesh"); | ||
66 | |||
67 | triangles.Add(triangle); | ||
68 | } | ||
69 | |||
70 | public void Add(Vertex v) | ||
71 | { | ||
72 | vertices.Add(v); | ||
73 | } | ||
74 | |||
75 | public void Remove(Vertex v) | ||
76 | { | ||
77 | int i; | ||
78 | |||
79 | // First, remove all triangles that are build on v | ||
80 | for (i = 0; i < triangles.Count; i++) | ||
81 | { | ||
82 | Triangle t = triangles[i]; | ||
83 | if (t.v1 == v || t.v2 == v || t.v3 == v) | ||
84 | { | ||
85 | triangles.RemoveAt(i); | ||
86 | i--; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | // Second remove v itself | ||
91 | vertices.Remove(v); | ||
92 | } | ||
93 | |||
94 | public void RemoveTrianglesOutside(SimpleHull hull) | ||
95 | { | ||
96 | int i; | ||
97 | |||
98 | for (i = 0; i < triangles.Count; i++) | ||
99 | { | ||
100 | Triangle t = triangles[i]; | ||
101 | Vertex v1 = t.v1; | ||
102 | Vertex v2 = t.v2; | ||
103 | Vertex v3 = t.v3; | ||
104 | PhysicsVector m = v1 + v2 + v3; | ||
105 | m /= 3.0f; | ||
106 | if (!hull.IsPointIn(new Vertex(m))) | ||
107 | { | ||
108 | triangles.RemoveAt(i); | ||
109 | i--; | ||
110 | } | ||
111 | } | ||
112 | } | ||
113 | |||
114 | |||
115 | public void Add(List<Vertex> lv) | ||
116 | { | ||
117 | foreach (Vertex v in lv) | ||
118 | { | ||
119 | vertices.Add(v); | ||
120 | } | ||
121 | } | ||
122 | |||
123 | public List<PhysicsVector> getVertexList() | ||
124 | { | ||
125 | List<PhysicsVector> result = new List<PhysicsVector>(); | ||
126 | foreach (Vertex v in vertices) | ||
127 | { | ||
128 | result.Add(v); | ||
129 | } | ||
130 | return result; | ||
131 | } | ||
132 | |||
133 | public float[] getVertexListAsFloatLocked() | ||
134 | { | ||
135 | float[] result = new float[vertices.Count * 3]; | ||
136 | for (int i = 0; i < vertices.Count; i++) | ||
137 | { | ||
138 | Vertex v = vertices[i]; | ||
139 | if (v == null) | ||
140 | continue; | ||
141 | result[3 * i + 0] = v.X; | ||
142 | result[3 * i + 1] = v.Y; | ||
143 | result[3 * i + 2] = v.Z; | ||
144 | } | ||
145 | GCHandle.Alloc(result, GCHandleType.Pinned); | ||
146 | return result; | ||
147 | } | ||
148 | |||
149 | public int[] getIndexListAsInt() | ||
150 | { | ||
151 | int[] result = new int[triangles.Count * 3]; | ||
152 | for (int i = 0; i < triangles.Count; i++) | ||
153 | { | ||
154 | Triangle t = triangles[i]; | ||
155 | result[3 * i + 0] = vertices.IndexOf(t.v1); | ||
156 | result[3 * i + 1] = vertices.IndexOf(t.v2); | ||
157 | result[3 * i + 2] = vertices.IndexOf(t.v3); | ||
158 | } | ||
159 | return result; | ||
160 | } | ||
161 | |||
162 | public int[] getIndexListAsIntLocked() | ||
163 | { | ||
164 | int[] result = getIndexListAsInt(); | ||
165 | GCHandle.Alloc(result, GCHandleType.Pinned); | ||
166 | return result; | ||
167 | } | ||
168 | |||
169 | |||
170 | public void Append(Mesh newMesh) | ||
171 | { | ||
172 | foreach (Vertex v in newMesh.vertices) | ||
173 | vertices.Add(v); | ||
174 | |||
175 | foreach (Triangle t in newMesh.triangles) | ||
176 | Add(t); | ||
177 | |||
178 | } | ||
179 | |||
180 | // Do a linear transformation of mesh. | ||
181 | public void TransformLinear(float[,] matrix, float[] offset) | ||
182 | { | ||
183 | foreach (Vertex v in vertices) | ||
184 | { | ||
185 | if (v == null) | ||
186 | continue; | ||
187 | float x, y, z; | ||
188 | x = v.X * matrix[0, 0] + v.Y * matrix[1, 0] + v.Z * matrix[2, 0]; | ||
189 | y = v.X * matrix[0, 1] + v.Y * matrix[1, 1] + v.Z * matrix[2, 1]; | ||
190 | z = v.X * matrix[0, 2] + v.Y * matrix[1, 2] + v.Z * matrix[2, 2]; | ||
191 | v.X = x + offset[0]; | ||
192 | v.Y = y + offset[1]; | ||
193 | v.Z = z + offset[2]; | ||
194 | } | ||
195 | } | ||
196 | |||
197 | public void DumpRaw(String path, String name, String title) | ||
198 | { | ||
199 | if (path == null) | ||
200 | return; | ||
201 | String fileName = name + "_" + title + ".raw"; | ||
202 | String completePath = Path.Combine(path, fileName); | ||
203 | StreamWriter sw = new StreamWriter(completePath); | ||
204 | foreach (Triangle t in triangles) | ||
205 | { | ||
206 | String s = t.ToStringRaw(); | ||
207 | sw.WriteLine(s); | ||
208 | } | ||
209 | sw.Close(); | ||
210 | } | ||
211 | } | ||
212 | |||
213 | } | ||
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 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | using System; | ||
30 | using System.IO; | ||
31 | using System.Globalization; | ||
32 | using System.Diagnostics; | ||
33 | using System.Collections.Generic; | ||
34 | using System.Runtime.InteropServices; | ||
35 | using OpenSim.Framework; | ||
36 | using OpenSim.Framework.Console; | ||
37 | using OpenSim.Region.Physics.Manager; | ||
38 | |||
39 | namespace OpenSim.Region.Physics.Meshing | ||
40 | { | ||
41 | |||
42 | public class MeshmerizerPlugin : IMeshingPlugin | ||
43 | { | ||
44 | public MeshmerizerPlugin() | ||
45 | { | ||
46 | } | ||
47 | |||
48 | public string GetName() | ||
49 | { | ||
50 | return "Meshmerizer"; | ||
51 | } | ||
52 | |||
53 | public IMesher GetMesher() | ||
54 | { | ||
55 | return new Meshmerizer(); | ||
56 | } | ||
57 | } | ||
58 | |||
59 | public class Meshmerizer : IMesher | ||
60 | { | ||
61 | // Setting baseDir to a path will enable the dumping of raw files | ||
62 | // raw files can be imported by blender so a visual inspection of the results can be done | ||
63 | // const string baseDir = "rawFiles"; | ||
64 | const string baseDir = null; | ||
65 | |||
66 | static void IntersectionParameterPD(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2, PhysicsVector r2, ref float lambda, ref float mu) | ||
67 | { | ||
68 | // p1, p2, points on the straight | ||
69 | // r1, r2, directional vectors of the straight. Not necessarily of length 1! | ||
70 | // note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points, | ||
71 | // thus allowing to decide whether an intersection is between two points | ||
72 | |||
73 | float r1x = r1.X; | ||
74 | float r1y = r1.Y; | ||
75 | float r2x = r2.X; | ||
76 | float r2y = r2.Y; | ||
77 | |||
78 | float denom = r1y*r2x - r1x*r2y; | ||
79 | |||
80 | if (denom == 0.0) | ||
81 | { | ||
82 | lambda = Single.NaN; | ||
83 | mu = Single.NaN; | ||
84 | return; | ||
85 | } | ||
86 | |||
87 | float p1x = p1.X; | ||
88 | float p1y = p1.Y; | ||
89 | float p2x = p2.X; | ||
90 | float p2y = p2.Y; | ||
91 | lambda = (-p2x * r2y + p1x * r2y + (p2y - p1y) * r2x) / denom; | ||
92 | mu = (-p2x * r1y + p1x * r1y + (p2y - p1y) * r1x) / denom; | ||
93 | |||
94 | } | ||
95 | |||
96 | private static List<Triangle> FindInfluencedTriangles(List<Triangle> triangles, Vertex v) | ||
97 | { | ||
98 | List<Triangle> influenced = new List<Triangle>(); | ||
99 | foreach (Triangle t in triangles) | ||
100 | { | ||
101 | if (t.isInCircle(v.X, v.Y)) | ||
102 | { | ||
103 | influenced.Add(t); | ||
104 | } | ||
105 | } | ||
106 | return influenced; | ||
107 | } | ||
108 | |||
109 | |||
110 | private static void InsertVertices(List<Vertex> vertices, int usedForSeed, List<Triangle> triangles) | ||
111 | { | ||
112 | // This is a variant of the delaunay algorithm | ||
113 | // each time a new vertex is inserted, all triangles that are influenced by it are deleted | ||
114 | // and replaced by new ones including the new vertex | ||
115 | // It is not very time efficient but easy to implement. | ||
116 | |||
117 | int iCurrentVertex; | ||
118 | int iMaxVertex = vertices.Count; | ||
119 | for (iCurrentVertex = usedForSeed; iCurrentVertex < iMaxVertex; iCurrentVertex++) | ||
120 | { | ||
121 | // Background: A triangle mesh fulfills the delaunay condition if (iff!) | ||
122 | // each circumlocutory circle (i.e. the circle that touches all three corners) | ||
123 | // of each triangle is empty of other vertices. | ||
124 | // Obviously a single (seeding) triangle fulfills this condition. | ||
125 | // If we now add one vertex, we need to reconstruct all triangles, that | ||
126 | // do not fulfill this condition with respect to the new triangle | ||
127 | |||
128 | // Find the triangles that are influenced by the new vertex | ||
129 | Vertex v=vertices[iCurrentVertex]; | ||
130 | if (v == null) | ||
131 | continue; // Null is polygon stop marker. Ignore it | ||
132 | List<Triangle> influencedTriangles=FindInfluencedTriangles(triangles, v); | ||
133 | |||
134 | List<Simplex> simplices = new List<Simplex>(); | ||
135 | |||
136 | // Reconstruction phase. First step, dissolve each triangle into it's simplices, | ||
137 | // i.e. it's "border lines" | ||
138 | // Goal is to find "inner" borders and delete them, while the hull gets conserved. | ||
139 | // Inner borders are special in the way that they always come twice, which is how we detect them | ||
140 | foreach (Triangle t in influencedTriangles) | ||
141 | { | ||
142 | List<Simplex> newSimplices = t.GetSimplices(); | ||
143 | simplices.AddRange(newSimplices); | ||
144 | triangles.Remove(t); | ||
145 | } | ||
146 | // Now sort the simplices. That will make identical ones reside side by side in the list | ||
147 | simplices.Sort(); | ||
148 | |||
149 | // Look for duplicate simplices here. | ||
150 | // Remember, they are directly side by side in the list right now, | ||
151 | // So we only check directly neighbours | ||
152 | int iSimplex; | ||
153 | List<Simplex> innerSimplices = new List<Simplex>(); | ||
154 | for (iSimplex = 1; iSimplex < simplices.Count; iSimplex++) // Startindex=1, so we can refer backwards | ||
155 | { | ||
156 | if (simplices[iSimplex - 1].CompareTo(simplices[iSimplex]) == 0) | ||
157 | { | ||
158 | innerSimplices.Add(simplices[iSimplex - 1]); | ||
159 | innerSimplices.Add(simplices[iSimplex]); | ||
160 | } | ||
161 | } | ||
162 | |||
163 | foreach (Simplex s in innerSimplices) | ||
164 | { | ||
165 | simplices.Remove(s); | ||
166 | } | ||
167 | |||
168 | // each simplex still in the list belongs to the hull of the region in question | ||
169 | // The new vertex (yes, we still deal with verices here :-) ) forms a triangle | ||
170 | // with each of these simplices. Build the new triangles and add them to the list | ||
171 | foreach (Simplex s in simplices) | ||
172 | { | ||
173 | Triangle t = new Triangle(s.v1, s.v2, vertices[iCurrentVertex]); | ||
174 | if (!t.isDegraded()) | ||
175 | { | ||
176 | triangles.Add(t); | ||
177 | } | ||
178 | } | ||
179 | } | ||
180 | |||
181 | } | ||
182 | |||
183 | |||
184 | static Mesh CreateBoxMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) | ||
185 | // Builds the z (+ and -) surfaces of a box shaped prim | ||
186 | { | ||
187 | UInt16 hollowFactor = primShape.ProfileHollow; | ||
188 | UInt16 profileBegin = primShape.ProfileBegin; | ||
189 | UInt16 profileEnd = primShape.ProfileEnd; | ||
190 | |||
191 | // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface | ||
192 | // of a block are basically the same | ||
193 | // They may be warped differently but the shape is identical | ||
194 | // So we only create one surface as a model and derive both plus and minus surface of the block from it | ||
195 | // This is done in a model space where the block spans from -.5 to +.5 in X and Y | ||
196 | // The mapping to Scene space is done later during the "extrusion" phase | ||
197 | |||
198 | // Base | ||
199 | Vertex MM = new Vertex(-0.5f, -0.5f, 0.0f); | ||
200 | Vertex PM = new Vertex(+0.5f, -0.5f, 0.0f); | ||
201 | Vertex MP = new Vertex(-0.5f, +0.5f, 0.0f); | ||
202 | Vertex PP = new Vertex(+0.5f, +0.5f, 0.0f); | ||
203 | |||
204 | Meshing.SimpleHull outerHull = new SimpleHull(); | ||
205 | outerHull.AddVertex(MM); | ||
206 | outerHull.AddVertex(PM); | ||
207 | outerHull.AddVertex(PP); | ||
208 | outerHull.AddVertex(MP); | ||
209 | |||
210 | // Deal with cuts now | ||
211 | if ((profileBegin != 0) || (profileEnd != 0)) | ||
212 | { | ||
213 | double fProfileBeginAngle = profileBegin / 50000.0 * 360.0; // In degree, for easier debugging and understanding | ||
214 | fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y | ||
215 | double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0 | ||
216 | fProfileEndAngle -= (90.0 + 45.0); | ||
217 | if (fProfileBeginAngle < fProfileEndAngle) | ||
218 | fProfileEndAngle -= 360.0; | ||
219 | |||
220 | // Note, that we don't want to cut out a triangle, even if this is a | ||
221 | // good approximation for small cuts. Indeed we want to cut out an arc | ||
222 | // and we approximate this arc by a polygon chain | ||
223 | // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space | ||
224 | // So it can easily be subtracted from the outer hull | ||
225 | int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5); // how many steps do we need with approximately 45 degree | ||
226 | double dStepWidth=(fProfileBeginAngle-fProfileEndAngle)/iSteps; | ||
227 | |||
228 | Vertex origin = new Vertex(0.0f, 0.0f, 0.0f); | ||
229 | |||
230 | // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull | ||
231 | SimpleHull cutHull = new SimpleHull(); | ||
232 | cutHull.AddVertex(origin); | ||
233 | for (int i=0; i<iSteps; i++) { | ||
234 | double angle=fProfileBeginAngle-i*dStepWidth; // we count against the angle orientation!!!! | ||
235 | Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0); | ||
236 | cutHull.AddVertex(v); | ||
237 | } | ||
238 | Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0); // Calculated separately to avoid errors | ||
239 | cutHull.AddVertex(legEnd); | ||
240 | |||
241 | MainLog.Instance.Debug("Starting cutting of the hollow shape from the prim {1}", 0, primName); | ||
242 | SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull); | ||
243 | |||
244 | outerHull = cuttedHull; | ||
245 | } | ||
246 | |||
247 | // Deal with the hole here | ||
248 | if (hollowFactor > 0) | ||
249 | { | ||
250 | float hollowFactorF = (float) hollowFactor/(float) 50000; | ||
251 | Vertex IMM = new Vertex(-0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f); | ||
252 | Vertex IPM = new Vertex(+0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f); | ||
253 | Vertex IMP = new Vertex(-0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f); | ||
254 | Vertex IPP = new Vertex(+0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f); | ||
255 | |||
256 | SimpleHull holeHull = new SimpleHull(); | ||
257 | |||
258 | holeHull.AddVertex(IMM); | ||
259 | holeHull.AddVertex(IMP); | ||
260 | holeHull.AddVertex(IPP); | ||
261 | holeHull.AddVertex(IPM); | ||
262 | |||
263 | SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull); | ||
264 | |||
265 | outerHull = hollowedHull; | ||
266 | |||
267 | } | ||
268 | |||
269 | Mesh m = new Mesh(); | ||
270 | |||
271 | Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f); | ||
272 | Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f); | ||
273 | Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f); | ||
274 | |||
275 | m.Add(Seed1); | ||
276 | m.Add(Seed2); | ||
277 | m.Add(Seed3); | ||
278 | |||
279 | m.Add(new Triangle(Seed1, Seed2, Seed3)); | ||
280 | m.Add(outerHull.getVertices()); | ||
281 | |||
282 | InsertVertices(m.vertices, 3, m.triangles); | ||
283 | m.DumpRaw(baseDir, primName, "Proto first Mesh"); | ||
284 | |||
285 | m.Remove(Seed1); | ||
286 | m.Remove(Seed2); | ||
287 | m.Remove(Seed3); | ||
288 | m.DumpRaw(baseDir, primName, "Proto seeds removed"); | ||
289 | |||
290 | m.RemoveTrianglesOutside(outerHull); | ||
291 | m.DumpRaw(baseDir, primName, "Proto outsides removed"); | ||
292 | |||
293 | foreach (Triangle t in m.triangles) | ||
294 | { | ||
295 | PhysicsVector n = t.getNormal(); | ||
296 | if (n.Z < 0.0) | ||
297 | t.invertNormal(); | ||
298 | } | ||
299 | |||
300 | Extruder extr = new Extruder(); | ||
301 | |||
302 | extr.size = size; | ||
303 | |||
304 | Mesh result = extr.Extrude(m); | ||
305 | result.DumpRaw(baseDir, primName, "Z extruded"); | ||
306 | return result; | ||
307 | } | ||
308 | |||
309 | public static void CalcNormals(Mesh mesh) | ||
310 | { | ||
311 | int iTriangles = mesh.triangles.Count; | ||
312 | |||
313 | mesh.normals = new float[iTriangles*3]; | ||
314 | |||
315 | int i = 0; | ||
316 | foreach (Triangle t in mesh.triangles) | ||
317 | { | ||
318 | float ux, uy, uz; | ||
319 | float vx, vy, vz; | ||
320 | float wx, wy, wz; | ||
321 | |||
322 | ux = t.v1.X; | ||
323 | uy = t.v1.Y; | ||
324 | uz = t.v1.Z; | ||
325 | |||
326 | vx = t.v2.X; | ||
327 | vy = t.v2.Y; | ||
328 | vz = t.v2.Z; | ||
329 | |||
330 | wx = t.v3.X; | ||
331 | wy = t.v3.Y; | ||
332 | wz = t.v3.Z; | ||
333 | |||
334 | |||
335 | // Vectors for edges | ||
336 | float e1x, e1y, e1z; | ||
337 | float e2x, e2y, e2z; | ||
338 | |||
339 | e1x = ux - vx; | ||
340 | e1y = uy - vy; | ||
341 | e1z = uz - vz; | ||
342 | |||
343 | e2x = ux - wx; | ||
344 | e2y = uy - wy; | ||
345 | e2z = uz - wz; | ||
346 | |||
347 | |||
348 | // Cross product for normal | ||
349 | float nx, ny, nz; | ||
350 | nx = e1y*e2z - e1z*e2y; | ||
351 | ny = e1z*e2x - e1x*e2z; | ||
352 | nz = e1x*e2y - e1y*e2x; | ||
353 | |||
354 | // Length | ||
355 | float l = (float) Math.Sqrt(nx*nx + ny*ny + nz*nz); | ||
356 | |||
357 | // Normalized "normal" | ||
358 | nx /= l; | ||
359 | ny /= l; | ||
360 | nz /= l; | ||
361 | |||
362 | mesh.normals[i] = nx; | ||
363 | mesh.normals[i + 1] = ny; | ||
364 | mesh.normals[i + 2] = nz; | ||
365 | |||
366 | i += 3; | ||
367 | } | ||
368 | } | ||
369 | |||
370 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) | ||
371 | { | ||
372 | Mesh mesh = null; | ||
373 | |||
374 | switch (primShape.ProfileShape) | ||
375 | { | ||
376 | case ProfileShape.Square: | ||
377 | mesh=CreateBoxMesh(primName, primShape, size); | ||
378 | CalcNormals(mesh); | ||
379 | break; | ||
380 | default: | ||
381 | mesh = CreateBoxMesh(primName, primShape, size); | ||
382 | CalcNormals(mesh); | ||
383 | //Set default mesh to cube otherwise it'll return | ||
384 | // null and crash on the 'setMesh' method in the physics plugins. | ||
385 | //mesh = null; | ||
386 | break; | ||
387 | } | ||
388 | |||
389 | return mesh; | ||
390 | } | ||
391 | } | ||
392 | |||
393 | } | ||
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 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | |||
5 | using OpenSim.Framework.Console; | ||
6 | |||
7 | namespace OpenSim.Region.Physics.Meshing | ||
8 | { | ||
9 | // A simple hull is a set of vertices building up to simplices that border a region | ||
10 | // The word simple referes to the fact, that this class assumes, that all simplices | ||
11 | // do not intersect | ||
12 | // Simple hulls can be added and subtracted. | ||
13 | // Vertices can be checked to lie inside a hull | ||
14 | // Also note, that the sequence of the vertices is important and defines if the region that | ||
15 | // is defined by the hull lies inside or outside the simplex chain | ||
16 | public class SimpleHull | ||
17 | { | ||
18 | List<Vertex> vertices = new List<Vertex>(); | ||
19 | List<Vertex> holeVertices = new List<Vertex>(); // Only used, when the hull is hollow | ||
20 | |||
21 | // Adds a vertex to the end of the list | ||
22 | public void AddVertex(Vertex v) { | ||
23 | vertices.Add(v); | ||
24 | } | ||
25 | |||
26 | override public String ToString() | ||
27 | { | ||
28 | String result=""; | ||
29 | foreach (Vertex v in vertices) | ||
30 | { | ||
31 | result += "b:" + v.ToString() + "\n"; | ||
32 | } | ||
33 | |||
34 | return result; | ||
35 | } | ||
36 | |||
37 | |||
38 | public List<Vertex> getVertices() { | ||
39 | List<Vertex> newVertices = new List<Vertex>(); | ||
40 | |||
41 | newVertices.AddRange(vertices); | ||
42 | newVertices.Add(null); | ||
43 | newVertices.AddRange(holeVertices); | ||
44 | |||
45 | return newVertices; | ||
46 | } | ||
47 | |||
48 | public SimpleHull Clone() | ||
49 | { | ||
50 | SimpleHull result = new SimpleHull(); | ||
51 | foreach (Vertex v in vertices) | ||
52 | { | ||
53 | result.AddVertex(v.Clone()); | ||
54 | } | ||
55 | |||
56 | foreach (Vertex v in this.holeVertices) | ||
57 | { | ||
58 | result.holeVertices.Add(v.Clone()); | ||
59 | } | ||
60 | |||
61 | return result; | ||
62 | } | ||
63 | |||
64 | public bool IsPointIn(Vertex v1) | ||
65 | { | ||
66 | int iCounter=0; | ||
67 | List<Simplex> simplices=buildSimplexList(); | ||
68 | foreach (Simplex s in simplices) | ||
69 | { | ||
70 | // Send a ray along the positive X-Direction | ||
71 | // Note, that this direction must correlate with the "below" interpretation | ||
72 | // of handling for the special cases below | ||
73 | Manager.PhysicsVector intersection = s.RayIntersect(v1, new Manager.PhysicsVector(1.0f, 0.0f, 0.0f), true); | ||
74 | |||
75 | if (intersection == null) | ||
76 | continue; // No intersection. Done. More tests to follow otherwise | ||
77 | |||
78 | // Did we hit the end of a simplex? | ||
79 | // Then this can be one of two special cases: | ||
80 | // 1. we go through a border exactly at a joint | ||
81 | // 2. we have just marginally touched a corner | ||
82 | // 3. we can slide along a border | ||
83 | // Solution: If the other vertex is "below" the ray, we don't count it | ||
84 | // Thus corners pointing down are counted twice, corners pointing up are not counted | ||
85 | // borders are counted once | ||
86 | if (intersection.IsIdentical(s.v1, 0.001f)) { | ||
87 | if (s.v2.Y < v1.Y) | ||
88 | continue; | ||
89 | } | ||
90 | // Do this for the other vertex two | ||
91 | if (intersection.IsIdentical(s.v2, 0.001f)) { | ||
92 | if (s.v1.Y<v1.Y) | ||
93 | continue; | ||
94 | } | ||
95 | iCounter++; | ||
96 | } | ||
97 | |||
98 | return iCounter % 2 == 1; // Point is inside if the number of intersections is odd | ||
99 | } | ||
100 | |||
101 | public bool containsPointsFrom(SimpleHull otherHull) | ||
102 | { | ||
103 | foreach (Vertex v in otherHull.vertices) | ||
104 | { | ||
105 | if (IsPointIn(v)) | ||
106 | return true; | ||
107 | } | ||
108 | |||
109 | return false; | ||
110 | } | ||
111 | |||
112 | |||
113 | List<Simplex> buildSimplexList() { | ||
114 | |||
115 | List<Simplex> result = new List<Simplex>(); | ||
116 | |||
117 | // Not asserted but assumed: at least three vertices | ||
118 | for (int i=0; i<vertices.Count-1; i++) { | ||
119 | Simplex s=new Simplex(vertices[i], vertices[i+1]); | ||
120 | result.Add(s); | ||
121 | } | ||
122 | Simplex s1=new Simplex(vertices[vertices.Count-1], vertices[0]); | ||
123 | result.Add(s1); | ||
124 | |||
125 | if (holeVertices.Count==0) | ||
126 | return result; | ||
127 | |||
128 | // Same here. At least three vertices in hole assumed | ||
129 | for (int i = 0; i < holeVertices.Count - 1; i++) | ||
130 | { | ||
131 | Simplex s = new Simplex(holeVertices[i], holeVertices[i + 1]); | ||
132 | result.Add(s); | ||
133 | } | ||
134 | |||
135 | s1 = new Simplex(holeVertices[holeVertices.Count - 1], holeVertices[0]); | ||
136 | result.Add(s1); | ||
137 | return result; | ||
138 | } | ||
139 | |||
140 | bool InsertVertex(Vertex v, int iAfter) | ||
141 | { | ||
142 | vertices.Insert(iAfter + 1, v); | ||
143 | return true; | ||
144 | } | ||
145 | |||
146 | Vertex getNextVertex(Vertex currentVertex) | ||
147 | { | ||
148 | int iCurrentIndex; | ||
149 | iCurrentIndex = vertices.IndexOf(currentVertex); | ||
150 | |||
151 | // Error handling for iCurrentIndex==-1 should go here (and probably never will) | ||
152 | |||
153 | iCurrentIndex++; | ||
154 | if (iCurrentIndex == vertices.Count) | ||
155 | iCurrentIndex = 0; | ||
156 | |||
157 | return vertices[iCurrentIndex]; | ||
158 | } | ||
159 | |||
160 | public Vertex FindVertex(Vertex vBase, float tolerance) { | ||
161 | foreach (Vertex v in vertices) { | ||
162 | if (v.IsIdentical(vBase, tolerance)) | ||
163 | return v; | ||
164 | } | ||
165 | |||
166 | return null; | ||
167 | } | ||
168 | |||
169 | public void FindIntersection(Simplex s, ref Vertex Intersection, ref Vertex nextVertex) | ||
170 | { | ||
171 | Vertex bestIntersection=null; | ||
172 | float distToV1=Single.PositiveInfinity; | ||
173 | Simplex bestIntersectingSimplex=null; | ||
174 | |||
175 | List<Simplex> simple = buildSimplexList(); | ||
176 | foreach (Simplex sTest in simple) | ||
177 | { | ||
178 | Manager.PhysicsVector vvTemp = Simplex.Intersect(sTest, s, -.001f, -.001f, 0.999f, .999f); | ||
179 | |||
180 | Vertex vTemp=null; | ||
181 | if (vvTemp != null) | ||
182 | vTemp = new Vertex(vvTemp); | ||
183 | |||
184 | if (vTemp!=null) { | ||
185 | |||
186 | Manager.PhysicsVector diff=(s.v1-vTemp); | ||
187 | float distTemp=diff.length(); | ||
188 | |||
189 | if (bestIntersection==null || distTemp<distToV1) { | ||
190 | bestIntersection=vTemp; | ||
191 | distToV1=distTemp; | ||
192 | bestIntersectingSimplex = sTest; | ||
193 | } | ||
194 | |||
195 | } // end if vTemp | ||
196 | |||
197 | } // end foreach | ||
198 | |||
199 | Intersection = bestIntersection; | ||
200 | if (bestIntersectingSimplex != null) | ||
201 | nextVertex = bestIntersectingSimplex.v2; | ||
202 | else | ||
203 | nextVertex = null; | ||
204 | } | ||
205 | |||
206 | |||
207 | public static SimpleHull SubtractHull(SimpleHull baseHull, SimpleHull otherHull) | ||
208 | { | ||
209 | |||
210 | SimpleHull baseHullClone = baseHull.Clone(); | ||
211 | SimpleHull otherHullClone = otherHull.Clone(); | ||
212 | bool intersects = false; | ||
213 | |||
214 | MainLog.Instance.Debug("State before intersection detection"); | ||
215 | MainLog.Instance.Debug("The baseHull is:\n{1}", 0, baseHullClone.ToString()); | ||
216 | MainLog.Instance.Debug("The otherHull is:\n{1}", 0, otherHullClone.ToString()); | ||
217 | |||
218 | { | ||
219 | int iBase, iOther; | ||
220 | |||
221 | // Insert into baseHull | ||
222 | for (iBase = 0; iBase < baseHullClone.vertices.Count; iBase++) | ||
223 | { | ||
224 | int iBaseNext = (iBase + 1) % baseHullClone.vertices.Count; | ||
225 | Simplex sBase = new Simplex(baseHullClone.vertices[iBase], baseHullClone.vertices[iBaseNext]); | ||
226 | |||
227 | for (iOther = 0; iOther < otherHullClone.vertices.Count; iOther++) | ||
228 | { | ||
229 | int iOtherNext = (iOther + 1) % otherHullClone.vertices.Count; | ||
230 | Simplex sOther = new Simplex(otherHullClone.vertices[iOther], otherHullClone.vertices[iOtherNext]); | ||
231 | |||
232 | Manager.PhysicsVector intersect = Simplex.Intersect(sBase, sOther, 0.001f, -.001f, 0.999f, 1.001f); | ||
233 | if (intersect != null) | ||
234 | { | ||
235 | Vertex vIntersect = new Vertex(intersect); | ||
236 | baseHullClone.vertices.Insert(iBase + 1, vIntersect); | ||
237 | sBase.v2 = vIntersect; | ||
238 | intersects = true; | ||
239 | } | ||
240 | } | ||
241 | } | ||
242 | } | ||
243 | |||
244 | MainLog.Instance.Debug("State after intersection detection for the base hull"); | ||
245 | MainLog.Instance.Debug("The baseHull is:\n{1}", 0, baseHullClone.ToString()); | ||
246 | |||
247 | { | ||
248 | int iOther, iBase; | ||
249 | |||
250 | // Insert into otherHull | ||
251 | for (iOther = 0; iOther < otherHullClone.vertices.Count; iOther++) | ||
252 | { | ||
253 | int iOtherNext = (iOther + 1) % otherHullClone.vertices.Count; | ||
254 | Simplex sOther = new Simplex(otherHullClone.vertices[iOther], otherHullClone.vertices[iOtherNext]); | ||
255 | |||
256 | for (iBase = 0; iBase < baseHullClone.vertices.Count; iBase++) | ||
257 | { | ||
258 | int iBaseNext = (iBase + 1) % baseHullClone.vertices.Count; | ||
259 | Simplex sBase = new Simplex(baseHullClone.vertices[iBase], baseHullClone.vertices[iBaseNext]); | ||
260 | |||
261 | Manager.PhysicsVector intersect = Simplex.Intersect(sBase, sOther, -.001f, 0.001f, 1.001f, 0.999f); | ||
262 | if (intersect != null) | ||
263 | { | ||
264 | Vertex vIntersect = new Vertex(intersect); | ||
265 | otherHullClone.vertices.Insert(iOther + 1, vIntersect); | ||
266 | sOther.v2 = vIntersect; | ||
267 | intersects = true; | ||
268 | } | ||
269 | } | ||
270 | } | ||
271 | } | ||
272 | |||
273 | MainLog.Instance.Debug("State after intersection detection for the base hull"); | ||
274 | MainLog.Instance.Debug("The otherHull is:\n{1}", 0, otherHullClone.ToString()); | ||
275 | |||
276 | |||
277 | bool otherIsInBase = baseHullClone.containsPointsFrom(otherHullClone); | ||
278 | if (!intersects && otherIsInBase) | ||
279 | { | ||
280 | // We have a hole here | ||
281 | baseHullClone.holeVertices = otherHullClone.vertices; | ||
282 | return baseHullClone; | ||
283 | } | ||
284 | |||
285 | |||
286 | SimpleHull result = new SimpleHull(); | ||
287 | |||
288 | // Find a good starting Simplex from baseHull | ||
289 | // A good starting simplex is one that is outside otherHull | ||
290 | // Such a simplex must exist, otherwise the result will be empty | ||
291 | Vertex baseStartVertex = null; | ||
292 | { | ||
293 | int iBase; | ||
294 | for (iBase = 0; iBase < baseHullClone.vertices.Count; iBase++) | ||
295 | { | ||
296 | int iBaseNext = (iBase + 1) % baseHullClone.vertices.Count; | ||
297 | Vertex center = new Vertex((baseHullClone.vertices[iBase] + baseHullClone.vertices[iBaseNext]) / 2.0f); | ||
298 | bool isOutside = !otherHullClone.IsPointIn(center); | ||
299 | if (isOutside) | ||
300 | { | ||
301 | baseStartVertex = baseHullClone.vertices[iBaseNext]; | ||
302 | break; | ||
303 | } | ||
304 | } | ||
305 | } | ||
306 | |||
307 | |||
308 | if (baseStartVertex == null) // i.e. no simplex fulfilled the "outside" condition. | ||
309 | // In otherwords, subtractHull completely embraces baseHull | ||
310 | { | ||
311 | return result; | ||
312 | } | ||
313 | |||
314 | // The simplex that *starts* with baseStartVertex is outside the cutting hull, | ||
315 | // so we can start our walk with the next vertex without loosing a branch | ||
316 | Vertex V1 = baseStartVertex; | ||
317 | bool onBase = true; | ||
318 | |||
319 | // And here is how we do the magic :-) | ||
320 | // Start on the base hull. | ||
321 | // Walk the vertices in the positive direction | ||
322 | // For each vertex check, whether it is a vertex shared with the other hull | ||
323 | // if this is the case, switch over to walking the other vertex list. | ||
324 | // Note: The other hull *must* go backwards to our starting point (via several orther vertices) | ||
325 | // Thus it is important that the cutting hull has the inverse directional sense than the | ||
326 | // base hull!!!!!!!!! (means if base goes CW around it's center cutting hull must go CCW) | ||
327 | |||
328 | bool done = false; | ||
329 | while (!done) | ||
330 | { | ||
331 | result.AddVertex(V1); | ||
332 | Vertex nextVertex = null; | ||
333 | if (onBase) | ||
334 | { | ||
335 | nextVertex = otherHullClone.FindVertex(V1, 0.001f); | ||
336 | } | ||
337 | else | ||
338 | { | ||
339 | nextVertex = baseHullClone.FindVertex(V1, 0.001f); | ||
340 | } | ||
341 | |||
342 | if (nextVertex != null) // A node that represents an intersection | ||
343 | { | ||
344 | V1 = nextVertex; // Needed to find the next vertex on the other hull | ||
345 | onBase = !onBase; | ||
346 | } | ||
347 | |||
348 | if (onBase) | ||
349 | V1 = baseHullClone.getNextVertex(V1); | ||
350 | else | ||
351 | V1 = otherHullClone.getNextVertex(V1); | ||
352 | |||
353 | if (V1 == baseStartVertex) | ||
354 | done = true; | ||
355 | } | ||
356 | |||
357 | MainLog.Instance.Debug("The resulting Hull is:\n{1}", 0, result.ToString()); | ||
358 | |||
359 | return result; | ||
360 | |||
361 | } | ||
362 | } | ||
363 | } | ||
diff --git a/OpenSim/Region/Physics/Meshing/Simplex.cs b/OpenSim/Region/Physics/Meshing/Simplex.cs new file mode 100644 index 0000000..4944f22 --- /dev/null +++ b/OpenSim/Region/Physics/Meshing/Simplex.cs | |||
@@ -0,0 +1,198 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using OpenSim.Region.Physics.Manager; | ||
5 | |||
6 | namespace OpenSim.Region.Physics.Meshing | ||
7 | { | ||
8 | // A simplex is a section of a straight line. | ||
9 | // It is defined by its endpoints, i.e. by two vertices | ||
10 | // Operation on vertices are | ||
11 | public class Simplex : IComparable<Simplex> | ||
12 | { | ||
13 | public Vertex v1; | ||
14 | public Vertex v2; | ||
15 | |||
16 | public Simplex(Vertex _v1, Vertex _v2) | ||
17 | { | ||
18 | v1 = _v1; | ||
19 | v2 = _v2; | ||
20 | } | ||
21 | |||
22 | public int CompareTo(Simplex other) | ||
23 | { | ||
24 | |||
25 | Vertex lv1, lv2, ov1, ov2, temp; | ||
26 | |||
27 | lv1 = v1; | ||
28 | lv2 = v2; | ||
29 | ov1 = other.v1; | ||
30 | ov2 = other.v2; | ||
31 | |||
32 | if (lv1 > lv2) | ||
33 | { | ||
34 | temp = lv1; | ||
35 | lv1 = lv2; | ||
36 | lv2 = temp; | ||
37 | } | ||
38 | |||
39 | if (ov1 > ov2) | ||
40 | { | ||
41 | temp = ov1; | ||
42 | ov1 = ov2; | ||
43 | ov2 = temp; | ||
44 | } | ||
45 | |||
46 | if (lv1 > ov1) | ||
47 | { | ||
48 | return 1; | ||
49 | } | ||
50 | if (lv1 < ov1) | ||
51 | { | ||
52 | return -1; | ||
53 | } | ||
54 | |||
55 | if (lv2 > ov2) | ||
56 | { | ||
57 | return 1; | ||
58 | } | ||
59 | if (lv2 < ov2) | ||
60 | { | ||
61 | return -1; | ||
62 | } | ||
63 | |||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | private static void intersectParameter(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2, PhysicsVector r2, ref float lambda, ref float mu) | ||
68 | { | ||
69 | // Intersects two straights | ||
70 | // p1, p2, points on the straight | ||
71 | // r1, r2, directional vectors of the straight. Not necessarily of length 1! | ||
72 | // note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points, | ||
73 | // thus allowing to decide whether an intersection is between two points | ||
74 | |||
75 | float r1x = r1.X; | ||
76 | float r1y = r1.Y; | ||
77 | float r2x = r2.X; | ||
78 | float r2y = r2.Y; | ||
79 | |||
80 | float denom = r1y*r2x - r1x*r2y; | ||
81 | |||
82 | float p1x = p1.X; | ||
83 | float p1y = p1.Y; | ||
84 | float p2x = p2.X; | ||
85 | float p2y = p2.Y; | ||
86 | |||
87 | float z1=-p2x * r2y + p1x * r2y + (p2y - p1y) * r2x; | ||
88 | float z2=-p2x * r1y + p1x * r1y + (p2y - p1y) * r1x; | ||
89 | |||
90 | if (denom == 0.0f) // Means the straights are parallel. Either no intersection or an infinite number of them | ||
91 | { | ||
92 | if (z1==0.0f) {// Means they are identical -> many, many intersections | ||
93 | lambda = Single.NaN; | ||
94 | mu = Single.NaN; | ||
95 | } else { | ||
96 | lambda = Single.PositiveInfinity; | ||
97 | mu = Single.PositiveInfinity; | ||
98 | } | ||
99 | return; | ||
100 | |||
101 | } | ||
102 | |||
103 | |||
104 | |||
105 | lambda = z1 / denom; | ||
106 | mu = z2 / denom; | ||
107 | |||
108 | } | ||
109 | |||
110 | |||
111 | // Intersects the simplex with another one. | ||
112 | // the borders are used to deal with float inaccuracies | ||
113 | // As a rule of thumb, the borders are | ||
114 | // lowerBorder1 : 0.0 | ||
115 | // lowerBorder2 : 0.0 | ||
116 | // upperBorder1 : 1.0 | ||
117 | // upperBorder2 : 1.0 | ||
118 | // 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) | ||
119 | public static PhysicsVector Intersect( | ||
120 | Simplex s1, | ||
121 | Simplex s2, | ||
122 | float lowerBorder1, | ||
123 | float lowerBorder2, | ||
124 | float upperBorder1, | ||
125 | float upperBorder2) | ||
126 | { | ||
127 | PhysicsVector firstSimplexDirection = s1.v2 - s1.v1; | ||
128 | PhysicsVector secondSimplexDirection = s2.v2 - s2.v1; | ||
129 | |||
130 | float lambda = 0.0f; | ||
131 | float mu = 0.0f; | ||
132 | |||
133 | // Give us the parameters of an intersection. This subroutine does *not* take the constraints | ||
134 | // (intersection must be between v1 and v2 and it must be in the positive direction of the ray) | ||
135 | // into account. We do that afterwards. | ||
136 | intersectParameter(s1.v1, firstSimplexDirection, s2.v1, secondSimplexDirection, ref lambda, ref mu); | ||
137 | |||
138 | if (Single.IsInfinity(lambda)) // Special case. No intersection at all. directions parallel. | ||
139 | return null; | ||
140 | |||
141 | if (Single.IsNaN(lambda)) // Special case. many, many intersections. | ||
142 | return null; | ||
143 | |||
144 | if (lambda > upperBorder1) // We're behind v2 | ||
145 | return null; | ||
146 | |||
147 | if (lambda < lowerBorder1) | ||
148 | return null; | ||
149 | |||
150 | if (mu < lowerBorder2) // outside simplex 2 | ||
151 | return null; | ||
152 | |||
153 | if (mu > upperBorder2) // outside simplex 2 | ||
154 | return null; | ||
155 | |||
156 | return s1.v1 + lambda * firstSimplexDirection; | ||
157 | |||
158 | } | ||
159 | |||
160 | // Intersects the simplex with a ray. The ray is defined as all p=origin + lambda*direction | ||
161 | // where lambda >= 0 | ||
162 | public PhysicsVector RayIntersect(Vertex origin, PhysicsVector direction, bool bEndsIncluded) | ||
163 | { | ||
164 | PhysicsVector simplexDirection = v2 - v1; | ||
165 | |||
166 | float lambda = 0.0f; | ||
167 | float mu = 0.0f; | ||
168 | |||
169 | // Give us the parameters of an intersection. This subroutine does *not* take the constraints | ||
170 | // (intersection must be between v1 and v2 and it must be in the positive direction of the ray) | ||
171 | // into account. We do that afterwards. | ||
172 | intersectParameter(v1, simplexDirection, origin, direction, ref lambda, ref mu); | ||
173 | |||
174 | if (Single.IsInfinity(lambda)) // Special case. No intersection at all. directions parallel. | ||
175 | return null; | ||
176 | |||
177 | if (Single.IsNaN(lambda)) // Special case. many, many intersections. | ||
178 | return null; | ||
179 | |||
180 | if (mu < 0.0) // We're on the wrong side of the ray | ||
181 | return null; | ||
182 | |||
183 | if (lambda > 1.0) // We're behind v2 | ||
184 | return null; | ||
185 | |||
186 | if (lambda == 1.0 && !bEndsIncluded) | ||
187 | return null; // The end of the simplices are not included | ||
188 | |||
189 | if (lambda < 0.0f) // we're before v1; | ||
190 | return null; | ||
191 | |||
192 | return this.v1 + lambda * simplexDirection; | ||
193 | |||
194 | } | ||
195 | |||
196 | |||
197 | } | ||
198 | } \ 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; | |||
32 | using Ode.NET; | 32 | using Ode.NET; |
33 | using OpenSim.Framework; | 33 | using OpenSim.Framework; |
34 | using OpenSim.Region.Physics.Manager; | 34 | using OpenSim.Region.Physics.Manager; |
35 | using OpenSim.Region.Physics.OdePlugin.Meshing; | 35 | //using OpenSim.Region.Physics.OdePlugin.Meshing; |
36 | 36 | ||
37 | namespace OpenSim.Region.Physics.OdePlugin | 37 | namespace OpenSim.Region.Physics.OdePlugin |
38 | { | 38 | { |
@@ -98,6 +98,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
98 | public IntPtr space; | 98 | public IntPtr space; |
99 | public static Object OdeLock = new Object(); | 99 | public static Object OdeLock = new Object(); |
100 | 100 | ||
101 | public IMesher mesher; | ||
102 | |||
101 | public OdeScene() | 103 | public OdeScene() |
102 | { | 104 | { |
103 | nearCallback = near; | 105 | nearCallback = near; |
@@ -137,6 +139,12 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
137 | 139 | ||
138 | } | 140 | } |
139 | 141 | ||
142 | public override void Initialise(IMesher meshmerizer) | ||
143 | { | ||
144 | mesher = meshmerizer; | ||
145 | } | ||
146 | |||
147 | |||
140 | // This function blatantly ripped off from BoxStack.cs | 148 | // This function blatantly ripped off from BoxStack.cs |
141 | private void near(IntPtr space, IntPtr g1, IntPtr g2) | 149 | private void near(IntPtr space, IntPtr g1, IntPtr g2) |
142 | { | 150 | { |
@@ -308,7 +316,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
308 | } | 316 | } |
309 | 317 | ||
310 | private PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, Quaternion rotation, | 318 | private PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, Quaternion rotation, |
311 | Mesh mesh, PrimitiveBaseShape pbs, bool isphysical) | 319 | IMesh mesh, PrimitiveBaseShape pbs, bool isphysical) |
312 | { | 320 | { |
313 | PhysicsVector pos = new PhysicsVector(); | 321 | PhysicsVector pos = new PhysicsVector(); |
314 | pos.X = position.X; | 322 | pos.X = position.X; |
@@ -409,11 +417,12 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
409 | { | 417 | { |
410 | return this.AddPrimShape(primName, pbs, position, size, rotation, false); | 418 | return this.AddPrimShape(primName, pbs, position, size, rotation, false); |
411 | } | 419 | } |
420 | |||
412 | public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, | 421 | public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, |
413 | PhysicsVector size, Quaternion rotation, bool isPhysical) | 422 | PhysicsVector size, Quaternion rotation, bool isPhysical) |
414 | { | 423 | { |
415 | PhysicsActor result; | 424 | PhysicsActor result; |
416 | Mesh mesh = null; | 425 | IMesh mesh = null; |
417 | 426 | ||
418 | switch (pbs.ProfileShape) | 427 | switch (pbs.ProfileShape) |
419 | { | 428 | { |
@@ -421,7 +430,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
421 | /// support simple box & hollow box now; later, more shapes | 430 | /// support simple box & hollow box now; later, more shapes |
422 | if (needsMeshing(pbs)) | 431 | if (needsMeshing(pbs)) |
423 | { | 432 | { |
424 | mesh = Meshmerizer.CreateMesh(primName, pbs, size); | 433 | mesh = mesher.CreateMesh(primName, pbs, size); |
425 | } | 434 | } |
426 | 435 | ||
427 | break; | 436 | break; |
@@ -931,7 +940,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
931 | private PhysicsVector _acceleration; | 940 | private PhysicsVector _acceleration; |
932 | public Quaternion _orientation; | 941 | public Quaternion _orientation; |
933 | 942 | ||
934 | private Mesh _mesh; | 943 | private IMesh _mesh; |
935 | private PrimitiveBaseShape _pbs; | 944 | private PrimitiveBaseShape _pbs; |
936 | private OdeScene _parent_scene; | 945 | private OdeScene _parent_scene; |
937 | public IntPtr prim_geom; | 946 | public IntPtr prim_geom; |
@@ -953,7 +962,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
953 | 962 | ||
954 | 963 | ||
955 | public OdePrim(String primName, OdeScene parent_scene, PhysicsVector pos, PhysicsVector size, | 964 | public OdePrim(String primName, OdeScene parent_scene, PhysicsVector pos, PhysicsVector size, |
956 | Quaternion rotation, Mesh mesh, PrimitiveBaseShape pbs, bool pisPhysical) | 965 | Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical) |
957 | { | 966 | { |
958 | 967 | ||
959 | 968 | ||
@@ -1036,15 +1045,15 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1036 | Body = (IntPtr)0; | 1045 | Body = (IntPtr)0; |
1037 | } | 1046 | } |
1038 | } | 1047 | } |
1039 | public void setMesh(OdeScene parent_scene, Mesh mesh) | 1048 | public void setMesh(OdeScene parent_scene, IMesh mesh) |
1040 | { | 1049 | { |
1041 | //Kill Body so that mesh can re-make the geom | 1050 | //Kill Body so that mesh can re-make the geom |
1042 | if (IsPhysical && Body != (IntPtr)0) | 1051 | if (IsPhysical && Body != (IntPtr)0) |
1043 | { | 1052 | { |
1044 | disableBody(); | 1053 | disableBody(); |
1045 | } | 1054 | } |
1046 | float[] vertexList = mesh.getVertexListAsFloat(); // Note, that vertextList is pinned in memory | 1055 | float[] vertexList = mesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory |
1047 | int[] indexList = mesh.getIndexListAsInt(); // Also pinned, needs release after usage | 1056 | int[] indexList = mesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage |
1048 | int VertexCount = vertexList.GetLength(0)/3; | 1057 | int VertexCount = vertexList.GetLength(0)/3; |
1049 | int IndexCount = indexList.GetLength(0); | 1058 | int IndexCount = indexList.GetLength(0); |
1050 | 1059 | ||
@@ -1169,7 +1178,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1169 | 1178 | ||
1170 | 1179 | ||
1171 | // Don't need to re-enable body.. it's done in SetMesh | 1180 | // Don't need to re-enable body.. it's done in SetMesh |
1172 | Mesh mesh = Meshmerizer.CreateMesh(oldname, _pbs, _size); | 1181 | IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size); |
1173 | // createmesh returns null when it's a shape that isn't a cube. | 1182 | // createmesh returns null when it's a shape that isn't a cube. |
1174 | if (mesh != null) | 1183 | if (mesh != null) |
1175 | setMesh(_parent_scene, mesh); | 1184 | setMesh(_parent_scene, mesh); |
@@ -1218,7 +1227,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1218 | // Construction of new prim | 1227 | // Construction of new prim |
1219 | if (this._parent_scene.needsMeshing(_pbs)) | 1228 | if (this._parent_scene.needsMeshing(_pbs)) |
1220 | { | 1229 | { |
1221 | Mesh mesh = Meshmerizer.CreateMesh(oldname, _pbs, _size); | 1230 | IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size); |
1222 | setMesh(_parent_scene, mesh); | 1231 | setMesh(_parent_scene, mesh); |
1223 | } else { | 1232 | } else { |
1224 | prim_geom = d.CreateBox(_parent_scene.space, _size.X, _size.Y, _size.Z); | 1233 | 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 | |||
84 | scene = mySdk.CreateScene(); | 84 | scene = mySdk.CreateScene(); |
85 | } | 85 | } |
86 | 86 | ||
87 | public override void Initialise(IMesher meshmerizer) | ||
88 | { | ||
89 | // Does nothing right now | ||
90 | } | ||
91 | |||
92 | |||
87 | public override PhysicsActor AddAvatar(string avName, PhysicsVector position) | 93 | public override PhysicsActor AddAvatar(string avName, PhysicsVector position) |
88 | { | 94 | { |
89 | Vec3 pos = new Vec3(); | 95 | Vec3 pos = new Vec3(); |