diff options
Diffstat (limited to 'OpenSim/Region/Physics')
17 files changed, 2334 insertions, 1174 deletions
diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index 5b743e8..8de70ef 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | |||
@@ -2190,7 +2190,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2190 | convex = false; | 2190 | convex = false; |
2191 | try | 2191 | try |
2192 | { | 2192 | { |
2193 | _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, (int)LevelOfDetail.High, true,convex); | 2193 | _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, (int)LevelOfDetail.High, true,convex,false); |
2194 | } | 2194 | } |
2195 | catch | 2195 | catch |
2196 | { | 2196 | { |
@@ -2557,7 +2557,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2557 | 2557 | ||
2558 | try | 2558 | try |
2559 | { | 2559 | { |
2560 | mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, (int)LevelOfDetail.High, true, convex); | 2560 | mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, (int)LevelOfDetail.High, true, convex,false); |
2561 | } | 2561 | } |
2562 | catch | 2562 | catch |
2563 | { | 2563 | { |
diff --git a/OpenSim/Region/Physics/Manager/IMesher.cs b/OpenSim/Region/Physics/Manager/IMesher.cs index a8c99f7..ecc2918 100644 --- a/OpenSim/Region/Physics/Manager/IMesher.cs +++ b/OpenSim/Region/Physics/Manager/IMesher.cs | |||
@@ -37,9 +37,11 @@ namespace OpenSim.Region.Physics.Manager | |||
37 | { | 37 | { |
38 | IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod); | 38 | IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod); |
39 | IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical); | 39 | IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical); |
40 | IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical,bool convex); | 40 | IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde); |
41 | IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex); | ||
41 | void ReleaseMesh(IMesh mesh); | 42 | void ReleaseMesh(IMesh mesh); |
42 | void ExpireReleaseMeshs(); | 43 | void ExpireReleaseMeshs(); |
44 | void ExpireFileCache(); | ||
43 | } | 45 | } |
44 | 46 | ||
45 | // Values for level of detail to be passed to the mesher. | 47 | // Values for level of detail to be passed to the mesher. |
@@ -57,6 +59,7 @@ namespace OpenSim.Region.Physics.Manager | |||
57 | { | 59 | { |
58 | } | 60 | } |
59 | 61 | ||
62 | [Serializable()] | ||
60 | [StructLayout(LayoutKind.Explicit)] | 63 | [StructLayout(LayoutKind.Explicit)] |
61 | public struct AMeshKey | 64 | public struct AMeshKey |
62 | { | 65 | { |
@@ -66,6 +69,13 @@ namespace OpenSim.Region.Physics.Manager | |||
66 | public ulong hashA; | 69 | public ulong hashA; |
67 | [FieldOffset(8)] | 70 | [FieldOffset(8)] |
68 | public ulong hashB; | 71 | public ulong hashB; |
72 | [FieldOffset(16)] | ||
73 | public ulong hashC; | ||
74 | |||
75 | public override string ToString() | ||
76 | { | ||
77 | return uuid.ToString() + "-" + hashC.ToString("x") ; | ||
78 | } | ||
69 | } | 79 | } |
70 | 80 | ||
71 | public interface IMesh | 81 | public interface IMesh |
@@ -81,5 +91,6 @@ namespace OpenSim.Region.Physics.Manager | |||
81 | void Append(IMesh newMesh); | 91 | void Append(IMesh newMesh); |
82 | void TransformLinear(float[,] matrix, float[] offset); | 92 | void TransformLinear(float[,] matrix, float[] offset); |
83 | Vector3 GetCentroid(); | 93 | Vector3 GetCentroid(); |
94 | Vector3 GetOBB(); | ||
84 | } | 95 | } |
85 | } | 96 | } |
diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs index a2c72c3..14f65b8 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs | |||
@@ -315,6 +315,23 @@ namespace OpenSim.Region.Physics.Manager | |||
315 | } | 315 | } |
316 | } | 316 | } |
317 | 317 | ||
318 | |||
319 | public virtual float PhysicsCost | ||
320 | { | ||
321 | get | ||
322 | { | ||
323 | return 0.1f; | ||
324 | } | ||
325 | } | ||
326 | |||
327 | public virtual float StreamCost | ||
328 | { | ||
329 | get | ||
330 | { | ||
331 | return 1.0f; | ||
332 | } | ||
333 | } | ||
334 | |||
318 | /// <summary> | 335 | /// <summary> |
319 | /// Velocity of this actor. | 336 | /// Velocity of this actor. |
320 | /// </summary> | 337 | /// </summary> |
diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs index 5274f3b..ce269fa 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs | |||
@@ -106,7 +106,7 @@ namespace OpenSim.Region.Physics.Manager | |||
106 | get { return new NullPhysicsScene(); } | 106 | get { return new NullPhysicsScene(); } |
107 | } | 107 | } |
108 | 108 | ||
109 | public RequestAssetDelegate RequestAssetMethod { private get; set; } | 109 | public RequestAssetDelegate RequestAssetMethod { get; set; } |
110 | 110 | ||
111 | public virtual void TriggerPhysicsBasedRestart() | 111 | public virtual void TriggerPhysicsBasedRestart() |
112 | { | 112 | { |
@@ -246,6 +246,9 @@ namespace OpenSim.Region.Physics.Manager | |||
246 | 246 | ||
247 | public abstract void AddPhysicsActorTaint(PhysicsActor prim); | 247 | public abstract void AddPhysicsActorTaint(PhysicsActor prim); |
248 | 248 | ||
249 | |||
250 | public virtual void PrepareSimulation() { } | ||
251 | |||
249 | /// <summary> | 252 | /// <summary> |
250 | /// Perform a simulation of the current physics scene over the given timestep. | 253 | /// Perform a simulation of the current physics scene over the given timestep. |
251 | /// </summary> | 254 | /// </summary> |
diff --git a/OpenSim/Region/Physics/Manager/ZeroMesher.cs b/OpenSim/Region/Physics/Manager/ZeroMesher.cs index f555cb9..16846e6 100644 --- a/OpenSim/Region/Physics/Manager/ZeroMesher.cs +++ b/OpenSim/Region/Physics/Manager/ZeroMesher.cs | |||
@@ -67,7 +67,7 @@ namespace OpenSim.Region.Physics.Manager | |||
67 | return CreateMesh(primName, primShape, size, lod, false); | 67 | return CreateMesh(primName, primShape, size, lod, false); |
68 | } | 68 | } |
69 | 69 | ||
70 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex) | 70 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex,bool forOde) |
71 | { | 71 | { |
72 | return CreateMesh(primName, primShape, size, lod, false); | 72 | return CreateMesh(primName, primShape, size, lod, false); |
73 | } | 73 | } |
@@ -79,7 +79,14 @@ namespace OpenSim.Region.Physics.Manager | |||
79 | 79 | ||
80 | return null; | 80 | return null; |
81 | } | 81 | } |
82 | |||
83 | public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex) | ||
84 | { | ||
85 | return null; | ||
86 | } | ||
87 | |||
82 | public void ReleaseMesh(IMesh mesh) { } | 88 | public void ReleaseMesh(IMesh mesh) { } |
83 | public void ExpireReleaseMeshs() { } | 89 | public void ExpireReleaseMeshs() { } |
90 | public void ExpireFileCache() { } | ||
84 | } | 91 | } |
85 | } | 92 | } |
diff --git a/OpenSim/Region/Physics/Meshing/Mesh.cs b/OpenSim/Region/Physics/Meshing/Mesh.cs index c715642..6970553 100644 --- a/OpenSim/Region/Physics/Meshing/Mesh.cs +++ b/OpenSim/Region/Physics/Meshing/Mesh.cs | |||
@@ -148,6 +148,12 @@ namespace OpenSim.Region.Physics.Meshing | |||
148 | return Vector3.Zero; | 148 | return Vector3.Zero; |
149 | } | 149 | } |
150 | 150 | ||
151 | // not functional | ||
152 | public Vector3 GetOBB() | ||
153 | { | ||
154 | return new Vector3(0.5f, 0.5f, 0.5f); | ||
155 | } | ||
156 | |||
151 | public void CalcNormals() | 157 | public void CalcNormals() |
152 | { | 158 | { |
153 | int iTriangles = m_triangles.Count; | 159 | int iTriangles = m_triangles.Count; |
@@ -253,6 +259,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
253 | public void getVertexListAsPtrToFloatArray(out IntPtr vertices, out int vertexStride, out int vertexCount) | 259 | public void getVertexListAsPtrToFloatArray(out IntPtr vertices, out int vertexStride, out int vertexCount) |
254 | { | 260 | { |
255 | // A vertex is 3 floats | 261 | // A vertex is 3 floats |
262 | |||
256 | vertexStride = 3 * sizeof(float); | 263 | vertexStride = 3 * sizeof(float); |
257 | 264 | ||
258 | // If there isn't an unmanaged array allocated yet, do it now | 265 | // If there isn't an unmanaged array allocated yet, do it now |
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 3c4f737..f629c4d 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs | |||
@@ -74,8 +74,6 @@ namespace OpenSim.Region.Physics.Meshing | |||
74 | #endif | 74 | #endif |
75 | 75 | ||
76 | private bool cacheSculptMaps = true; | 76 | private bool cacheSculptMaps = true; |
77 | private bool cacheSculptAlphaMaps = true; | ||
78 | |||
79 | private string decodedSculptMapPath = null; | 77 | private string decodedSculptMapPath = null; |
80 | private bool useMeshiesPhysicsMesh = false; | 78 | private bool useMeshiesPhysicsMesh = false; |
81 | 79 | ||
@@ -89,16 +87,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
89 | IConfig mesh_config = config.Configs["Mesh"]; | 87 | IConfig mesh_config = config.Configs["Mesh"]; |
90 | 88 | ||
91 | decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); | 89 | decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); |
92 | |||
93 | cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); | 90 | cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); |
94 | |||
95 | if (Environment.OSVersion.Platform == PlatformID.Unix) | ||
96 | { | ||
97 | cacheSculptAlphaMaps = false; | ||
98 | } | ||
99 | else | ||
100 | cacheSculptAlphaMaps = cacheSculptMaps; | ||
101 | |||
102 | if(mesh_config != null) | 91 | if(mesh_config != null) |
103 | useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); | 92 | useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); |
104 | 93 | ||
@@ -279,18 +268,15 @@ namespace OpenSim.Region.Physics.Meshing | |||
279 | { | 268 | { |
280 | if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, out coords, out faces)) | 269 | if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, out coords, out faces)) |
281 | return null; | 270 | return null; |
282 | // Remove the reference to any JPEG2000 sculpt data so it can be GCed | ||
283 | // don't loose it | ||
284 | // primShape.SculptData = Utils.EmptyBytes; | ||
285 | } | 271 | } |
286 | // primShape.SculptDataLoaded = true; | ||
287 | } | 272 | } |
288 | else | 273 | else |
289 | { | 274 | { |
290 | if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces)) | 275 | if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces)) |
291 | return null; | 276 | return null; |
292 | } | 277 | } |
293 | // keep compatible | 278 | |
279 | // Remove the reference to any JPEG2000 sculpt data so it can be GCed | ||
294 | primShape.SculptData = Utils.EmptyBytes; | 280 | primShape.SculptData = Utils.EmptyBytes; |
295 | 281 | ||
296 | int numCoords = coords.Count; | 282 | int numCoords = coords.Count; |
@@ -335,7 +321,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
335 | 321 | ||
336 | if (primShape.SculptData.Length <= 0) | 322 | if (primShape.SculptData.Length <= 0) |
337 | { | 323 | { |
338 | m_log.InfoFormat("[MESH]: asset data for {0} is zero length", primName); | 324 | // m_log.ErrorFormat("[MESH]: asset data for {0} is zero length", primName); |
339 | return false; | 325 | return false; |
340 | } | 326 | } |
341 | 327 | ||
@@ -496,8 +482,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
496 | 482 | ||
497 | //idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData); | 483 | //idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData); |
498 | 484 | ||
499 | if (cacheSculptMaps && (cacheSculptAlphaMaps || (((ImageFlags)(idata.Flags) & ImageFlags.HasAlpha) ==0))) | 485 | if (cacheSculptMaps) |
500 | // don't cache images with alpha channel in linux since mono can't load them correctly) | ||
501 | { | 486 | { |
502 | try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); } | 487 | try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); } |
503 | catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); } | 488 | catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); } |
@@ -717,7 +702,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
717 | return CreateMesh(primName, primShape, size, lod, false); | 702 | return CreateMesh(primName, primShape, size, lod, false); |
718 | } | 703 | } |
719 | 704 | ||
720 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex) | 705 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde) |
721 | { | 706 | { |
722 | return CreateMesh(primName, primShape, size, lod, false); | 707 | return CreateMesh(primName, primShape, size, lod, false); |
723 | } | 708 | } |
@@ -763,7 +748,13 @@ namespace OpenSim.Region.Physics.Meshing | |||
763 | 748 | ||
764 | return mesh; | 749 | return mesh; |
765 | } | 750 | } |
751 | public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex) | ||
752 | { | ||
753 | return null; | ||
754 | } | ||
755 | |||
766 | public void ReleaseMesh(IMesh imesh) { } | 756 | public void ReleaseMesh(IMesh imesh) { } |
767 | public void ExpireReleaseMeshs() { } | 757 | public void ExpireReleaseMeshs() { } |
758 | public void ExpireFileCache() { } | ||
768 | } | 759 | } |
769 | } | 760 | } |
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index a41c856..b2c2d8a 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | |||
@@ -63,6 +63,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
63 | 63 | ||
64 | private bool m_isphysical; | 64 | private bool m_isphysical; |
65 | 65 | ||
66 | public int ExpectedCollisionContacts { get { return m_expectedCollisionContacts; } } | ||
67 | private int m_expectedCollisionContacts = 0; | ||
68 | |||
66 | /// <summary> | 69 | /// <summary> |
67 | /// Is this prim subject to physics? Even if not, it's still solid for collision purposes. | 70 | /// Is this prim subject to physics? Even if not, it's still solid for collision purposes. |
68 | /// </summary> | 71 | /// </summary> |
@@ -97,6 +100,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
97 | private Vector3 m_taintAngularLock = Vector3.One; | 100 | private Vector3 m_taintAngularLock = Vector3.One; |
98 | private IntPtr Amotor = IntPtr.Zero; | 101 | private IntPtr Amotor = IntPtr.Zero; |
99 | 102 | ||
103 | private object m_assetsLock = new object(); | ||
104 | private bool m_assetFailed = false; | ||
105 | |||
100 | private Vector3 m_PIDTarget; | 106 | private Vector3 m_PIDTarget; |
101 | private float m_PIDTau; | 107 | private float m_PIDTau; |
102 | private float PID_D = 35f; | 108 | private float PID_D = 35f; |
@@ -279,6 +285,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
279 | } | 285 | } |
280 | 286 | ||
281 | m_taintadd = true; | 287 | m_taintadd = true; |
288 | m_assetFailed = false; | ||
282 | _parent_scene.AddPhysicsActorTaint(this); | 289 | _parent_scene.AddPhysicsActorTaint(this); |
283 | } | 290 | } |
284 | 291 | ||
@@ -601,8 +608,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
601 | break; | 608 | break; |
602 | 609 | ||
603 | case HollowShape.Circle: | 610 | case HollowShape.Circle: |
604 | // Hollow shape is a perfect cylinder in respect to the cube's scale | 611 | // Hollow shape is a perfect cyllinder in respect to the cube's scale |
605 | // Cylinder hollow volume calculation | 612 | // Cyllinder hollow volume calculation |
606 | 613 | ||
607 | hollowVolume *= 0.1963495f * 3.07920140172638f; | 614 | hollowVolume *= 0.1963495f * 3.07920140172638f; |
608 | break; | 615 | break; |
@@ -840,7 +847,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
840 | int vertexStride, triStride; | 847 | int vertexStride, triStride; |
841 | mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap | 848 | mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap |
842 | mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage | 849 | mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage |
843 | 850 | m_expectedCollisionContacts = indexCount; | |
844 | mesh.releaseSourceMeshData(); // free up the original mesh data to save memory | 851 | mesh.releaseSourceMeshData(); // free up the original mesh data to save memory |
845 | 852 | ||
846 | // We must lock here since m_MeshToTriMeshMap is static and multiple scene threads may call this method at | 853 | // We must lock here since m_MeshToTriMeshMap is static and multiple scene threads may call this method at |
@@ -1377,6 +1384,7 @@ Console.WriteLine("CreateGeom:"); | |||
1377 | { | 1384 | { |
1378 | //Console.WriteLine(" CreateGeom 1"); | 1385 | //Console.WriteLine(" CreateGeom 1"); |
1379 | SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); | 1386 | SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); |
1387 | m_expectedCollisionContacts = 3; | ||
1380 | } | 1388 | } |
1381 | catch (AccessViolationException) | 1389 | catch (AccessViolationException) |
1382 | { | 1390 | { |
@@ -1391,6 +1399,7 @@ Console.WriteLine("CreateGeom:"); | |||
1391 | { | 1399 | { |
1392 | //Console.WriteLine(" CreateGeom 2"); | 1400 | //Console.WriteLine(" CreateGeom 2"); |
1393 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); | 1401 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); |
1402 | m_expectedCollisionContacts = 4; | ||
1394 | } | 1403 | } |
1395 | catch (AccessViolationException) | 1404 | catch (AccessViolationException) |
1396 | { | 1405 | { |
@@ -1406,6 +1415,7 @@ Console.WriteLine("CreateGeom:"); | |||
1406 | { | 1415 | { |
1407 | //Console.WriteLine(" CreateGeom 3"); | 1416 | //Console.WriteLine(" CreateGeom 3"); |
1408 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); | 1417 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); |
1418 | m_expectedCollisionContacts = 4; | ||
1409 | } | 1419 | } |
1410 | catch (AccessViolationException) | 1420 | catch (AccessViolationException) |
1411 | { | 1421 | { |
@@ -1421,6 +1431,7 @@ Console.WriteLine("CreateGeom:"); | |||
1421 | { | 1431 | { |
1422 | //Console.WriteLine(" CreateGeom 4"); | 1432 | //Console.WriteLine(" CreateGeom 4"); |
1423 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); | 1433 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); |
1434 | m_expectedCollisionContacts = 4; | ||
1424 | } | 1435 | } |
1425 | catch (AccessViolationException) | 1436 | catch (AccessViolationException) |
1426 | { | 1437 | { |
@@ -1446,11 +1457,13 @@ Console.WriteLine("CreateGeom:"); | |||
1446 | _parent_scene.geom_name_map.Remove(prim_geom); | 1457 | _parent_scene.geom_name_map.Remove(prim_geom); |
1447 | _parent_scene.actor_name_map.Remove(prim_geom); | 1458 | _parent_scene.actor_name_map.Remove(prim_geom); |
1448 | d.GeomDestroy(prim_geom); | 1459 | d.GeomDestroy(prim_geom); |
1460 | m_expectedCollisionContacts = 0; | ||
1449 | prim_geom = IntPtr.Zero; | 1461 | prim_geom = IntPtr.Zero; |
1450 | } | 1462 | } |
1451 | catch (System.AccessViolationException) | 1463 | catch (System.AccessViolationException) |
1452 | { | 1464 | { |
1453 | prim_geom = IntPtr.Zero; | 1465 | prim_geom = IntPtr.Zero; |
1466 | m_expectedCollisionContacts = 0; | ||
1454 | m_log.ErrorFormat("[PHYSICS]: PrimGeom dead for {0}", Name); | 1467 | m_log.ErrorFormat("[PHYSICS]: PrimGeom dead for {0}", Name); |
1455 | 1468 | ||
1456 | return false; | 1469 | return false; |
@@ -1489,6 +1502,8 @@ Console.WriteLine("CreateGeom:"); | |||
1489 | mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical); | 1502 | mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical); |
1490 | // createmesh returns null when it's a shape that isn't a cube. | 1503 | // createmesh returns null when it's a shape that isn't a cube. |
1491 | // m_log.Debug(m_localID); | 1504 | // m_log.Debug(m_localID); |
1505 | if (mesh == null) | ||
1506 | CheckMeshAsset(); | ||
1492 | } | 1507 | } |
1493 | 1508 | ||
1494 | #if SPAM | 1509 | #if SPAM |
@@ -1988,7 +2003,12 @@ Console.WriteLine(" JointCreateFixed"); | |||
1988 | // Don't need to re-enable body.. it's done in SetMesh | 2003 | // Don't need to re-enable body.. it's done in SetMesh |
1989 | 2004 | ||
1990 | if (_parent_scene.needsMeshing(_pbs)) | 2005 | if (_parent_scene.needsMeshing(_pbs)) |
2006 | { | ||
1991 | mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical); | 2007 | mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical); |
2008 | if (mesh == null) | ||
2009 | CheckMeshAsset(); | ||
2010 | } | ||
2011 | |||
1992 | } | 2012 | } |
1993 | 2013 | ||
1994 | CreateGeom(m_targetSpace, mesh); | 2014 | CreateGeom(m_targetSpace, mesh); |
@@ -2048,6 +2068,8 @@ Console.WriteLine(" JointCreateFixed"); | |||
2048 | /// </summary> | 2068 | /// </summary> |
2049 | private void changeshape() | 2069 | private void changeshape() |
2050 | { | 2070 | { |
2071 | m_taintshape = false; | ||
2072 | |||
2051 | // Cleanup of old prim geometry and Bodies | 2073 | // Cleanup of old prim geometry and Bodies |
2052 | if (IsPhysical && Body != IntPtr.Zero) | 2074 | if (IsPhysical && Body != IntPtr.Zero) |
2053 | { | 2075 | { |
@@ -2075,6 +2097,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
2075 | 2097 | ||
2076 | IMesh mesh = null; | 2098 | IMesh mesh = null; |
2077 | 2099 | ||
2100 | |||
2078 | if (_parent_scene.needsMeshing(_pbs)) | 2101 | if (_parent_scene.needsMeshing(_pbs)) |
2079 | { | 2102 | { |
2080 | // Don't need to re-enable body.. it's done in CreateMesh | 2103 | // Don't need to re-enable body.. it's done in CreateMesh |
@@ -2085,6 +2108,8 @@ Console.WriteLine(" JointCreateFixed"); | |||
2085 | 2108 | ||
2086 | // createmesh returns null when it doesn't mesh. | 2109 | // createmesh returns null when it doesn't mesh. |
2087 | mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical); | 2110 | mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical); |
2111 | if (mesh == null) | ||
2112 | CheckMeshAsset(); | ||
2088 | } | 2113 | } |
2089 | 2114 | ||
2090 | CreateGeom(m_targetSpace, mesh); | 2115 | CreateGeom(m_targetSpace, mesh); |
@@ -2121,7 +2146,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
2121 | } | 2146 | } |
2122 | 2147 | ||
2123 | resetCollisionAccounting(); | 2148 | resetCollisionAccounting(); |
2124 | m_taintshape = false; | 2149 | // m_taintshape = false; |
2125 | } | 2150 | } |
2126 | 2151 | ||
2127 | /// <summary> | 2152 | /// <summary> |
@@ -2387,6 +2412,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
2387 | set | 2412 | set |
2388 | { | 2413 | { |
2389 | _pbs = value; | 2414 | _pbs = value; |
2415 | m_assetFailed = false; | ||
2390 | m_taintshape = true; | 2416 | m_taintshape = true; |
2391 | } | 2417 | } |
2392 | } | 2418 | } |
@@ -2395,15 +2421,15 @@ Console.WriteLine(" JointCreateFixed"); | |||
2395 | { | 2421 | { |
2396 | get | 2422 | get |
2397 | { | 2423 | { |
2398 | // Averate previous velocity with the new one so | 2424 | // Average previous velocity with the new one so |
2399 | // client object interpolation works a 'little' better | 2425 | // client object interpolation works a 'little' better |
2400 | if (_zeroFlag) | 2426 | if (_zeroFlag) |
2401 | return Vector3.Zero; | 2427 | return Vector3.Zero; |
2402 | 2428 | ||
2403 | Vector3 returnVelocity = Vector3.Zero; | 2429 | Vector3 returnVelocity = Vector3.Zero; |
2404 | returnVelocity.X = (m_lastVelocity.X + _velocity.X)/2; | 2430 | returnVelocity.X = (m_lastVelocity.X + _velocity.X) * 0.5f; // 0.5f is mathematically equiv to '/ 2' |
2405 | returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y)/2; | 2431 | returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y) * 0.5f; |
2406 | returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z)/2; | 2432 | returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z) * 0.5f; |
2407 | return returnVelocity; | 2433 | return returnVelocity; |
2408 | } | 2434 | } |
2409 | set | 2435 | set |
@@ -2600,6 +2626,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
2600 | { | 2626 | { |
2601 | Vector3 pv = Vector3.Zero; | 2627 | Vector3 pv = Vector3.Zero; |
2602 | bool lastZeroFlag = _zeroFlag; | 2628 | bool lastZeroFlag = _zeroFlag; |
2629 | float m_minvelocity = 0; | ||
2603 | if (Body != (IntPtr)0) // FIXME -> or if it is a joint | 2630 | if (Body != (IntPtr)0) // FIXME -> or if it is a joint |
2604 | { | 2631 | { |
2605 | d.Vector3 vec = d.BodyGetPosition(Body); | 2632 | d.Vector3 vec = d.BodyGetPosition(Body); |
@@ -2752,8 +2779,21 @@ Console.WriteLine(" JointCreateFixed"); | |||
2752 | _acceleration = ((_velocity - m_lastVelocity) / 0.1f); | 2779 | _acceleration = ((_velocity - m_lastVelocity) / 0.1f); |
2753 | _acceleration = new Vector3(_velocity.X - m_lastVelocity.X / 0.1f, _velocity.Y - m_lastVelocity.Y / 0.1f, _velocity.Z - m_lastVelocity.Z / 0.1f); | 2780 | _acceleration = new Vector3(_velocity.X - m_lastVelocity.X / 0.1f, _velocity.Y - m_lastVelocity.Y / 0.1f, _velocity.Z - m_lastVelocity.Z / 0.1f); |
2754 | //m_log.Info("[PHYSICS]: V1: " + _velocity + " V2: " + m_lastVelocity + " Acceleration: " + _acceleration.ToString()); | 2781 | //m_log.Info("[PHYSICS]: V1: " + _velocity + " V2: " + m_lastVelocity + " Acceleration: " + _acceleration.ToString()); |
2782 | |||
2783 | // Note here that linearvelocity is affecting angular velocity... so I'm guessing this is a vehicle specific thing... | ||
2784 | // it does make sense to do this for tiny little instabilities with physical prim, however 0.5m/frame is fairly large. | ||
2785 | // reducing this to 0.02m/frame seems to help the angular rubberbanding quite a bit, however, to make sure it doesn't affect elevators and vehicles | ||
2786 | // adding these logical exclusion situations to maintain this where I think it was intended to be. | ||
2787 | if (m_throttleUpdates || m_usePID || (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) || (Amotor != IntPtr.Zero)) | ||
2788 | { | ||
2789 | m_minvelocity = 0.5f; | ||
2790 | } | ||
2791 | else | ||
2792 | { | ||
2793 | m_minvelocity = 0.02f; | ||
2794 | } | ||
2755 | 2795 | ||
2756 | if (_velocity.ApproxEquals(pv, 0.5f)) | 2796 | if (_velocity.ApproxEquals(pv, m_minvelocity)) |
2757 | { | 2797 | { |
2758 | m_rotationalVelocity = pv; | 2798 | m_rotationalVelocity = pv; |
2759 | } | 2799 | } |
@@ -3211,5 +3251,37 @@ Console.WriteLine(" JointCreateFixed"); | |||
3211 | { | 3251 | { |
3212 | m_material = pMaterial; | 3252 | m_material = pMaterial; |
3213 | } | 3253 | } |
3254 | |||
3255 | |||
3256 | private void CheckMeshAsset() | ||
3257 | { | ||
3258 | if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero) | ||
3259 | { | ||
3260 | m_assetFailed = true; | ||
3261 | Util.FireAndForget(delegate | ||
3262 | { | ||
3263 | RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod; | ||
3264 | if (assetProvider != null) | ||
3265 | assetProvider(_pbs.SculptTexture, MeshAssetReveived); | ||
3266 | }); | ||
3267 | } | ||
3268 | } | ||
3269 | |||
3270 | void MeshAssetReveived(AssetBase asset) | ||
3271 | { | ||
3272 | if (asset.Data != null && asset.Data.Length > 0) | ||
3273 | { | ||
3274 | if (!_pbs.SculptEntry) | ||
3275 | return; | ||
3276 | if (_pbs.SculptTexture.ToString() != asset.ID) | ||
3277 | return; | ||
3278 | |||
3279 | _pbs.SculptData = new byte[asset.Data.Length]; | ||
3280 | asset.Data.CopyTo(_pbs.SculptData, 0); | ||
3281 | m_assetFailed = false; | ||
3282 | m_taintshape = true; | ||
3283 | _parent_scene.AddPhysicsActorTaint(this); | ||
3284 | } | ||
3285 | } | ||
3214 | } | 3286 | } |
3215 | } \ No newline at end of file | 3287 | } \ No newline at end of file |
diff --git a/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs index 7e3ec63..8d7d3b3 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs | |||
@@ -137,15 +137,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
137 | ODERayCastRequest[] reqs = m_PendingRequests.ToArray(); | 137 | ODERayCastRequest[] reqs = m_PendingRequests.ToArray(); |
138 | for (int i = 0; i < reqs.Length; i++) | 138 | for (int i = 0; i < reqs.Length; i++) |
139 | { | 139 | { |
140 | try | 140 | if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast |
141 | { | 141 | RayCast(reqs[i]); // if there isn't anyone to send results |
142 | if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast | ||
143 | RayCast(reqs[i]); // if there isn't anyone to send results | ||
144 | } | ||
145 | catch | ||
146 | { | ||
147 | //Fail silently | ||
148 | } | ||
149 | } | 142 | } |
150 | 143 | ||
151 | m_PendingRequests.Clear(); | 144 | m_PendingRequests.Clear(); |
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index 929b019..7a50c4c 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs | |||
@@ -336,6 +336,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
336 | 336 | ||
337 | public int geomContactPointsStartthrottle = 3; | 337 | public int geomContactPointsStartthrottle = 3; |
338 | public int geomUpdatesPerThrottledUpdate = 15; | 338 | public int geomUpdatesPerThrottledUpdate = 15; |
339 | private const int avatarExpectedContacts = 3; | ||
339 | 340 | ||
340 | public float bodyPIDD = 35f; | 341 | public float bodyPIDD = 35f; |
341 | public float bodyPIDG = 25; | 342 | public float bodyPIDG = 25; |
@@ -474,6 +475,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
474 | private OdePrim cp1; | 475 | private OdePrim cp1; |
475 | private OdeCharacter cc2; | 476 | private OdeCharacter cc2; |
476 | private OdePrim cp2; | 477 | private OdePrim cp2; |
478 | private int p1ExpectedPoints = 0; | ||
479 | private int p2ExpectedPoints = 0; | ||
477 | //private int cStartStop = 0; | 480 | //private int cStartStop = 0; |
478 | //private string cDictKey = ""; | 481 | //private string cDictKey = ""; |
479 | 482 | ||
@@ -498,6 +501,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
498 | public int physics_logging_interval = 0; | 501 | public int physics_logging_interval = 0; |
499 | public bool physics_logging_append_existing_logfile = false; | 502 | public bool physics_logging_append_existing_logfile = false; |
500 | 503 | ||
504 | |||
501 | public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f); | 505 | public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f); |
502 | public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); | 506 | public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); |
503 | 507 | ||
@@ -644,7 +648,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
644 | 648 | ||
645 | contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80); | 649 | contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80); |
646 | 650 | ||
647 | geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 3); | 651 | geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 5); |
648 | geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15); | 652 | geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15); |
649 | geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5); | 653 | geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5); |
650 | 654 | ||
@@ -1064,7 +1068,10 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1064 | 1068 | ||
1065 | PhysicsActor p1; | 1069 | PhysicsActor p1; |
1066 | PhysicsActor p2; | 1070 | PhysicsActor p2; |
1067 | 1071 | ||
1072 | p1ExpectedPoints = 0; | ||
1073 | p2ExpectedPoints = 0; | ||
1074 | |||
1068 | if (!actor_name_map.TryGetValue(g1, out p1)) | 1075 | if (!actor_name_map.TryGetValue(g1, out p1)) |
1069 | { | 1076 | { |
1070 | p1 = PANull; | 1077 | p1 = PANull; |
@@ -1121,9 +1128,13 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1121 | switch (p1.PhysicsActorType) | 1128 | switch (p1.PhysicsActorType) |
1122 | { | 1129 | { |
1123 | case (int)ActorTypes.Agent: | 1130 | case (int)ActorTypes.Agent: |
1131 | p1ExpectedPoints = avatarExpectedContacts; | ||
1124 | p2.CollidingObj = true; | 1132 | p2.CollidingObj = true; |
1125 | break; | 1133 | break; |
1126 | case (int)ActorTypes.Prim: | 1134 | case (int)ActorTypes.Prim: |
1135 | if (p1 != null && p1 is OdePrim) | ||
1136 | p1ExpectedPoints = ((OdePrim) p1).ExpectedCollisionContacts; | ||
1137 | |||
1127 | if (p2.Velocity.LengthSquared() > 0.0f) | 1138 | if (p2.Velocity.LengthSquared() > 0.0f) |
1128 | p2.CollidingObj = true; | 1139 | p2.CollidingObj = true; |
1129 | break; | 1140 | break; |
@@ -1319,6 +1330,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1319 | if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && | 1330 | if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && |
1320 | (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) | 1331 | (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) |
1321 | { | 1332 | { |
1333 | p2ExpectedPoints = avatarExpectedContacts; | ||
1322 | // Avatar is moving on terrain, use the movement terrain contact | 1334 | // Avatar is moving on terrain, use the movement terrain contact |
1323 | AvatarMovementTerrainContact.geom = curContact; | 1335 | AvatarMovementTerrainContact.geom = curContact; |
1324 | 1336 | ||
@@ -1332,6 +1344,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1332 | { | 1344 | { |
1333 | if (p2.PhysicsActorType == (int)ActorTypes.Agent) | 1345 | if (p2.PhysicsActorType == (int)ActorTypes.Agent) |
1334 | { | 1346 | { |
1347 | p2ExpectedPoints = avatarExpectedContacts; | ||
1335 | // Avatar is standing on terrain, use the non moving terrain contact | 1348 | // Avatar is standing on terrain, use the non moving terrain contact |
1336 | TerrainContact.geom = curContact; | 1349 | TerrainContact.geom = curContact; |
1337 | 1350 | ||
@@ -1356,9 +1369,18 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1356 | } | 1369 | } |
1357 | 1370 | ||
1358 | if (p2 is OdePrim) | 1371 | if (p2 is OdePrim) |
1359 | material = ((OdePrim)p2).m_material; | 1372 | { |
1360 | 1373 | material = ((OdePrim) p2).m_material; | |
1374 | p2ExpectedPoints = ((OdePrim)p2).ExpectedCollisionContacts; | ||
1375 | } | ||
1376 | |||
1377 | // Unnessesary because p1 is defined above | ||
1378 | //if (p1 is OdePrim) | ||
1379 | // { | ||
1380 | // p1ExpectedPoints = ((OdePrim)p1).ExpectedCollisionContacts; | ||
1381 | // } | ||
1361 | //m_log.DebugFormat("Material: {0}", material); | 1382 | //m_log.DebugFormat("Material: {0}", material); |
1383 | |||
1362 | m_materialContacts[material, movintYN].geom = curContact; | 1384 | m_materialContacts[material, movintYN].geom = curContact; |
1363 | 1385 | ||
1364 | if (m_global_contactcount < maxContactsbeforedeath) | 1386 | if (m_global_contactcount < maxContactsbeforedeath) |
@@ -1379,7 +1401,10 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1379 | int material = (int)Material.Wood; | 1401 | int material = (int)Material.Wood; |
1380 | 1402 | ||
1381 | if (p2 is OdePrim) | 1403 | if (p2 is OdePrim) |
1404 | { | ||
1382 | material = ((OdePrim)p2).m_material; | 1405 | material = ((OdePrim)p2).m_material; |
1406 | p2ExpectedPoints = ((OdePrim)p2).ExpectedCollisionContacts; | ||
1407 | } | ||
1383 | 1408 | ||
1384 | //m_log.DebugFormat("Material: {0}", material); | 1409 | //m_log.DebugFormat("Material: {0}", material); |
1385 | m_materialContacts[material, movintYN].geom = curContact; | 1410 | m_materialContacts[material, movintYN].geom = curContact; |
@@ -1429,6 +1454,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1429 | { | 1454 | { |
1430 | if ((p2.PhysicsActorType == (int)ActorTypes.Agent)) | 1455 | if ((p2.PhysicsActorType == (int)ActorTypes.Agent)) |
1431 | { | 1456 | { |
1457 | p2ExpectedPoints = avatarExpectedContacts; | ||
1432 | if ((Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) | 1458 | if ((Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) |
1433 | { | 1459 | { |
1434 | // Avatar is moving on a prim, use the Movement prim contact | 1460 | // Avatar is moving on a prim, use the Movement prim contact |
@@ -1458,7 +1484,10 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1458 | int material = (int)Material.Wood; | 1484 | int material = (int)Material.Wood; |
1459 | 1485 | ||
1460 | if (p2 is OdePrim) | 1486 | if (p2 is OdePrim) |
1487 | { | ||
1461 | material = ((OdePrim)p2).m_material; | 1488 | material = ((OdePrim)p2).m_material; |
1489 | p2ExpectedPoints = ((OdePrim)p2).ExpectedCollisionContacts; | ||
1490 | } | ||
1462 | 1491 | ||
1463 | //m_log.DebugFormat("Material: {0}", material); | 1492 | //m_log.DebugFormat("Material: {0}", material); |
1464 | m_materialContacts[material, 0].geom = curContact; | 1493 | m_materialContacts[material, 0].geom = curContact; |
@@ -1479,8 +1508,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1479 | } | 1508 | } |
1480 | 1509 | ||
1481 | collision_accounting_events(p1, p2, maxDepthContact); | 1510 | collision_accounting_events(p1, p2, maxDepthContact); |
1482 | 1511 | ||
1483 | if (count > geomContactPointsStartthrottle) | 1512 | if (count > ((p1ExpectedPoints + p2ExpectedPoints) * 0.25) + (geomContactPointsStartthrottle)) |
1484 | { | 1513 | { |
1485 | // If there are more then 3 contact points, it's likely | 1514 | // If there are more then 3 contact points, it's likely |
1486 | // that we've got a pile of objects, so ... | 1515 | // that we've got a pile of objects, so ... |
diff --git a/OpenSim/Region/Physics/UbitMeshing/Mesh.cs b/OpenSim/Region/Physics/UbitMeshing/Mesh.cs index 98c0f0b..1e9b8bc 100644 --- a/OpenSim/Region/Physics/UbitMeshing/Mesh.cs +++ b/OpenSim/Region/Physics/UbitMeshing/Mesh.cs | |||
@@ -32,24 +32,49 @@ using System.Runtime.InteropServices; | |||
32 | using OpenSim.Region.Physics.Manager; | 32 | using OpenSim.Region.Physics.Manager; |
33 | using PrimMesher; | 33 | using PrimMesher; |
34 | using OpenMetaverse; | 34 | using OpenMetaverse; |
35 | using System.Runtime.Serialization; | ||
36 | using System.Runtime.Serialization.Formatters.Binary; | ||
35 | 37 | ||
36 | namespace OpenSim.Region.Physics.Meshing | 38 | namespace OpenSim.Region.Physics.Meshing |
37 | { | 39 | { |
38 | public class Mesh : IMesh | 40 | public class MeshBuildingData |
39 | { | 41 | { |
42 | public Dictionary<Vertex, int> m_vertices; | ||
43 | public List<Triangle> m_triangles; | ||
44 | public float m_obbXmin; | ||
45 | public float m_obbXmax; | ||
46 | public float m_obbYmin; | ||
47 | public float m_obbYmax; | ||
48 | public float m_obbZmin; | ||
49 | public float m_obbZmax; | ||
50 | public Vector3 m_centroid; | ||
51 | public int m_centroidDiv; | ||
52 | } | ||
40 | 53 | ||
41 | private Dictionary<Vertex, int> m_vertices; | 54 | [Serializable()] |
42 | private List<Triangle> m_triangles; | 55 | public class Mesh : IMesh |
43 | GCHandle m_pinnedVertexes; | 56 | { |
44 | GCHandle m_pinnedIndex; | 57 | float[] vertices; |
58 | int[] indexes; | ||
59 | Vector3 m_obb; | ||
60 | Vector3 m_obboffset; | ||
61 | [NonSerialized()] | ||
62 | MeshBuildingData m_bdata; | ||
63 | [NonSerialized()] | ||
64 | GCHandle vhandler; | ||
65 | [NonSerialized()] | ||
66 | GCHandle ihandler; | ||
67 | [NonSerialized()] | ||
45 | IntPtr m_verticesPtr = IntPtr.Zero; | 68 | IntPtr m_verticesPtr = IntPtr.Zero; |
46 | int m_vertexCount = 0; | 69 | [NonSerialized()] |
47 | IntPtr m_indicesPtr = IntPtr.Zero; | 70 | IntPtr m_indicesPtr = IntPtr.Zero; |
71 | [NonSerialized()] | ||
72 | int m_vertexCount = 0; | ||
73 | [NonSerialized()] | ||
48 | int m_indexCount = 0; | 74 | int m_indexCount = 0; |
49 | public float[] m_normals; | ||
50 | Vector3 m_centroid; | ||
51 | int m_centroidDiv; | ||
52 | 75 | ||
76 | public int RefCount { get; set; } | ||
77 | public AMeshKey Key { get; set; } | ||
53 | 78 | ||
54 | private class vertexcomp : IEqualityComparer<Vertex> | 79 | private class vertexcomp : IEqualityComparer<Vertex> |
55 | { | 80 | { |
@@ -73,43 +98,119 @@ namespace OpenSim.Region.Physics.Meshing | |||
73 | { | 98 | { |
74 | vertexcomp vcomp = new vertexcomp(); | 99 | vertexcomp vcomp = new vertexcomp(); |
75 | 100 | ||
76 | m_vertices = new Dictionary<Vertex, int>(vcomp); | 101 | m_bdata = new MeshBuildingData(); |
77 | m_triangles = new List<Triangle>(); | 102 | m_bdata.m_vertices = new Dictionary<Vertex, int>(vcomp); |
78 | m_centroid = Vector3.Zero; | 103 | m_bdata.m_triangles = new List<Triangle>(); |
79 | m_centroidDiv = 0; | 104 | m_bdata.m_centroid = Vector3.Zero; |
105 | m_bdata.m_centroidDiv = 0; | ||
106 | m_bdata.m_obbXmin = float.MaxValue; | ||
107 | m_bdata.m_obbXmax = float.MinValue; | ||
108 | m_bdata.m_obbYmin = float.MaxValue; | ||
109 | m_bdata.m_obbYmax = float.MinValue; | ||
110 | m_bdata.m_obbZmin = float.MaxValue; | ||
111 | m_bdata.m_obbZmax = float.MinValue; | ||
112 | m_obb = new Vector3(0.5f, 0.5f, 0.5f); | ||
113 | m_obboffset = Vector3.Zero; | ||
80 | } | 114 | } |
81 | 115 | ||
82 | public int RefCount { get; set; } | ||
83 | |||
84 | public AMeshKey Key { get; set; } | ||
85 | 116 | ||
86 | public void Scale(Vector3 scale) | 117 | public Mesh Scale(Vector3 scale) |
87 | { | 118 | { |
119 | if (m_verticesPtr == null || m_indicesPtr == null) | ||
120 | return null; | ||
121 | |||
122 | Mesh result = new Mesh(); | ||
123 | |||
124 | float x = scale.X; | ||
125 | float y = scale.Y; | ||
126 | float z = scale.Z; | ||
127 | |||
128 | result.m_obb.X = m_obb.X * x; | ||
129 | result.m_obb.Y = m_obb.Y * y; | ||
130 | result.m_obb.Z = m_obb.Z * z; | ||
131 | result.m_obboffset.X = m_obboffset.X * x; | ||
132 | result.m_obboffset.Y = m_obboffset.Y * y; | ||
133 | result.m_obboffset.Z = m_obboffset.Z * z; | ||
88 | 134 | ||
135 | result.vertices = new float[vertices.Length]; | ||
136 | int j = 0; | ||
137 | for (int i = 0; i < m_vertexCount; i++) | ||
138 | { | ||
139 | result.vertices[j] = vertices[j] * x; | ||
140 | j++; | ||
141 | result.vertices[j] = vertices[j] * y; | ||
142 | j++; | ||
143 | result.vertices[j] = vertices[j] * z; | ||
144 | j++; | ||
145 | } | ||
146 | |||
147 | result.indexes = new int[indexes.Length]; | ||
148 | indexes.CopyTo(result.indexes,0); | ||
149 | |||
150 | result.pinMemory(); | ||
89 | 151 | ||
152 | return result; | ||
90 | } | 153 | } |
91 | 154 | ||
92 | public Mesh Clone() | 155 | public Mesh Clone() |
93 | { | 156 | { |
94 | Mesh result = new Mesh(); | 157 | Mesh result = new Mesh(); |
95 | 158 | ||
96 | foreach (Triangle t in m_triangles) | 159 | if (m_bdata != null) |
97 | { | 160 | { |
98 | result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone())); | 161 | result.m_bdata = new MeshBuildingData(); |
162 | foreach (Triangle t in m_bdata.m_triangles) | ||
163 | { | ||
164 | result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone())); | ||
165 | } | ||
166 | result.m_bdata.m_centroid = m_bdata.m_centroid; | ||
167 | result.m_bdata.m_centroidDiv = m_bdata.m_centroidDiv; | ||
168 | result.m_bdata.m_obbXmin = m_bdata.m_obbXmin; | ||
169 | result.m_bdata.m_obbXmax = m_bdata.m_obbXmax; | ||
170 | result.m_bdata.m_obbYmin = m_bdata.m_obbYmin; | ||
171 | result.m_bdata.m_obbYmax = m_bdata.m_obbYmax; | ||
172 | result.m_bdata.m_obbZmin = m_bdata.m_obbZmin; | ||
173 | result.m_bdata.m_obbZmax = m_bdata.m_obbZmax; | ||
99 | } | 174 | } |
100 | result.m_centroid = m_centroid; | 175 | result.m_obb = m_obb; |
101 | result.m_centroidDiv = m_centroidDiv; | 176 | result.m_obboffset = m_obboffset; |
102 | return result; | 177 | return result; |
103 | } | 178 | } |
104 | 179 | ||
180 | public void addVertexLStats(Vertex v) | ||
181 | { | ||
182 | float x = v.X; | ||
183 | float y = v.Y; | ||
184 | float z = v.Z; | ||
185 | |||
186 | m_bdata.m_centroid.X += x; | ||
187 | m_bdata.m_centroid.Y += y; | ||
188 | m_bdata.m_centroid.Z += z; | ||
189 | m_bdata.m_centroidDiv++; | ||
190 | |||
191 | if (x > m_bdata.m_obbXmax) | ||
192 | m_bdata.m_obbXmax = x; | ||
193 | else if (x < m_bdata.m_obbXmin) | ||
194 | m_bdata.m_obbXmin = x; | ||
195 | |||
196 | if (y > m_bdata.m_obbYmax) | ||
197 | m_bdata.m_obbYmax = y; | ||
198 | else if (y < m_bdata.m_obbYmin) | ||
199 | m_bdata.m_obbYmin = y; | ||
200 | |||
201 | if (z > m_bdata.m_obbZmax) | ||
202 | m_bdata.m_obbZmax = z; | ||
203 | else if (z < m_bdata.m_obbZmin) | ||
204 | m_bdata.m_obbZmin = z; | ||
205 | |||
206 | } | ||
207 | |||
208 | |||
105 | public void Add(Triangle triangle) | 209 | public void Add(Triangle triangle) |
106 | { | 210 | { |
107 | if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero) | 211 | if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero) |
108 | throw new NotSupportedException("Attempt to Add to a pinned Mesh"); | 212 | throw new NotSupportedException("Attempt to Add to a pinned Mesh"); |
109 | // If a vertex of the triangle is not yet in the vertices list, | 213 | |
110 | // add it and set its index to the current index count | ||
111 | // vertex == seems broken | ||
112 | // skip colapsed triangles | ||
113 | if ((triangle.v1.X == triangle.v2.X && triangle.v1.Y == triangle.v2.Y && triangle.v1.Z == triangle.v2.Z) | 214 | if ((triangle.v1.X == triangle.v2.X && triangle.v1.Y == triangle.v2.Y && triangle.v1.Z == triangle.v2.Z) |
114 | || (triangle.v1.X == triangle.v3.X && triangle.v1.Y == triangle.v3.Y && triangle.v1.Z == triangle.v3.Z) | 215 | || (triangle.v1.X == triangle.v3.X && triangle.v1.Y == triangle.v3.Y && triangle.v1.Z == triangle.v3.Z) |
115 | || (triangle.v2.X == triangle.v3.X && triangle.v2.Y == triangle.v3.Y && triangle.v2.Z == triangle.v3.Z) | 216 | || (triangle.v2.X == triangle.v3.X && triangle.v2.Y == triangle.v3.Y && triangle.v2.Z == triangle.v3.Z) |
@@ -118,113 +219,59 @@ namespace OpenSim.Region.Physics.Meshing | |||
118 | return; | 219 | return; |
119 | } | 220 | } |
120 | 221 | ||
121 | if (m_vertices.Count == 0) | 222 | if (m_bdata.m_vertices.Count == 0) |
122 | { | 223 | { |
123 | m_centroidDiv = 0; | 224 | m_bdata.m_centroidDiv = 0; |
124 | m_centroid = Vector3.Zero; | 225 | m_bdata.m_centroid = Vector3.Zero; |
125 | } | 226 | } |
126 | 227 | ||
127 | if (!m_vertices.ContainsKey(triangle.v1)) | 228 | if (!m_bdata.m_vertices.ContainsKey(triangle.v1)) |
128 | { | 229 | { |
129 | m_vertices[triangle.v1] = m_vertices.Count; | 230 | m_bdata.m_vertices[triangle.v1] = m_bdata.m_vertices.Count; |
130 | m_centroid.X += triangle.v1.X; | 231 | addVertexLStats(triangle.v1); |
131 | m_centroid.Y += triangle.v1.Y; | ||
132 | m_centroid.Z += triangle.v1.Z; | ||
133 | m_centroidDiv++; | ||
134 | } | 232 | } |
135 | if (!m_vertices.ContainsKey(triangle.v2)) | 233 | if (!m_bdata.m_vertices.ContainsKey(triangle.v2)) |
136 | { | 234 | { |
137 | m_vertices[triangle.v2] = m_vertices.Count; | 235 | m_bdata.m_vertices[triangle.v2] = m_bdata.m_vertices.Count; |
138 | m_centroid.X += triangle.v2.X; | 236 | addVertexLStats(triangle.v2); |
139 | m_centroid.Y += triangle.v2.Y; | ||
140 | m_centroid.Z += triangle.v2.Z; | ||
141 | m_centroidDiv++; | ||
142 | } | 237 | } |
143 | if (!m_vertices.ContainsKey(triangle.v3)) | 238 | if (!m_bdata.m_vertices.ContainsKey(triangle.v3)) |
144 | { | 239 | { |
145 | m_vertices[triangle.v3] = m_vertices.Count; | 240 | m_bdata.m_vertices[triangle.v3] = m_bdata.m_vertices.Count; |
146 | m_centroid.X += triangle.v3.X; | 241 | addVertexLStats(triangle.v3); |
147 | m_centroid.Y += triangle.v3.Y; | ||
148 | m_centroid.Z += triangle.v3.Z; | ||
149 | m_centroidDiv++; | ||
150 | } | 242 | } |
151 | m_triangles.Add(triangle); | 243 | m_bdata.m_triangles.Add(triangle); |
152 | } | 244 | } |
153 | 245 | ||
154 | public Vector3 GetCentroid() | 246 | public Vector3 GetCentroid() |
155 | { | 247 | { |
156 | if (m_centroidDiv > 0) | 248 | return m_obboffset; |
157 | return new Vector3(m_centroid.X / m_centroidDiv, m_centroid.Y / m_centroidDiv, m_centroid.Z / m_centroidDiv); | 249 | |
158 | else | ||
159 | return Vector3.Zero; | ||
160 | } | 250 | } |
161 | 251 | ||
162 | public void CalcNormals() | 252 | public Vector3 GetOBB() |
163 | { | 253 | { |
164 | int iTriangles = m_triangles.Count; | 254 | return m_obb; |
165 | 255 | float x, y, z; | |
166 | this.m_normals = new float[iTriangles * 3]; | 256 | if (m_bdata.m_centroidDiv > 0) |
167 | |||
168 | int i = 0; | ||
169 | foreach (Triangle t in m_triangles) | ||
170 | { | 257 | { |
171 | float ux, uy, uz; | 258 | x = (m_bdata.m_obbXmax - m_bdata.m_obbXmin) * 0.5f; |
172 | float vx, vy, vz; | 259 | y = (m_bdata.m_obbYmax - m_bdata.m_obbYmin) * 0.5f; |
173 | float wx, wy, wz; | 260 | z = (m_bdata.m_obbZmax - m_bdata.m_obbZmin) * 0.5f; |
174 | 261 | } | |
175 | ux = t.v1.X; | 262 | else // ?? |
176 | uy = t.v1.Y; | 263 | { |
177 | uz = t.v1.Z; | 264 | x = 0.5f; |
178 | 265 | y = 0.5f; | |
179 | vx = t.v2.X; | 266 | z = 0.5f; |
180 | vy = t.v2.Y; | ||
181 | vz = t.v2.Z; | ||
182 | |||
183 | wx = t.v3.X; | ||
184 | wy = t.v3.Y; | ||
185 | wz = t.v3.Z; | ||
186 | |||
187 | |||
188 | // Vectors for edges | ||
189 | float e1x, e1y, e1z; | ||
190 | float e2x, e2y, e2z; | ||
191 | |||
192 | e1x = ux - vx; | ||
193 | e1y = uy - vy; | ||
194 | e1z = uz - vz; | ||
195 | |||
196 | e2x = ux - wx; | ||
197 | e2y = uy - wy; | ||
198 | e2z = uz - wz; | ||
199 | |||
200 | |||
201 | // Cross product for normal | ||
202 | float nx, ny, nz; | ||
203 | nx = e1y * e2z - e1z * e2y; | ||
204 | ny = e1z * e2x - e1x * e2z; | ||
205 | nz = e1x * e2y - e1y * e2x; | ||
206 | |||
207 | // Length | ||
208 | float l = (float)Math.Sqrt(nx * nx + ny * ny + nz * nz); | ||
209 | float lReciprocal = 1.0f / l; | ||
210 | |||
211 | // Normalized "normal" | ||
212 | //nx /= l; | ||
213 | //ny /= l; | ||
214 | //nz /= l; | ||
215 | |||
216 | m_normals[i] = nx * lReciprocal; | ||
217 | m_normals[i + 1] = ny * lReciprocal; | ||
218 | m_normals[i + 2] = nz * lReciprocal; | ||
219 | |||
220 | i += 3; | ||
221 | } | 267 | } |
268 | return new Vector3(x, y, z); | ||
222 | } | 269 | } |
223 | 270 | ||
224 | public List<Vector3> getVertexList() | 271 | public List<Vector3> getVertexList() |
225 | { | 272 | { |
226 | List<Vector3> result = new List<Vector3>(); | 273 | List<Vector3> result = new List<Vector3>(); |
227 | foreach (Vertex v in m_vertices.Keys) | 274 | foreach (Vertex v in m_bdata.m_vertices.Keys) |
228 | { | 275 | { |
229 | result.Add(new Vector3(v.X, v.Y, v.Z)); | 276 | result.Add(new Vector3(v.X, v.Y, v.Z)); |
230 | } | 277 | } |
@@ -233,10 +280,10 @@ namespace OpenSim.Region.Physics.Meshing | |||
233 | 280 | ||
234 | private float[] getVertexListAsFloat() | 281 | private float[] getVertexListAsFloat() |
235 | { | 282 | { |
236 | if (m_vertices == null) | 283 | if (m_bdata.m_vertices == null) |
237 | throw new NotSupportedException(); | 284 | throw new NotSupportedException(); |
238 | float[] result = new float[m_vertices.Count * 3]; | 285 | float[] result = new float[m_bdata.m_vertices.Count * 3]; |
239 | foreach (KeyValuePair<Vertex, int> kvp in m_vertices) | 286 | foreach (KeyValuePair<Vertex, int> kvp in m_bdata.m_vertices) |
240 | { | 287 | { |
241 | Vertex v = kvp.Key; | 288 | Vertex v = kvp.Key; |
242 | int i = kvp.Value; | 289 | int i = kvp.Value; |
@@ -249,48 +296,39 @@ namespace OpenSim.Region.Physics.Meshing | |||
249 | 296 | ||
250 | public float[] getVertexListAsFloatLocked() | 297 | public float[] getVertexListAsFloatLocked() |
251 | { | 298 | { |
252 | if (m_pinnedVertexes.IsAllocated) | 299 | return null; |
253 | return (float[])(m_pinnedVertexes.Target); | ||
254 | |||
255 | float[] result = getVertexListAsFloat(); | ||
256 | m_pinnedVertexes = GCHandle.Alloc(result, GCHandleType.Pinned); | ||
257 | // Inform the garbage collector of this unmanaged allocation so it can schedule | ||
258 | // the next GC round more intelligently | ||
259 | GC.AddMemoryPressure(Buffer.ByteLength(result)); | ||
260 | |||
261 | return result; | ||
262 | } | 300 | } |
263 | 301 | ||
264 | public void getVertexListAsPtrToFloatArray(out IntPtr vertices, out int vertexStride, out int vertexCount) | 302 | public void getVertexListAsPtrToFloatArray(out IntPtr _vertices, out int vertexStride, out int vertexCount) |
265 | { | 303 | { |
266 | // A vertex is 3 floats | 304 | // A vertex is 3 floats |
267 | vertexStride = 3 * sizeof(float); | 305 | vertexStride = 3 * sizeof(float); |
268 | 306 | ||
269 | // If there isn't an unmanaged array allocated yet, do it now | 307 | // If there isn't an unmanaged array allocated yet, do it now |
270 | if (m_verticesPtr == IntPtr.Zero) | 308 | if (m_verticesPtr == IntPtr.Zero && m_bdata != null) |
271 | { | 309 | { |
272 | float[] vertexList = getVertexListAsFloat(); | 310 | vertices = getVertexListAsFloat(); |
273 | // Each vertex is 3 elements (floats) | 311 | // Each vertex is 3 elements (floats) |
274 | m_vertexCount = vertexList.Length / 3; | 312 | m_vertexCount = vertices.Length / 3; |
275 | int byteCount = m_vertexCount * vertexStride; | 313 | vhandler = GCHandle.Alloc(vertices, GCHandleType.Pinned); |
276 | m_verticesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount); | 314 | m_verticesPtr = vhandler.AddrOfPinnedObject(); |
277 | System.Runtime.InteropServices.Marshal.Copy(vertexList, 0, m_verticesPtr, m_vertexCount * 3); | 315 | GC.AddMemoryPressure(Buffer.ByteLength(vertices)); |
278 | } | 316 | } |
279 | vertices = m_verticesPtr; | 317 | _vertices = m_verticesPtr; |
280 | vertexCount = m_vertexCount; | 318 | vertexCount = m_vertexCount; |
281 | } | 319 | } |
282 | 320 | ||
283 | public int[] getIndexListAsInt() | 321 | public int[] getIndexListAsInt() |
284 | { | 322 | { |
285 | if (m_triangles == null) | 323 | if (m_bdata.m_triangles == null) |
286 | throw new NotSupportedException(); | 324 | throw new NotSupportedException(); |
287 | int[] result = new int[m_triangles.Count * 3]; | 325 | int[] result = new int[m_bdata.m_triangles.Count * 3]; |
288 | for (int i = 0; i < m_triangles.Count; i++) | 326 | for (int i = 0; i < m_bdata.m_triangles.Count; i++) |
289 | { | 327 | { |
290 | Triangle t = m_triangles[i]; | 328 | Triangle t = m_bdata.m_triangles[i]; |
291 | result[3 * i + 0] = m_vertices[t.v1]; | 329 | result[3 * i + 0] = m_bdata.m_vertices[t.v1]; |
292 | result[3 * i + 1] = m_vertices[t.v2]; | 330 | result[3 * i + 1] = m_bdata.m_vertices[t.v2]; |
293 | result[3 * i + 2] = m_vertices[t.v3]; | 331 | result[3 * i + 2] = m_bdata.m_vertices[t.v3]; |
294 | } | 332 | } |
295 | return result; | 333 | return result; |
296 | } | 334 | } |
@@ -301,28 +339,19 @@ namespace OpenSim.Region.Physics.Meshing | |||
301 | /// <returns></returns> | 339 | /// <returns></returns> |
302 | public int[] getIndexListAsIntLocked() | 340 | public int[] getIndexListAsIntLocked() |
303 | { | 341 | { |
304 | if (m_pinnedIndex.IsAllocated) | 342 | return null; |
305 | return (int[])(m_pinnedIndex.Target); | ||
306 | |||
307 | int[] result = getIndexListAsInt(); | ||
308 | m_pinnedIndex = GCHandle.Alloc(result, GCHandleType.Pinned); | ||
309 | // Inform the garbage collector of this unmanaged allocation so it can schedule | ||
310 | // the next GC round more intelligently | ||
311 | GC.AddMemoryPressure(Buffer.ByteLength(result)); | ||
312 | |||
313 | return result; | ||
314 | } | 343 | } |
315 | 344 | ||
316 | public void getIndexListAsPtrToIntArray(out IntPtr indices, out int triStride, out int indexCount) | 345 | public void getIndexListAsPtrToIntArray(out IntPtr indices, out int triStride, out int indexCount) |
317 | { | 346 | { |
318 | // If there isn't an unmanaged array allocated yet, do it now | 347 | // If there isn't an unmanaged array allocated yet, do it now |
319 | if (m_indicesPtr == IntPtr.Zero) | 348 | if (m_indicesPtr == IntPtr.Zero && m_bdata != null) |
320 | { | 349 | { |
321 | int[] indexList = getIndexListAsInt(); | 350 | indexes = getIndexListAsInt(); |
322 | m_indexCount = indexList.Length; | 351 | m_indexCount = indexes.Length; |
323 | int byteCount = m_indexCount * sizeof(int); | 352 | ihandler = GCHandle.Alloc(indexes, GCHandleType.Pinned); |
324 | m_indicesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount); | 353 | m_indicesPtr = ihandler.AddrOfPinnedObject(); |
325 | System.Runtime.InteropServices.Marshal.Copy(indexList, 0, m_indicesPtr, m_indexCount); | 354 | GC.AddMemoryPressure(Buffer.ByteLength(indexes)); |
326 | } | 355 | } |
327 | // A triangle is 3 ints (indices) | 356 | // A triangle is 3 ints (indices) |
328 | triStride = 3 * sizeof(int); | 357 | triStride = 3 * sizeof(int); |
@@ -332,18 +361,16 @@ namespace OpenSim.Region.Physics.Meshing | |||
332 | 361 | ||
333 | public void releasePinned() | 362 | public void releasePinned() |
334 | { | 363 | { |
335 | if (m_pinnedVertexes.IsAllocated) | ||
336 | m_pinnedVertexes.Free(); | ||
337 | if (m_pinnedIndex.IsAllocated) | ||
338 | m_pinnedIndex.Free(); | ||
339 | if (m_verticesPtr != IntPtr.Zero) | 364 | if (m_verticesPtr != IntPtr.Zero) |
340 | { | 365 | { |
341 | System.Runtime.InteropServices.Marshal.FreeHGlobal(m_verticesPtr); | 366 | vhandler.Free(); |
367 | vertices = null; | ||
342 | m_verticesPtr = IntPtr.Zero; | 368 | m_verticesPtr = IntPtr.Zero; |
343 | } | 369 | } |
344 | if (m_indicesPtr != IntPtr.Zero) | 370 | if (m_indicesPtr != IntPtr.Zero) |
345 | { | 371 | { |
346 | System.Runtime.InteropServices.Marshal.FreeHGlobal(m_indicesPtr); | 372 | ihandler.Free(); |
373 | indexes = null; | ||
347 | m_indicesPtr = IntPtr.Zero; | 374 | m_indicesPtr = IntPtr.Zero; |
348 | } | 375 | } |
349 | } | 376 | } |
@@ -353,29 +380,42 @@ namespace OpenSim.Region.Physics.Meshing | |||
353 | /// </summary> | 380 | /// </summary> |
354 | public void releaseSourceMeshData() | 381 | public void releaseSourceMeshData() |
355 | { | 382 | { |
356 | m_triangles = null; | 383 | if (m_bdata != null) |
357 | m_vertices = null; | 384 | { |
385 | m_bdata.m_triangles = null; | ||
386 | m_bdata.m_vertices = null; | ||
387 | } | ||
388 | } | ||
389 | |||
390 | public void releaseBuildingMeshData() | ||
391 | { | ||
392 | if (m_bdata != null) | ||
393 | { | ||
394 | m_bdata.m_triangles = null; | ||
395 | m_bdata.m_vertices = null; | ||
396 | m_bdata = null; | ||
397 | } | ||
358 | } | 398 | } |
359 | 399 | ||
360 | public void Append(IMesh newMesh) | 400 | public void Append(IMesh newMesh) |
361 | { | 401 | { |
362 | if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero) | 402 | if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero) |
363 | throw new NotSupportedException("Attempt to Append to a pinned Mesh"); | 403 | throw new NotSupportedException("Attempt to Append to a pinned Mesh"); |
364 | 404 | ||
365 | if (!(newMesh is Mesh)) | 405 | if (!(newMesh is Mesh)) |
366 | return; | 406 | return; |
367 | 407 | ||
368 | foreach (Triangle t in ((Mesh)newMesh).m_triangles) | 408 | foreach (Triangle t in ((Mesh)newMesh).m_bdata.m_triangles) |
369 | Add(t); | 409 | Add(t); |
370 | } | 410 | } |
371 | 411 | ||
372 | // Do a linear transformation of mesh. | 412 | // Do a linear transformation of mesh. |
373 | public void TransformLinear(float[,] matrix, float[] offset) | 413 | public void TransformLinear(float[,] matrix, float[] offset) |
374 | { | 414 | { |
375 | if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero) | 415 | if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero) |
376 | throw new NotSupportedException("Attempt to TransformLinear a pinned Mesh"); | 416 | throw new NotSupportedException("Attempt to TransformLinear a pinned Mesh"); |
377 | 417 | ||
378 | foreach (Vertex v in m_vertices.Keys) | 418 | foreach (Vertex v in m_bdata.m_vertices.Keys) |
379 | { | 419 | { |
380 | if (v == null) | 420 | if (v == null) |
381 | continue; | 421 | continue; |
@@ -393,10 +433,12 @@ namespace OpenSim.Region.Physics.Meshing | |||
393 | { | 433 | { |
394 | if (path == null) | 434 | if (path == null) |
395 | return; | 435 | return; |
436 | if (m_bdata == null) | ||
437 | return; | ||
396 | String fileName = name + "_" + title + ".raw"; | 438 | String fileName = name + "_" + title + ".raw"; |
397 | String completePath = System.IO.Path.Combine(path, fileName); | 439 | String completePath = System.IO.Path.Combine(path, fileName); |
398 | StreamWriter sw = new StreamWriter(completePath); | 440 | StreamWriter sw = new StreamWriter(completePath); |
399 | foreach (Triangle t in m_triangles) | 441 | foreach (Triangle t in m_bdata.m_triangles) |
400 | { | 442 | { |
401 | String s = t.ToStringRaw(); | 443 | String s = t.ToStringRaw(); |
402 | sw.WriteLine(s); | 444 | sw.WriteLine(s); |
@@ -406,7 +448,144 @@ namespace OpenSim.Region.Physics.Meshing | |||
406 | 448 | ||
407 | public void TrimExcess() | 449 | public void TrimExcess() |
408 | { | 450 | { |
409 | m_triangles.TrimExcess(); | 451 | m_bdata.m_triangles.TrimExcess(); |
452 | } | ||
453 | |||
454 | public void pinMemory() | ||
455 | { | ||
456 | m_vertexCount = vertices.Length / 3; | ||
457 | vhandler = GCHandle.Alloc(vertices, GCHandleType.Pinned); | ||
458 | m_verticesPtr = vhandler.AddrOfPinnedObject(); | ||
459 | GC.AddMemoryPressure(Buffer.ByteLength(vertices)); | ||
460 | |||
461 | m_indexCount = indexes.Length; | ||
462 | ihandler = GCHandle.Alloc(indexes, GCHandleType.Pinned); | ||
463 | m_indicesPtr = ihandler.AddrOfPinnedObject(); | ||
464 | GC.AddMemoryPressure(Buffer.ByteLength(indexes)); | ||
465 | } | ||
466 | |||
467 | public void PrepForOde() | ||
468 | { | ||
469 | // If there isn't an unmanaged array allocated yet, do it now | ||
470 | if (m_verticesPtr == IntPtr.Zero) | ||
471 | vertices = getVertexListAsFloat(); | ||
472 | |||
473 | // If there isn't an unmanaged array allocated yet, do it now | ||
474 | if (m_indicesPtr == IntPtr.Zero) | ||
475 | indexes = getIndexListAsInt(); | ||
476 | |||
477 | pinMemory(); | ||
478 | |||
479 | float x, y, z; | ||
480 | |||
481 | if (m_bdata.m_centroidDiv > 0) | ||
482 | { | ||
483 | m_obboffset = new Vector3(m_bdata.m_centroid.X / m_bdata.m_centroidDiv, m_bdata.m_centroid.Y / m_bdata.m_centroidDiv, m_bdata.m_centroid.Z / m_bdata.m_centroidDiv); | ||
484 | x = (m_bdata.m_obbXmax - m_bdata.m_obbXmin) * 0.5f; | ||
485 | y = (m_bdata.m_obbYmax - m_bdata.m_obbYmin) * 0.5f; | ||
486 | z = (m_bdata.m_obbZmax - m_bdata.m_obbZmin) * 0.5f; | ||
487 | } | ||
488 | |||
489 | else | ||
490 | { | ||
491 | m_obboffset = Vector3.Zero; | ||
492 | x = 0.5f; | ||
493 | y = 0.5f; | ||
494 | z = 0.5f; | ||
495 | } | ||
496 | m_obb = new Vector3(x, y, z); | ||
497 | |||
498 | releaseBuildingMeshData(); | ||
499 | } | ||
500 | public bool ToStream(Stream st) | ||
501 | { | ||
502 | if (m_indicesPtr == IntPtr.Zero || m_verticesPtr == IntPtr.Zero) | ||
503 | return false; | ||
504 | |||
505 | BinaryWriter bw = new BinaryWriter(st); | ||
506 | bool ok = true; | ||
507 | |||
508 | try | ||
509 | { | ||
510 | |||
511 | bw.Write(m_vertexCount); | ||
512 | bw.Write(m_indexCount); | ||
513 | |||
514 | for (int i = 0; i < 3 * m_vertexCount; i++) | ||
515 | bw.Write(vertices[i]); | ||
516 | for (int i = 0; i < m_indexCount; i++) | ||
517 | bw.Write(indexes[i]); | ||
518 | bw.Write(m_obb.X); | ||
519 | bw.Write(m_obb.Y); | ||
520 | bw.Write(m_obb.Z); | ||
521 | bw.Write(m_obboffset.X); | ||
522 | bw.Write(m_obboffset.Y); | ||
523 | bw.Write(m_obboffset.Z); | ||
524 | } | ||
525 | catch | ||
526 | { | ||
527 | ok = false; | ||
528 | } | ||
529 | |||
530 | if (bw != null) | ||
531 | { | ||
532 | bw.Flush(); | ||
533 | bw.Close(); | ||
534 | } | ||
535 | |||
536 | return ok; | ||
537 | } | ||
538 | |||
539 | public static Mesh FromStream(Stream st, AMeshKey key) | ||
540 | { | ||
541 | Mesh mesh = new Mesh(); | ||
542 | mesh.releaseBuildingMeshData(); | ||
543 | |||
544 | BinaryReader br = new BinaryReader(st); | ||
545 | |||
546 | bool ok = true; | ||
547 | try | ||
548 | { | ||
549 | mesh.m_vertexCount = br.ReadInt32(); | ||
550 | mesh.m_indexCount = br.ReadInt32(); | ||
551 | |||
552 | int n = 3 * mesh.m_vertexCount; | ||
553 | mesh.vertices = new float[n]; | ||
554 | for (int i = 0; i < n; i++) | ||
555 | mesh.vertices[i] = br.ReadSingle(); | ||
556 | |||
557 | mesh.indexes = new int[mesh.m_indexCount]; | ||
558 | for (int i = 0; i < mesh.m_indexCount; i++) | ||
559 | mesh.indexes[i] = br.ReadInt32(); | ||
560 | |||
561 | mesh.m_obb.X = br.ReadSingle(); | ||
562 | mesh.m_obb.Y = br.ReadSingle(); | ||
563 | mesh.m_obb.Z = br.ReadSingle(); | ||
564 | |||
565 | mesh.m_obboffset.X = br.ReadSingle(); | ||
566 | mesh.m_obboffset.Y = br.ReadSingle(); | ||
567 | mesh.m_obboffset.Z = br.ReadSingle(); | ||
568 | } | ||
569 | catch | ||
570 | { | ||
571 | ok = false; | ||
572 | } | ||
573 | |||
574 | br.Close(); | ||
575 | |||
576 | if (ok) | ||
577 | { | ||
578 | mesh.pinMemory(); | ||
579 | |||
580 | mesh.Key = key; | ||
581 | mesh.RefCount = 1; | ||
582 | |||
583 | return mesh; | ||
584 | } | ||
585 | |||
586 | mesh.vertices = null; | ||
587 | mesh.indexes = null; | ||
588 | return null; | ||
410 | } | 589 | } |
411 | } | 590 | } |
412 | } | 591 | } |
diff --git a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs index 4c40175..29fdda4 100644 --- a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs | |||
@@ -42,6 +42,8 @@ using System.Reflection; | |||
42 | using System.IO; | 42 | using System.IO; |
43 | using ComponentAce.Compression.Libs.zlib; | 43 | using ComponentAce.Compression.Libs.zlib; |
44 | using OpenSim.Region.Physics.ConvexDecompositionDotNet; | 44 | using OpenSim.Region.Physics.ConvexDecompositionDotNet; |
45 | using System.Runtime.Serialization; | ||
46 | using System.Runtime.Serialization.Formatters.Binary; | ||
45 | 47 | ||
46 | namespace OpenSim.Region.Physics.Meshing | 48 | namespace OpenSim.Region.Physics.Meshing |
47 | { | 49 | { |
@@ -68,22 +70,22 @@ namespace OpenSim.Region.Physics.Meshing | |||
68 | 70 | ||
69 | // Setting baseDir to a path will enable the dumping of raw files | 71 | // Setting baseDir to a path will enable the dumping of raw files |
70 | // raw files can be imported by blender so a visual inspection of the results can be done | 72 | // raw files can be imported by blender so a visual inspection of the results can be done |
71 | #if SPAM | ||
72 | const string baseDir = "rawFiles"; | ||
73 | #else | ||
74 | private const string baseDir = null; //"rawFiles"; | ||
75 | #endif | ||
76 | 73 | ||
77 | private bool cacheSculptMaps = true; | 74 | public object diskLock = new object(); |
78 | private bool cacheSculptAlphaMaps = true; | 75 | |
76 | public bool doMeshFileCache = true; | ||
77 | |||
78 | public string cachePath = "MeshCache"; | ||
79 | public TimeSpan CacheExpire; | ||
80 | public bool doCacheExpire = true; | ||
81 | |||
82 | // const string baseDir = "rawFiles"; | ||
83 | private const string baseDir = null; //"rawFiles"; | ||
79 | 84 | ||
80 | private string decodedSculptMapPath = null; | ||
81 | private bool useMeshiesPhysicsMesh = false; | 85 | private bool useMeshiesPhysicsMesh = false; |
82 | 86 | ||
83 | private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh | 87 | private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh |
84 | 88 | ||
85 | // private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>(); | ||
86 | // private Dictionary<ulong, Mesh> m_uniqueReleasedMeshes = new Dictionary<ulong, Mesh>(); | ||
87 | private Dictionary<AMeshKey, Mesh> m_uniqueMeshes = new Dictionary<AMeshKey, Mesh>(); | 89 | private Dictionary<AMeshKey, Mesh> m_uniqueMeshes = new Dictionary<AMeshKey, Mesh>(); |
88 | private Dictionary<AMeshKey, Mesh> m_uniqueReleasedMeshes = new Dictionary<AMeshKey, Mesh>(); | 90 | private Dictionary<AMeshKey, Mesh> m_uniqueReleasedMeshes = new Dictionary<AMeshKey, Mesh>(); |
89 | 91 | ||
@@ -92,29 +94,29 @@ namespace OpenSim.Region.Physics.Meshing | |||
92 | IConfig start_config = config.Configs["Startup"]; | 94 | IConfig start_config = config.Configs["Startup"]; |
93 | IConfig mesh_config = config.Configs["Mesh"]; | 95 | IConfig mesh_config = config.Configs["Mesh"]; |
94 | 96 | ||
95 | decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); | ||
96 | 97 | ||
97 | cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); | 98 | float fcache = 48.0f; |
99 | // float fcache = 0.02f; | ||
98 | 100 | ||
99 | if (Environment.OSVersion.Platform == PlatformID.Unix) | 101 | if(mesh_config != null) |
100 | { | 102 | { |
101 | cacheSculptAlphaMaps = false; | 103 | useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); |
104 | if (useMeshiesPhysicsMesh) | ||
105 | { | ||
106 | doMeshFileCache = mesh_config.GetBoolean("MeshFileCache", doMeshFileCache); | ||
107 | cachePath = mesh_config.GetString("MeshFileCachePath", cachePath); | ||
108 | fcache = mesh_config.GetFloat("MeshFileCacheExpireHours", fcache); | ||
109 | doCacheExpire = mesh_config.GetBoolean("MeshFileCacheDoExpire", doCacheExpire); | ||
110 | } | ||
111 | else | ||
112 | { | ||
113 | doMeshFileCache = false; | ||
114 | doCacheExpire = false; | ||
115 | } | ||
102 | } | 116 | } |
103 | else | ||
104 | cacheSculptAlphaMaps = cacheSculptMaps; | ||
105 | 117 | ||
106 | if(mesh_config != null) | 118 | CacheExpire = TimeSpan.FromHours(fcache); |
107 | useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); | ||
108 | 119 | ||
109 | try | ||
110 | { | ||
111 | if (!Directory.Exists(decodedSculptMapPath)) | ||
112 | Directory.CreateDirectory(decodedSculptMapPath); | ||
113 | } | ||
114 | catch (Exception e) | ||
115 | { | ||
116 | m_log.WarnFormat("[SCULPT]: Unable to create {0} directory: ", decodedSculptMapPath, e.Message); | ||
117 | } | ||
118 | } | 120 | } |
119 | 121 | ||
120 | /// <summary> | 122 | /// <summary> |
@@ -212,7 +214,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
212 | /// <param name="size">Size of entire object</param> | 214 | /// <param name="size">Size of entire object</param> |
213 | /// <param name="coords"></param> | 215 | /// <param name="coords"></param> |
214 | /// <param name="faces"></param> | 216 | /// <param name="faces"></param> |
215 | private void AddSubMesh(OSDMap subMeshData, Vector3 size, List<Coord> coords, List<Face> faces) | 217 | private void AddSubMesh(OSDMap subMeshData, List<Coord> coords, List<Face> faces) |
216 | { | 218 | { |
217 | // Console.WriteLine("subMeshMap for {0} - {1}", primName, Util.GetFormattedXml((OSD)subMeshMap)); | 219 | // Console.WriteLine("subMeshMap for {0} - {1}", primName, Util.GetFormattedXml((OSD)subMeshMap)); |
218 | 220 | ||
@@ -245,9 +247,9 @@ namespace OpenSim.Region.Physics.Meshing | |||
245 | ushort uZ = Utils.BytesToUInt16(posBytes, i + 4); | 247 | ushort uZ = Utils.BytesToUInt16(posBytes, i + 4); |
246 | 248 | ||
247 | Coord c = new Coord( | 249 | Coord c = new Coord( |
248 | Utils.UInt16ToFloat(uX, posMin.X, posMax.X) * size.X, | 250 | Utils.UInt16ToFloat(uX, posMin.X, posMax.X), |
249 | Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y) * size.Y, | 251 | Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y), |
250 | Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z) * size.Z); | 252 | Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z)); |
251 | 253 | ||
252 | coords.Add(c); | 254 | coords.Add(c); |
253 | } | 255 | } |
@@ -271,7 +273,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
271 | /// <param name="size"></param> | 273 | /// <param name="size"></param> |
272 | /// <param name="lod"></param> | 274 | /// <param name="lod"></param> |
273 | /// <returns></returns> | 275 | /// <returns></returns> |
274 | private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool convex) | 276 | private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, float lod, bool convex) |
275 | { | 277 | { |
276 | // m_log.DebugFormat( | 278 | // m_log.DebugFormat( |
277 | // "[MESH]: Creating physics proxy for {0}, shape {1}", | 279 | // "[MESH]: Creating physics proxy for {0}, shape {1}", |
@@ -287,18 +289,18 @@ namespace OpenSim.Region.Physics.Meshing | |||
287 | if (!useMeshiesPhysicsMesh) | 289 | if (!useMeshiesPhysicsMesh) |
288 | return null; | 290 | return null; |
289 | 291 | ||
290 | if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, size, out coords, out faces, convex)) | 292 | if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, out coords, out faces, convex)) |
291 | return null; | 293 | return null; |
292 | } | 294 | } |
293 | else | 295 | else |
294 | { | 296 | { |
295 | if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, out coords, out faces)) | 297 | if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, lod, out coords, out faces)) |
296 | return null; | 298 | return null; |
297 | } | 299 | } |
298 | } | 300 | } |
299 | else | 301 | else |
300 | { | 302 | { |
301 | if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces)) | 303 | if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, lod, out coords, out faces)) |
302 | return null; | 304 | return null; |
303 | } | 305 | } |
304 | 306 | ||
@@ -333,7 +335,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
333 | /// <param name="faces">Faces are added to this list by the method.</param> | 335 | /// <param name="faces">Faces are added to this list by the method.</param> |
334 | /// <returns>true if coords and faces were successfully generated, false if not</returns> | 336 | /// <returns>true if coords and faces were successfully generated, false if not</returns> |
335 | private bool GenerateCoordsAndFacesFromPrimMeshData( | 337 | private bool GenerateCoordsAndFacesFromPrimMeshData( |
336 | string primName, PrimitiveBaseShape primShape, Vector3 size, out List<Coord> coords, out List<Face> faces, bool convex) | 338 | string primName, PrimitiveBaseShape primShape, out List<Coord> coords, out List<Face> faces, bool convex) |
337 | { | 339 | { |
338 | // m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName); | 340 | // m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName); |
339 | 341 | ||
@@ -345,7 +347,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
345 | 347 | ||
346 | if (primShape.SculptData.Length <= 0) | 348 | if (primShape.SculptData.Length <= 0) |
347 | { | 349 | { |
348 | m_log.InfoFormat("[MESH]: asset data for {0} is zero length", primName); | 350 | // m_log.InfoFormat("[MESH]: asset data for {0} is zero length", primName); |
349 | return false; | 351 | return false; |
350 | } | 352 | } |
351 | 353 | ||
@@ -406,7 +408,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
406 | OSD decodedMeshOsd = new OSD(); | 408 | OSD decodedMeshOsd = new OSD(); |
407 | byte[] meshBytes = new byte[physSize]; | 409 | byte[] meshBytes = new byte[physSize]; |
408 | System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize); | 410 | System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize); |
409 | // byte[] decompressed = new byte[physSize * 5]; | 411 | |
410 | try | 412 | try |
411 | { | 413 | { |
412 | using (MemoryStream inMs = new MemoryStream(meshBytes)) | 414 | using (MemoryStream inMs = new MemoryStream(meshBytes)) |
@@ -444,13 +446,13 @@ namespace OpenSim.Region.Physics.Meshing | |||
444 | // physics_shape is an array of OSDMaps, one for each submesh | 446 | // physics_shape is an array of OSDMaps, one for each submesh |
445 | if (decodedMeshOsd is OSDArray) | 447 | if (decodedMeshOsd is OSDArray) |
446 | { | 448 | { |
447 | // Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd)); | 449 | // Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd)); |
448 | 450 | ||
449 | decodedMeshOsdArray = (OSDArray)decodedMeshOsd; | 451 | decodedMeshOsdArray = (OSDArray)decodedMeshOsd; |
450 | foreach (OSD subMeshOsd in decodedMeshOsdArray) | 452 | foreach (OSD subMeshOsd in decodedMeshOsdArray) |
451 | { | 453 | { |
452 | if (subMeshOsd is OSDMap) | 454 | if (subMeshOsd is OSDMap) |
453 | AddSubMesh(subMeshOsd as OSDMap, size, coords, faces); | 455 | AddSubMesh(subMeshOsd as OSDMap, coords, faces); |
454 | } | 456 | } |
455 | } | 457 | } |
456 | } | 458 | } |
@@ -522,9 +524,9 @@ namespace OpenSim.Region.Physics.Meshing | |||
522 | t3 = data[ptr++]; | 524 | t3 = data[ptr++]; |
523 | t3 += data[ptr++] << 8; | 525 | t3 += data[ptr++] << 8; |
524 | 526 | ||
525 | f3 = new float3((t1 * range.X + min.X) * size.X, | 527 | f3 = new float3((t1 * range.X + min.X), |
526 | (t2 * range.Y + min.Y) * size.Y, | 528 | (t2 * range.Y + min.Y), |
527 | (t3 * range.Z + min.Z) * size.Z); | 529 | (t3 * range.Z + min.Z)); |
528 | vs.Add(f3); | 530 | vs.Add(f3); |
529 | } | 531 | } |
530 | 532 | ||
@@ -621,9 +623,9 @@ namespace OpenSim.Region.Physics.Meshing | |||
621 | t3 = data[i++]; | 623 | t3 = data[i++]; |
622 | t3 += data[i++] << 8; | 624 | t3 += data[i++] << 8; |
623 | 625 | ||
624 | f3 = new float3((t1 * range.X + min.X) * size.X, | 626 | f3 = new float3((t1 * range.X + min.X), |
625 | (t2 * range.Y + min.Y) * size.Y, | 627 | (t2 * range.Y + min.Y), |
626 | (t3 * range.Z + min.Z) * size.Z); | 628 | (t3 * range.Z + min.Z)); |
627 | vs.Add(f3); | 629 | vs.Add(f3); |
628 | } | 630 | } |
629 | 631 | ||
@@ -711,35 +713,13 @@ namespace OpenSim.Region.Physics.Meshing | |||
711 | /// <param name="faces">Faces are added to this list by the method.</param> | 713 | /// <param name="faces">Faces are added to this list by the method.</param> |
712 | /// <returns>true if coords and faces were successfully generated, false if not</returns> | 714 | /// <returns>true if coords and faces were successfully generated, false if not</returns> |
713 | private bool GenerateCoordsAndFacesFromPrimSculptData( | 715 | private bool GenerateCoordsAndFacesFromPrimSculptData( |
714 | string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, out List<Coord> coords, out List<Face> faces) | 716 | string primName, PrimitiveBaseShape primShape, float lod, out List<Coord> coords, out List<Face> faces) |
715 | { | 717 | { |
716 | coords = new List<Coord>(); | 718 | coords = new List<Coord>(); |
717 | faces = new List<Face>(); | 719 | faces = new List<Face>(); |
718 | PrimMesher.SculptMesh sculptMesh; | 720 | PrimMesher.SculptMesh sculptMesh; |
719 | Image idata = null; | 721 | Image idata = null; |
720 | string decodedSculptFileName = ""; | ||
721 | |||
722 | if (cacheSculptMaps && primShape.SculptTexture != UUID.Zero) | ||
723 | { | ||
724 | decodedSculptFileName = System.IO.Path.Combine(decodedSculptMapPath, "smap_" + primShape.SculptTexture.ToString()); | ||
725 | try | ||
726 | { | ||
727 | if (File.Exists(decodedSculptFileName)) | ||
728 | { | ||
729 | idata = Image.FromFile(decodedSculptFileName); | ||
730 | } | ||
731 | } | ||
732 | catch (Exception e) | ||
733 | { | ||
734 | m_log.Error("[SCULPT]: unable to load cached sculpt map " + decodedSculptFileName + " " + e.Message); | ||
735 | 722 | ||
736 | } | ||
737 | //if (idata != null) | ||
738 | // m_log.Debug("[SCULPT]: loaded cached map asset for map ID: " + primShape.SculptTexture.ToString()); | ||
739 | } | ||
740 | |||
741 | if (idata == null) | ||
742 | { | ||
743 | if (primShape.SculptData == null || primShape.SculptData.Length == 0) | 723 | if (primShape.SculptData == null || primShape.SculptData.Length == 0) |
744 | return false; | 724 | return false; |
745 | 725 | ||
@@ -748,25 +728,15 @@ namespace OpenSim.Region.Physics.Meshing | |||
748 | OpenMetaverse.Imaging.ManagedImage unusedData; | 728 | OpenMetaverse.Imaging.ManagedImage unusedData; |
749 | OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata); | 729 | OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata); |
750 | 730 | ||
731 | unusedData = null; | ||
732 | |||
751 | if (idata == null) | 733 | if (idata == null) |
752 | { | 734 | { |
753 | // In some cases it seems that the decode can return a null bitmap without throwing | 735 | // In some cases it seems that the decode can return a null bitmap without throwing |
754 | // an exception | 736 | // an exception |
755 | m_log.WarnFormat("[PHYSICS]: OpenJPEG decoded sculpt data for {0} to a null bitmap. Ignoring.", primName); | 737 | m_log.WarnFormat("[PHYSICS]: OpenJPEG decoded sculpt data for {0} to a null bitmap. Ignoring.", primName); |
756 | |||
757 | return false; | 738 | return false; |
758 | } | 739 | } |
759 | |||
760 | unusedData = null; | ||
761 | |||
762 | //idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData); | ||
763 | |||
764 | if (cacheSculptMaps && (cacheSculptAlphaMaps || (((ImageFlags)(idata.Flags) & ImageFlags.HasAlpha) ==0))) | ||
765 | // don't cache images with alpha channel in linux since mono can't load them correctly) | ||
766 | { | ||
767 | try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); } | ||
768 | catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); } | ||
769 | } | ||
770 | } | 740 | } |
771 | catch (DllNotFoundException) | 741 | catch (DllNotFoundException) |
772 | { | 742 | { |
@@ -783,7 +753,6 @@ namespace OpenSim.Region.Physics.Meshing | |||
783 | m_log.Error("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed: " + ex.Message); | 753 | m_log.Error("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed: " + ex.Message); |
784 | return false; | 754 | return false; |
785 | } | 755 | } |
786 | } | ||
787 | 756 | ||
788 | PrimMesher.SculptMesh.SculptType sculptType; | 757 | PrimMesher.SculptMesh.SculptType sculptType; |
789 | // remove mirror and invert bits | 758 | // remove mirror and invert bits |
@@ -814,9 +783,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
814 | 783 | ||
815 | idata.Dispose(); | 784 | idata.Dispose(); |
816 | 785 | ||
817 | sculptMesh.DumpRaw(baseDir, primName, "primMesh"); | 786 | // sculptMesh.DumpRaw(baseDir, primName, "primMesh"); |
818 | |||
819 | sculptMesh.Scale(size.X, size.Y, size.Z); | ||
820 | 787 | ||
821 | coords = sculptMesh.coords; | 788 | coords = sculptMesh.coords; |
822 | faces = sculptMesh.faces; | 789 | faces = sculptMesh.faces; |
@@ -834,7 +801,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
834 | /// <param name="faces">Faces are added to this list by the method.</param> | 801 | /// <param name="faces">Faces are added to this list by the method.</param> |
835 | /// <returns>true if coords and faces were successfully generated, false if not</returns> | 802 | /// <returns>true if coords and faces were successfully generated, false if not</returns> |
836 | private bool GenerateCoordsAndFacesFromPrimShapeData( | 803 | private bool GenerateCoordsAndFacesFromPrimShapeData( |
837 | string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, out List<Coord> coords, out List<Face> faces) | 804 | string primName, PrimitiveBaseShape primShape, float lod, out List<Coord> coords, out List<Face> faces) |
838 | { | 805 | { |
839 | PrimMesh primMesh; | 806 | PrimMesh primMesh; |
840 | coords = new List<Coord>(); | 807 | coords = new List<Coord>(); |
@@ -969,9 +936,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
969 | } | 936 | } |
970 | } | 937 | } |
971 | 938 | ||
972 | primMesh.DumpRaw(baseDir, primName, "primMesh"); | 939 | // primMesh.DumpRaw(baseDir, primName, "primMesh"); |
973 | |||
974 | primMesh.Scale(size.X, size.Y, size.Z); | ||
975 | 940 | ||
976 | coords = primMesh.coords; | 941 | coords = primMesh.coords; |
977 | faces = primMesh.faces; | 942 | faces = primMesh.faces; |
@@ -985,12 +950,14 @@ namespace OpenSim.Region.Physics.Meshing | |||
985 | Byte[] someBytes; | 950 | Byte[] someBytes; |
986 | 951 | ||
987 | key.hashB = 5181; | 952 | key.hashB = 5181; |
953 | key.hashC = 5181; | ||
988 | ulong hash = 5381; | 954 | ulong hash = 5381; |
989 | 955 | ||
990 | if (primShape.SculptEntry) | 956 | if (primShape.SculptEntry) |
991 | { | 957 | { |
992 | key.uuid = primShape.SculptTexture; | 958 | key.uuid = primShape.SculptTexture; |
993 | key.hashB = mdjb2(key.hashB, primShape.SculptType); | 959 | key.hashC = mdjb2(key.hashC, primShape.SculptType); |
960 | key.hashC = mdjb2(key.hashC, primShape.PCode); | ||
994 | } | 961 | } |
995 | else | 962 | else |
996 | { | 963 | { |
@@ -1002,6 +969,8 @@ namespace OpenSim.Region.Physics.Meshing | |||
1002 | hash = mdjb2(hash, primShape.PathScaleX); | 969 | hash = mdjb2(hash, primShape.PathScaleX); |
1003 | hash = mdjb2(hash, primShape.PathScaleY); | 970 | hash = mdjb2(hash, primShape.PathScaleY); |
1004 | hash = mdjb2(hash, primShape.PathShearX); | 971 | hash = mdjb2(hash, primShape.PathShearX); |
972 | key.hashA = hash; | ||
973 | hash = key.hashB; | ||
1005 | hash = mdjb2(hash, primShape.PathShearY); | 974 | hash = mdjb2(hash, primShape.PathShearY); |
1006 | hash = mdjb2(hash, (byte)primShape.PathTwist); | 975 | hash = mdjb2(hash, (byte)primShape.PathTwist); |
1007 | hash = mdjb2(hash, (byte)primShape.PathTwistBegin); | 976 | hash = mdjb2(hash, (byte)primShape.PathTwistBegin); |
@@ -1013,26 +982,38 @@ namespace OpenSim.Region.Physics.Meshing | |||
1013 | hash = mdjb2(hash, primShape.ProfileBegin); | 982 | hash = mdjb2(hash, primShape.ProfileBegin); |
1014 | hash = mdjb2(hash, primShape.ProfileEnd); | 983 | hash = mdjb2(hash, primShape.ProfileEnd); |
1015 | hash = mdjb2(hash, primShape.ProfileHollow); | 984 | hash = mdjb2(hash, primShape.ProfileHollow); |
1016 | key.hashA = hash; | 985 | hash = mdjb2(hash, primShape.PCode); |
986 | key.hashB = hash; | ||
1017 | } | 987 | } |
1018 | 988 | ||
1019 | hash = key.hashB; | 989 | hash = key.hashC; |
1020 | |||
1021 | someBytes = size.GetBytes(); | ||
1022 | for (int i = 0; i < someBytes.Length; i++) | ||
1023 | hash = mdjb2(hash, someBytes[i]); | ||
1024 | 990 | ||
1025 | hash = mdjb2(hash, lod); | 991 | hash = mdjb2(hash, lod); |
1026 | 992 | ||
1027 | hash &= 0x3fffffffffffffff; | 993 | if (size == m_MeshUnitSize) |
994 | { | ||
995 | hash = hash << 8; | ||
996 | hash |= 8; | ||
997 | } | ||
998 | else | ||
999 | { | ||
1000 | someBytes = size.GetBytes(); | ||
1001 | for (int i = 0; i < someBytes.Length; i++) | ||
1002 | hash = mdjb2(hash, someBytes[i]); | ||
1003 | hash = hash << 8; | ||
1004 | } | ||
1028 | 1005 | ||
1029 | if (convex) | 1006 | if (convex) |
1030 | hash |= 0x4000000000000000; | 1007 | hash |= 4; |
1031 | 1008 | ||
1032 | if (primShape.SculptEntry) | 1009 | if (primShape.SculptEntry) |
1033 | hash |= 0x8000000000000000; | 1010 | { |
1011 | hash |= 1; | ||
1012 | if (primShape.SculptType == (byte)SculptType.Mesh) | ||
1013 | hash |= 2; | ||
1014 | } | ||
1034 | 1015 | ||
1035 | key.hashB = hash; | 1016 | key.hashC = hash; |
1036 | 1017 | ||
1037 | return key; | 1018 | return key; |
1038 | } | 1019 | } |
@@ -1048,35 +1029,74 @@ namespace OpenSim.Region.Physics.Meshing | |||
1048 | return ((hash << 5) + hash) + (ulong)(c >> 8); | 1029 | return ((hash << 5) + hash) + (ulong)(c >> 8); |
1049 | } | 1030 | } |
1050 | 1031 | ||
1051 | |||
1052 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) | 1032 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) |
1053 | { | 1033 | { |
1054 | return CreateMesh(primName, primShape, size, lod, false,false); | 1034 | return CreateMesh(primName, primShape, size, lod, false,false,false); |
1055 | } | 1035 | } |
1056 | 1036 | ||
1057 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) | 1037 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) |
1058 | { | 1038 | { |
1059 | return CreateMesh(primName, primShape, size, lod, false,false); | 1039 | return CreateMesh(primName, primShape, size, lod, false,false,false); |
1060 | } | 1040 | } |
1061 | 1041 | ||
1062 | private static Vector3 m_MeshUnitSize = new Vector3(0.5f, 0.5f, 0.5f); | 1042 | public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex) |
1043 | { | ||
1044 | Mesh mesh = null; | ||
1045 | |||
1046 | if (size.X < 0.01f) size.X = 0.01f; | ||
1047 | if (size.Y < 0.01f) size.Y = 0.01f; | ||
1048 | if (size.Z < 0.01f) size.Z = 0.01f; | ||
1049 | |||
1050 | AMeshKey key = GetMeshUniqueKey(primShape, size, (byte)lod, convex); | ||
1051 | lock (m_uniqueMeshes) | ||
1052 | { | ||
1053 | m_uniqueMeshes.TryGetValue(key, out mesh); | ||
1054 | |||
1055 | if (mesh != null) | ||
1056 | { | ||
1057 | mesh.RefCount++; | ||
1058 | return mesh; | ||
1059 | } | ||
1060 | } | ||
1061 | |||
1062 | // try to find a identical mesh on meshs recently released | ||
1063 | lock (m_uniqueReleasedMeshes) | ||
1064 | { | ||
1065 | m_uniqueReleasedMeshes.TryGetValue(key, out mesh); | ||
1066 | if (mesh != null) | ||
1067 | { | ||
1068 | m_uniqueReleasedMeshes.Remove(key); | ||
1069 | lock (m_uniqueMeshes) | ||
1070 | { | ||
1071 | try | ||
1072 | { | ||
1073 | m_uniqueMeshes.Add(key, mesh); | ||
1074 | } | ||
1075 | catch { } | ||
1076 | } | ||
1077 | mesh.RefCount = 1; | ||
1078 | return mesh; | ||
1079 | } | ||
1080 | } | ||
1081 | return null; | ||
1082 | } | ||
1063 | 1083 | ||
1064 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex) | 1084 | private static Vector3 m_MeshUnitSize = new Vector3(1.0f, 1.0f, 1.0f); |
1085 | |||
1086 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde) | ||
1065 | { | 1087 | { |
1066 | #if SPAM | 1088 | #if SPAM |
1067 | m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName); | 1089 | m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName); |
1068 | #endif | 1090 | #endif |
1069 | 1091 | ||
1070 | Mesh mesh = null; | 1092 | Mesh mesh = null; |
1071 | // ulong key = 0; | ||
1072 | |||
1073 | 1093 | ||
1074 | if (size.X < 0.01f) size.X = 0.01f; | 1094 | if (size.X < 0.01f) size.X = 0.01f; |
1075 | if (size.Y < 0.01f) size.Y = 0.01f; | 1095 | if (size.Y < 0.01f) size.Y = 0.01f; |
1076 | if (size.Z < 0.01f) size.Z = 0.01f; | 1096 | if (size.Z < 0.01f) size.Z = 0.01f; |
1077 | 1097 | ||
1078 | // try to find a identical mesh on meshs in use | 1098 | // try to find a identical mesh on meshs in use |
1079 | // key = primShape.GetMeshKey(size, lod, convex); | 1099 | |
1080 | AMeshKey key = GetMeshUniqueKey(primShape,size,(byte)lod, convex); | 1100 | AMeshKey key = GetMeshUniqueKey(primShape,size,(byte)lod, convex); |
1081 | 1101 | ||
1082 | lock (m_uniqueMeshes) | 1102 | lock (m_uniqueMeshes) |
@@ -1098,35 +1118,78 @@ namespace OpenSim.Region.Physics.Meshing | |||
1098 | { | 1118 | { |
1099 | m_uniqueReleasedMeshes.Remove(key); | 1119 | m_uniqueReleasedMeshes.Remove(key); |
1100 | lock (m_uniqueMeshes) | 1120 | lock (m_uniqueMeshes) |
1101 | m_uniqueMeshes.Add(key, mesh); | 1121 | { |
1122 | try | ||
1123 | { | ||
1124 | m_uniqueMeshes.Add(key, mesh); | ||
1125 | } | ||
1126 | catch { } | ||
1127 | } | ||
1102 | mesh.RefCount = 1; | 1128 | mesh.RefCount = 1; |
1103 | return mesh; | 1129 | return mesh; |
1104 | } | 1130 | } |
1105 | } | 1131 | } |
1106 | 1132 | ||
1107 | mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod,convex); | 1133 | Mesh UnitMesh = null; |
1134 | AMeshKey unitKey = GetMeshUniqueKey(primShape, m_MeshUnitSize, (byte)lod, convex); | ||
1108 | 1135 | ||
1109 | if (mesh != null) | 1136 | lock (m_uniqueReleasedMeshes) |
1110 | { | 1137 | { |
1111 | if ((!isPhysical) && size.X < minSizeForComplexMesh && size.Y < minSizeForComplexMesh && size.Z < minSizeForComplexMesh) | 1138 | m_uniqueReleasedMeshes.TryGetValue(unitKey, out UnitMesh); |
1139 | if (UnitMesh != null) | ||
1112 | { | 1140 | { |
1113 | #if SPAM | 1141 | UnitMesh.RefCount = 1; |
1114 | m_log.Debug("Meshmerizer: prim " + primName + " has a size of " + size.ToString() + " which is below threshold of " + | ||
1115 | minSizeForComplexMesh.ToString() + " - creating simple bounding box"); | ||
1116 | #endif | ||
1117 | mesh = CreateBoundingBoxMesh(mesh); | ||
1118 | mesh.DumpRaw(baseDir, primName, "Z extruded"); | ||
1119 | } | 1142 | } |
1143 | } | ||
1120 | 1144 | ||
1121 | // trim the vertex and triangle lists to free up memory | 1145 | if (UnitMesh == null && primShape.SculptEntry && doMeshFileCache) |
1122 | mesh.TrimExcess(); | 1146 | UnitMesh = GetFromFileCache(unitKey); |
1123 | mesh.Key = key; | ||
1124 | mesh.RefCount = 1; | ||
1125 | 1147 | ||
1126 | lock(m_uniqueMeshes) | 1148 | if (UnitMesh == null) |
1127 | m_uniqueMeshes.Add(key, mesh); | 1149 | { |
1150 | UnitMesh = CreateMeshFromPrimMesher(primName, primShape, lod, convex); | ||
1151 | |||
1152 | if (UnitMesh == null) | ||
1153 | return null; | ||
1154 | |||
1155 | UnitMesh.DumpRaw(baseDir, unitKey.ToString(), "Z"); | ||
1156 | |||
1157 | if (forOde) | ||
1158 | { | ||
1159 | // force pinned mem allocation | ||
1160 | UnitMesh.PrepForOde(); | ||
1161 | } | ||
1162 | else | ||
1163 | UnitMesh.TrimExcess(); | ||
1164 | |||
1165 | UnitMesh.Key = unitKey; | ||
1166 | UnitMesh.RefCount = 1; | ||
1167 | |||
1168 | if (doMeshFileCache && primShape.SculptEntry) | ||
1169 | StoreToFileCache(unitKey, UnitMesh); | ||
1170 | |||
1171 | lock (m_uniqueReleasedMeshes) | ||
1172 | { | ||
1173 | try | ||
1174 | { | ||
1175 | m_uniqueReleasedMeshes.Add(unitKey, UnitMesh); | ||
1176 | } | ||
1177 | catch { } | ||
1178 | } | ||
1128 | } | 1179 | } |
1129 | 1180 | ||
1181 | mesh = UnitMesh.Scale(size); | ||
1182 | mesh.Key = key; | ||
1183 | mesh.RefCount = 1; | ||
1184 | lock (m_uniqueMeshes) | ||
1185 | { | ||
1186 | try | ||
1187 | { | ||
1188 | m_uniqueMeshes.Add(key, mesh); | ||
1189 | } | ||
1190 | catch { } | ||
1191 | } | ||
1192 | |||
1130 | return mesh; | 1193 | return mesh; |
1131 | } | 1194 | } |
1132 | 1195 | ||
@@ -1137,21 +1200,27 @@ namespace OpenSim.Region.Physics.Meshing | |||
1137 | 1200 | ||
1138 | Mesh mesh = (Mesh)imesh; | 1201 | Mesh mesh = (Mesh)imesh; |
1139 | 1202 | ||
1140 | int curRefCount = mesh.RefCount; | ||
1141 | curRefCount--; | ||
1142 | |||
1143 | if (curRefCount > 0) | ||
1144 | { | ||
1145 | mesh.RefCount = curRefCount; | ||
1146 | return; | ||
1147 | } | ||
1148 | |||
1149 | lock (m_uniqueMeshes) | 1203 | lock (m_uniqueMeshes) |
1150 | { | 1204 | { |
1205 | int curRefCount = mesh.RefCount; | ||
1206 | curRefCount--; | ||
1207 | |||
1208 | if (curRefCount > 0) | ||
1209 | { | ||
1210 | mesh.RefCount = curRefCount; | ||
1211 | return; | ||
1212 | } | ||
1213 | |||
1151 | mesh.RefCount = 0; | 1214 | mesh.RefCount = 0; |
1152 | m_uniqueMeshes.Remove(mesh.Key); | 1215 | m_uniqueMeshes.Remove(mesh.Key); |
1153 | lock (m_uniqueReleasedMeshes) | 1216 | lock (m_uniqueReleasedMeshes) |
1154 | m_uniqueReleasedMeshes.Add(mesh.Key, mesh); | 1217 | { |
1218 | try | ||
1219 | { | ||
1220 | m_uniqueReleasedMeshes.Add(mesh.Key, mesh); | ||
1221 | } | ||
1222 | catch { } | ||
1223 | } | ||
1155 | } | 1224 | } |
1156 | } | 1225 | } |
1157 | 1226 | ||
@@ -1178,10 +1247,170 @@ namespace OpenSim.Region.Physics.Meshing | |||
1178 | foreach (Mesh m in meshstodelete) | 1247 | foreach (Mesh m in meshstodelete) |
1179 | { | 1248 | { |
1180 | m_uniqueReleasedMeshes.Remove(m.Key); | 1249 | m_uniqueReleasedMeshes.Remove(m.Key); |
1181 | m.releaseSourceMeshData(); | 1250 | m.releaseBuildingMeshData(); |
1182 | m.releasePinned(); | 1251 | m.releasePinned(); |
1183 | } | 1252 | } |
1184 | } | 1253 | } |
1185 | } | 1254 | } |
1255 | |||
1256 | public void FileNames(AMeshKey key, out string dir,out string fullFileName) | ||
1257 | { | ||
1258 | string id = key.ToString(); | ||
1259 | string init = id.Substring(0, 1); | ||
1260 | dir = System.IO.Path.Combine(cachePath, init); | ||
1261 | fullFileName = System.IO.Path.Combine(dir, id); | ||
1262 | } | ||
1263 | |||
1264 | public string FullFileName(AMeshKey key) | ||
1265 | { | ||
1266 | string id = key.ToString(); | ||
1267 | string init = id.Substring(0,1); | ||
1268 | id = System.IO.Path.Combine(init, id); | ||
1269 | id = System.IO.Path.Combine(cachePath, id); | ||
1270 | return id; | ||
1271 | } | ||
1272 | |||
1273 | private Mesh GetFromFileCache(AMeshKey key) | ||
1274 | { | ||
1275 | Mesh mesh = null; | ||
1276 | string filename = FullFileName(key); | ||
1277 | bool ok = true; | ||
1278 | |||
1279 | lock (diskLock) | ||
1280 | { | ||
1281 | if (File.Exists(filename)) | ||
1282 | { | ||
1283 | FileStream stream = null; | ||
1284 | try | ||
1285 | { | ||
1286 | stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); | ||
1287 | BinaryFormatter bformatter = new BinaryFormatter(); | ||
1288 | |||
1289 | mesh = Mesh.FromStream(stream, key); | ||
1290 | |||
1291 | } | ||
1292 | catch (Exception e) | ||
1293 | { | ||
1294 | ok = false; | ||
1295 | m_log.ErrorFormat( | ||
1296 | "[MESH CACHE]: Failed to get file {0}. Exception {1} {2}", | ||
1297 | filename, e.Message, e.StackTrace); | ||
1298 | } | ||
1299 | |||
1300 | if (stream != null) | ||
1301 | stream.Close(); | ||
1302 | |||
1303 | if (mesh == null || !ok) | ||
1304 | File.Delete(filename); | ||
1305 | else | ||
1306 | File.SetLastAccessTimeUtc(filename, DateTime.UtcNow); | ||
1307 | } | ||
1308 | } | ||
1309 | |||
1310 | return mesh; | ||
1311 | } | ||
1312 | |||
1313 | private void StoreToFileCache(AMeshKey key, Mesh mesh) | ||
1314 | { | ||
1315 | Stream stream = null; | ||
1316 | bool ok = false; | ||
1317 | |||
1318 | // Make sure the target cache directory exists | ||
1319 | string dir = String.Empty; | ||
1320 | string filename = String.Empty; | ||
1321 | |||
1322 | FileNames(key, out dir, out filename); | ||
1323 | |||
1324 | lock (diskLock) | ||
1325 | { | ||
1326 | try | ||
1327 | { | ||
1328 | if (!Directory.Exists(dir)) | ||
1329 | { | ||
1330 | Directory.CreateDirectory(dir); | ||
1331 | } | ||
1332 | |||
1333 | stream = File.Open(filename, FileMode.Create); | ||
1334 | ok = mesh.ToStream(stream); | ||
1335 | } | ||
1336 | catch (IOException e) | ||
1337 | { | ||
1338 | m_log.ErrorFormat( | ||
1339 | "[MESH CACHE]: Failed to write file {0}. Exception {1} {2}.", | ||
1340 | filename, e.Message, e.StackTrace); | ||
1341 | ok = false; | ||
1342 | } | ||
1343 | |||
1344 | if (stream != null) | ||
1345 | stream.Close(); | ||
1346 | |||
1347 | if (File.Exists(filename)) | ||
1348 | { | ||
1349 | if (ok) | ||
1350 | File.SetLastAccessTimeUtc(filename, DateTime.UtcNow); | ||
1351 | else | ||
1352 | File.Delete(filename); | ||
1353 | } | ||
1354 | } | ||
1355 | } | ||
1356 | |||
1357 | public void ExpireFileCache() | ||
1358 | { | ||
1359 | if (!doCacheExpire) | ||
1360 | return; | ||
1361 | |||
1362 | string controlfile = System.IO.Path.Combine(cachePath, "cntr"); | ||
1363 | |||
1364 | lock (diskLock) | ||
1365 | { | ||
1366 | try | ||
1367 | { | ||
1368 | if (File.Exists(controlfile)) | ||
1369 | { | ||
1370 | int ndeleted = 0; | ||
1371 | int totalfiles = 0; | ||
1372 | int ndirs = 0; | ||
1373 | DateTime OlderTime = File.GetLastAccessTimeUtc(controlfile) - CacheExpire; | ||
1374 | File.SetLastAccessTimeUtc(controlfile, DateTime.UtcNow); | ||
1375 | |||
1376 | foreach (string dir in Directory.GetDirectories(cachePath)) | ||
1377 | { | ||
1378 | try | ||
1379 | { | ||
1380 | foreach (string file in Directory.GetFiles(dir)) | ||
1381 | { | ||
1382 | try | ||
1383 | { | ||
1384 | if (File.GetLastAccessTimeUtc(file) < OlderTime) | ||
1385 | { | ||
1386 | File.Delete(file); | ||
1387 | ndeleted++; | ||
1388 | } | ||
1389 | } | ||
1390 | catch { } | ||
1391 | totalfiles++; | ||
1392 | } | ||
1393 | } | ||
1394 | catch { } | ||
1395 | ndirs++; | ||
1396 | } | ||
1397 | |||
1398 | if (ndeleted == 0) | ||
1399 | m_log.InfoFormat("[MESH CACHE]: {0} Files in {1} cache folders, no expires", | ||
1400 | totalfiles,ndirs); | ||
1401 | else | ||
1402 | m_log.InfoFormat("[MESH CACHE]: {0} Files in {1} cache folders, expired {2} files accessed before {3}", | ||
1403 | totalfiles,ndirs, ndeleted, OlderTime.ToString()); | ||
1404 | } | ||
1405 | else | ||
1406 | { | ||
1407 | m_log.Info("[MESH CACHE]: Expire delayed to next startup"); | ||
1408 | FileStream fs = File.Create(controlfile,4096,FileOptions.WriteThrough); | ||
1409 | fs.Close(); | ||
1410 | } | ||
1411 | } | ||
1412 | catch { } | ||
1413 | } | ||
1414 | } | ||
1186 | } | 1415 | } |
1187 | } | 1416 | } |
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs index c363310..f5bf05d 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs | |||
@@ -172,7 +172,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
172 | // force lower density for testing | 172 | // force lower density for testing |
173 | m_density = 3.0f; | 173 | m_density = 3.0f; |
174 | 174 | ||
175 | |||
176 | mu = parent_scene.AvatarFriction; | 175 | mu = parent_scene.AvatarFriction; |
177 | 176 | ||
178 | walkDivisor = walk_divisor; | 177 | walkDivisor = walk_divisor; |
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs new file mode 100644 index 0000000..73dd2fd --- /dev/null +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs | |||
@@ -0,0 +1,931 @@ | |||
1 | /* | ||
2 | * AJLDuarte 2012 | ||
3 | */ | ||
4 | |||
5 | using System; | ||
6 | using System.Threading; | ||
7 | using System.Collections.Generic; | ||
8 | using System.IO; | ||
9 | using System.Reflection; | ||
10 | using System.Runtime.InteropServices; | ||
11 | using System.Text; | ||
12 | using OpenSim.Framework; | ||
13 | using OpenSim.Region.Physics.Manager; | ||
14 | using OdeAPI; | ||
15 | using log4net; | ||
16 | using Nini.Config; | ||
17 | using OpenMetaverse; | ||
18 | |||
19 | namespace OpenSim.Region.Physics.OdePlugin | ||
20 | { | ||
21 | public enum MeshState : byte | ||
22 | { | ||
23 | noNeed = 0, | ||
24 | |||
25 | loadingAsset = 1, | ||
26 | |||
27 | AssetOK = 0x0f, // 00001111 | ||
28 | |||
29 | NeedMask = 0x30, // 00110000 | ||
30 | needMesh = 0x10, // 00010000 | ||
31 | needAsset = 0x20, // 00100000 | ||
32 | |||
33 | FailMask = 0xC0, // 11000000 | ||
34 | AssetFailed = 0x40, // 01000000 | ||
35 | MeshFailed = 0x80, // 10000000 | ||
36 | |||
37 | MeshNoColide = FailMask | needAsset | ||
38 | } | ||
39 | |||
40 | public enum meshWorkerCmnds : byte | ||
41 | { | ||
42 | nop = 0, | ||
43 | addnew, | ||
44 | changefull, | ||
45 | changesize, | ||
46 | changeshapetype, | ||
47 | getmesh, | ||
48 | } | ||
49 | |||
50 | public class ODEPhysRepData | ||
51 | { | ||
52 | public PhysicsActor actor; | ||
53 | public PrimitiveBaseShape pbs; | ||
54 | public IMesh mesh; | ||
55 | |||
56 | public Vector3 size; | ||
57 | public Vector3 OBB; | ||
58 | public Vector3 OBBOffset; | ||
59 | |||
60 | public float volume; | ||
61 | |||
62 | public byte shapetype; | ||
63 | public bool hasOBB; | ||
64 | public bool hasMeshVolume; | ||
65 | public MeshState meshState; | ||
66 | public UUID? assetID; | ||
67 | public meshWorkerCmnds comand; | ||
68 | } | ||
69 | |||
70 | public class ODEMeshWorker | ||
71 | { | ||
72 | |||
73 | private ILog m_log; | ||
74 | private OdeScene m_scene; | ||
75 | private IMesher m_mesher; | ||
76 | |||
77 | public bool meshSculptedPrim = true; | ||
78 | public bool forceSimplePrimMeshing = false; | ||
79 | public float meshSculptLOD = 32; | ||
80 | public float MeshSculptphysicalLOD = 32; | ||
81 | |||
82 | |||
83 | private OpenSim.Framework.BlockingQueue<ODEPhysRepData> createqueue = new OpenSim.Framework.BlockingQueue<ODEPhysRepData>(); | ||
84 | private bool m_running; | ||
85 | |||
86 | private Thread m_thread; | ||
87 | |||
88 | public ODEMeshWorker(OdeScene pScene, ILog pLog, IMesher pMesher, IConfig pConfig) | ||
89 | { | ||
90 | m_scene = pScene; | ||
91 | m_log = pLog; | ||
92 | m_mesher = pMesher; | ||
93 | |||
94 | if (pConfig != null) | ||
95 | { | ||
96 | forceSimplePrimMeshing = pConfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing); | ||
97 | meshSculptedPrim = pConfig.GetBoolean("mesh_sculpted_prim", meshSculptedPrim); | ||
98 | meshSculptLOD = pConfig.GetFloat("mesh_lod", meshSculptLOD); | ||
99 | MeshSculptphysicalLOD = pConfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD); | ||
100 | } | ||
101 | m_running = true; | ||
102 | m_thread = new Thread(DoWork); | ||
103 | m_thread.Start(); | ||
104 | } | ||
105 | |||
106 | private void DoWork() | ||
107 | { | ||
108 | m_mesher.ExpireFileCache(); | ||
109 | |||
110 | while(m_running) | ||
111 | { | ||
112 | ODEPhysRepData nextRep = createqueue.Dequeue(); | ||
113 | if(!m_running) | ||
114 | return; | ||
115 | if (nextRep == null) | ||
116 | continue; | ||
117 | if (m_scene.haveActor(nextRep.actor)) | ||
118 | { | ||
119 | switch (nextRep.comand) | ||
120 | { | ||
121 | case meshWorkerCmnds.changefull: | ||
122 | case meshWorkerCmnds.changeshapetype: | ||
123 | case meshWorkerCmnds.changesize: | ||
124 | GetMesh(nextRep); | ||
125 | if (CreateActorPhysRep(nextRep) && m_scene.haveActor(nextRep.actor)) | ||
126 | m_scene.AddChange(nextRep.actor, changes.PhysRepData, nextRep); | ||
127 | break; | ||
128 | case meshWorkerCmnds.getmesh: | ||
129 | DoRepDataGetMesh(nextRep); | ||
130 | break; | ||
131 | } | ||
132 | } | ||
133 | } | ||
134 | } | ||
135 | |||
136 | public void Stop() | ||
137 | { | ||
138 | try | ||
139 | { | ||
140 | m_thread.Abort(); | ||
141 | createqueue.Clear(); | ||
142 | } | ||
143 | catch | ||
144 | { | ||
145 | } | ||
146 | } | ||
147 | |||
148 | public void ChangeActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs, | ||
149 | Vector3 size, byte shapetype) | ||
150 | { | ||
151 | ODEPhysRepData repData = new ODEPhysRepData(); | ||
152 | repData.actor = actor; | ||
153 | repData.pbs = pbs; | ||
154 | repData.size = size; | ||
155 | repData.shapetype = shapetype; | ||
156 | |||
157 | CheckMesh(repData); | ||
158 | CalcVolumeData(repData); | ||
159 | m_scene.AddChange(actor, changes.PhysRepData, repData); | ||
160 | return; | ||
161 | } | ||
162 | |||
163 | public ODEPhysRepData NewActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs, | ||
164 | Vector3 size, byte shapetype) | ||
165 | { | ||
166 | ODEPhysRepData repData = new ODEPhysRepData(); | ||
167 | repData.actor = actor; | ||
168 | repData.pbs = pbs; | ||
169 | repData.size = size; | ||
170 | repData.shapetype = shapetype; | ||
171 | |||
172 | CheckMesh(repData); | ||
173 | CalcVolumeData(repData); | ||
174 | m_scene.AddChange(actor, changes.AddPhysRep, repData); | ||
175 | return repData; | ||
176 | } | ||
177 | |||
178 | public void RequestMesh(ODEPhysRepData repData) | ||
179 | { | ||
180 | repData.mesh = null; | ||
181 | |||
182 | if (repData.meshState == MeshState.needAsset) | ||
183 | { | ||
184 | PrimitiveBaseShape pbs = repData.pbs; | ||
185 | |||
186 | // check if we got outdated | ||
187 | |||
188 | if (!pbs.SculptEntry || pbs.SculptTexture == UUID.Zero) | ||
189 | { | ||
190 | repData.meshState = MeshState.noNeed; | ||
191 | return; | ||
192 | } | ||
193 | |||
194 | repData.assetID = pbs.SculptTexture; | ||
195 | repData.meshState = MeshState.loadingAsset; | ||
196 | |||
197 | repData.comand = meshWorkerCmnds.getmesh; | ||
198 | createqueue.Enqueue(repData); | ||
199 | } | ||
200 | } | ||
201 | |||
202 | // creates and prepares a mesh to use and calls parameters estimation | ||
203 | public bool CreateActorPhysRep(ODEPhysRepData repData) | ||
204 | { | ||
205 | IMesh mesh = repData.mesh; | ||
206 | |||
207 | if (mesh != null) | ||
208 | { | ||
209 | IntPtr vertices, indices; | ||
210 | int vertexCount, indexCount; | ||
211 | int vertexStride, triStride; | ||
212 | |||
213 | mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); | ||
214 | mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); | ||
215 | |||
216 | if (vertexCount == 0 || indexCount == 0) | ||
217 | { | ||
218 | m_log.WarnFormat("[PHYSICS]: Invalid mesh data on prim {0} mesh UUID {1}", | ||
219 | repData.actor.Name, repData.pbs.SculptTexture.ToString()); | ||
220 | repData.meshState = MeshState.MeshFailed; | ||
221 | repData.hasOBB = false; | ||
222 | repData.mesh = null; | ||
223 | m_scene.mesher.ReleaseMesh(mesh); | ||
224 | } | ||
225 | else | ||
226 | { | ||
227 | repData.OBBOffset = mesh.GetCentroid(); | ||
228 | repData.OBB = mesh.GetOBB(); | ||
229 | repData.hasOBB = true; | ||
230 | mesh.releaseSourceMeshData(); | ||
231 | } | ||
232 | } | ||
233 | CalcVolumeData(repData); | ||
234 | return true; | ||
235 | } | ||
236 | |||
237 | public void AssetLoaded(ODEPhysRepData repData) | ||
238 | { | ||
239 | if (m_scene.haveActor(repData.actor)) | ||
240 | { | ||
241 | if (needsMeshing(repData.pbs)) // no need for pbs now? | ||
242 | { | ||
243 | repData.comand = meshWorkerCmnds.changefull; | ||
244 | createqueue.Enqueue(repData); | ||
245 | } | ||
246 | } | ||
247 | else | ||
248 | repData.pbs.SculptData = Utils.EmptyBytes; | ||
249 | } | ||
250 | |||
251 | public void DoRepDataGetMesh(ODEPhysRepData repData) | ||
252 | { | ||
253 | if (!repData.pbs.SculptEntry) | ||
254 | return; | ||
255 | |||
256 | if (repData.meshState != MeshState.loadingAsset) | ||
257 | return; | ||
258 | |||
259 | if (repData.assetID == null || repData.assetID == UUID.Zero) | ||
260 | return; | ||
261 | |||
262 | if (repData.assetID != repData.pbs.SculptTexture) | ||
263 | return; | ||
264 | |||
265 | // check if it is in cache | ||
266 | GetMesh(repData); | ||
267 | if (repData.meshState != MeshState.needAsset) | ||
268 | { | ||
269 | CreateActorPhysRep(repData); | ||
270 | m_scene.AddChange(repData.actor, changes.PhysRepData, repData); | ||
271 | return; | ||
272 | } | ||
273 | |||
274 | RequestAssetDelegate assetProvider = m_scene.RequestAssetMethod; | ||
275 | if (assetProvider == null) | ||
276 | return; | ||
277 | ODEAssetRequest asr = new ODEAssetRequest(this, assetProvider, repData, m_log); | ||
278 | } | ||
279 | |||
280 | |||
281 | /// <summary> | ||
282 | /// Routine to figure out if we need to mesh this prim with our mesher | ||
283 | /// </summary> | ||
284 | /// <param name="pbs"></param> | ||
285 | /// <returns></returns> | ||
286 | public bool needsMeshing(PrimitiveBaseShape pbs) | ||
287 | { | ||
288 | // check sculpts or meshs | ||
289 | if (pbs.SculptEntry) | ||
290 | { | ||
291 | if (meshSculptedPrim) | ||
292 | return true; | ||
293 | |||
294 | if (pbs.SculptType == (byte)SculptType.Mesh) // always do meshs | ||
295 | return true; | ||
296 | |||
297 | return false; | ||
298 | } | ||
299 | |||
300 | if (forceSimplePrimMeshing) | ||
301 | return true; | ||
302 | |||
303 | // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim | ||
304 | |||
305 | if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) | ||
306 | || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 | ||
307 | && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)) | ||
308 | { | ||
309 | |||
310 | if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 | ||
311 | && pbs.ProfileHollow == 0 | ||
312 | && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 | ||
313 | && pbs.PathBegin == 0 && pbs.PathEnd == 0 | ||
314 | && pbs.PathTaperX == 0 && pbs.PathTaperY == 0 | ||
315 | && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 | ||
316 | && pbs.PathShearX == 0 && pbs.PathShearY == 0) | ||
317 | { | ||
318 | return false; | ||
319 | } | ||
320 | } | ||
321 | |||
322 | // following code doesn't give meshs to boxes and spheres ever | ||
323 | // and it's odd.. so for now just return true if asked to force meshs | ||
324 | // hopefully mesher will fail if doesn't suport so things still get basic boxes | ||
325 | |||
326 | int iPropertiesNotSupportedDefault = 0; | ||
327 | |||
328 | if (pbs.ProfileHollow != 0) | ||
329 | iPropertiesNotSupportedDefault++; | ||
330 | |||
331 | if ((pbs.PathBegin != 0) || pbs.PathEnd != 0) | ||
332 | iPropertiesNotSupportedDefault++; | ||
333 | |||
334 | if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0)) | ||
335 | iPropertiesNotSupportedDefault++; | ||
336 | |||
337 | if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0) | ||
338 | iPropertiesNotSupportedDefault++; | ||
339 | |||
340 | if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100)) | ||
341 | iPropertiesNotSupportedDefault++; | ||
342 | |||
343 | if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0)) | ||
344 | iPropertiesNotSupportedDefault++; | ||
345 | |||
346 | if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight) | ||
347 | iPropertiesNotSupportedDefault++; | ||
348 | |||
349 | if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X)) | ||
350 | iPropertiesNotSupportedDefault++; | ||
351 | |||
352 | if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) | ||
353 | iPropertiesNotSupportedDefault++; | ||
354 | |||
355 | // test for torus | ||
356 | if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square) | ||
357 | { | ||
358 | if (pbs.PathCurve == (byte)Extrusion.Curve1) | ||
359 | { | ||
360 | iPropertiesNotSupportedDefault++; | ||
361 | } | ||
362 | } | ||
363 | else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) | ||
364 | { | ||
365 | if (pbs.PathCurve == (byte)Extrusion.Straight) | ||
366 | { | ||
367 | iPropertiesNotSupportedDefault++; | ||
368 | } | ||
369 | |||
370 | // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits | ||
371 | else if (pbs.PathCurve == (byte)Extrusion.Curve1) | ||
372 | { | ||
373 | iPropertiesNotSupportedDefault++; | ||
374 | } | ||
375 | } | ||
376 | else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) | ||
377 | { | ||
378 | if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2) | ||
379 | { | ||
380 | iPropertiesNotSupportedDefault++; | ||
381 | } | ||
382 | } | ||
383 | else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) | ||
384 | { | ||
385 | if (pbs.PathCurve == (byte)Extrusion.Straight) | ||
386 | { | ||
387 | iPropertiesNotSupportedDefault++; | ||
388 | } | ||
389 | else if (pbs.PathCurve == (byte)Extrusion.Curve1) | ||
390 | { | ||
391 | iPropertiesNotSupportedDefault++; | ||
392 | } | ||
393 | } | ||
394 | |||
395 | if (iPropertiesNotSupportedDefault == 0) | ||
396 | { | ||
397 | return false; | ||
398 | } | ||
399 | return true; | ||
400 | } | ||
401 | |||
402 | // see if we need a mesh and if so if we have a cached one | ||
403 | // called with a new repData | ||
404 | public void CheckMesh(ODEPhysRepData repData) | ||
405 | { | ||
406 | PhysicsActor actor = repData.actor; | ||
407 | PrimitiveBaseShape pbs = repData.pbs; | ||
408 | |||
409 | if (!needsMeshing(pbs)) | ||
410 | { | ||
411 | repData.meshState = MeshState.noNeed; | ||
412 | return; | ||
413 | } | ||
414 | |||
415 | IMesh mesh = null; | ||
416 | |||
417 | Vector3 size = repData.size; | ||
418 | byte shapetype = repData.shapetype; | ||
419 | |||
420 | bool convex; | ||
421 | |||
422 | int clod = (int)LevelOfDetail.High; | ||
423 | if (shapetype == 0) | ||
424 | convex = false; | ||
425 | else | ||
426 | { | ||
427 | convex = true; | ||
428 | if (pbs.SculptType != (byte)SculptType.Mesh) | ||
429 | clod = (int)LevelOfDetail.Low; | ||
430 | } | ||
431 | |||
432 | mesh = m_mesher.GetMesh(actor.Name, pbs, size, clod, true, convex); | ||
433 | |||
434 | if (mesh == null) | ||
435 | { | ||
436 | if (pbs.SculptEntry) | ||
437 | { | ||
438 | if (pbs.SculptTexture != null && pbs.SculptTexture != UUID.Zero) | ||
439 | { | ||
440 | repData.assetID = pbs.SculptTexture; | ||
441 | repData.meshState = MeshState.needAsset; | ||
442 | } | ||
443 | else | ||
444 | repData.meshState = MeshState.MeshFailed; | ||
445 | |||
446 | return; | ||
447 | } | ||
448 | else | ||
449 | { | ||
450 | repData.meshState = MeshState.needMesh; | ||
451 | mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true); | ||
452 | if (mesh == null) | ||
453 | { | ||
454 | repData.meshState = MeshState.MeshFailed; | ||
455 | return; | ||
456 | } | ||
457 | } | ||
458 | } | ||
459 | |||
460 | repData.meshState = MeshState.AssetOK; | ||
461 | repData.mesh = mesh; | ||
462 | |||
463 | if (pbs.SculptEntry) | ||
464 | { | ||
465 | repData.assetID = pbs.SculptTexture; | ||
466 | } | ||
467 | |||
468 | pbs.SculptData = Utils.EmptyBytes; | ||
469 | return ; | ||
470 | } | ||
471 | |||
472 | public void GetMesh(ODEPhysRepData repData) | ||
473 | { | ||
474 | PhysicsActor actor = repData.actor; | ||
475 | |||
476 | PrimitiveBaseShape pbs = repData.pbs; | ||
477 | |||
478 | repData.mesh = null; | ||
479 | repData.hasOBB = false; | ||
480 | |||
481 | if (!needsMeshing(pbs)) | ||
482 | { | ||
483 | repData.meshState = MeshState.noNeed; | ||
484 | return; | ||
485 | } | ||
486 | |||
487 | if (repData.meshState == MeshState.MeshFailed) | ||
488 | return; | ||
489 | |||
490 | if (pbs.SculptEntry) | ||
491 | { | ||
492 | if (repData.meshState == MeshState.AssetFailed) | ||
493 | { | ||
494 | if (pbs.SculptTexture == repData.assetID) | ||
495 | return; | ||
496 | } | ||
497 | } | ||
498 | |||
499 | repData.meshState = MeshState.noNeed; | ||
500 | |||
501 | IMesh mesh = null; | ||
502 | Vector3 size = repData.size; | ||
503 | byte shapetype = repData.shapetype; | ||
504 | |||
505 | bool convex; | ||
506 | int clod = (int)LevelOfDetail.High; | ||
507 | if (shapetype == 0) | ||
508 | convex = false; | ||
509 | else | ||
510 | { | ||
511 | convex = true; | ||
512 | if (pbs.SculptType != (byte)SculptType.Mesh) | ||
513 | clod = (int)LevelOfDetail.Low; | ||
514 | } | ||
515 | |||
516 | mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true); | ||
517 | |||
518 | if (mesh == null) | ||
519 | { | ||
520 | if (pbs.SculptEntry) | ||
521 | { | ||
522 | if (pbs.SculptTexture == UUID.Zero) | ||
523 | return; | ||
524 | |||
525 | repData.assetID = pbs.SculptTexture; | ||
526 | |||
527 | if (pbs.SculptData == null || pbs.SculptData.Length == 0) | ||
528 | { | ||
529 | repData.meshState = MeshState.needAsset; | ||
530 | return; | ||
531 | } | ||
532 | } | ||
533 | } | ||
534 | |||
535 | repData.mesh = mesh; | ||
536 | repData.pbs.SculptData = Utils.EmptyBytes; | ||
537 | |||
538 | if (mesh == null) | ||
539 | { | ||
540 | if (pbs.SculptEntry) | ||
541 | repData.meshState = MeshState.AssetFailed; | ||
542 | else | ||
543 | repData.meshState = MeshState.MeshFailed; | ||
544 | |||
545 | return; | ||
546 | } | ||
547 | |||
548 | repData.meshState = MeshState.AssetOK; | ||
549 | |||
550 | return; | ||
551 | } | ||
552 | |||
553 | private void CalculateBasicPrimVolume(ODEPhysRepData repData) | ||
554 | { | ||
555 | PrimitiveBaseShape _pbs = repData.pbs; | ||
556 | Vector3 _size = repData.size; | ||
557 | |||
558 | float volume = _size.X * _size.Y * _size.Z; // default | ||
559 | float tmp; | ||
560 | |||
561 | float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f; | ||
562 | float hollowVolume = hollowAmount * hollowAmount; | ||
563 | |||
564 | switch (_pbs.ProfileShape) | ||
565 | { | ||
566 | case ProfileShape.Square: | ||
567 | // default box | ||
568 | |||
569 | if (_pbs.PathCurve == (byte)Extrusion.Straight) | ||
570 | { | ||
571 | if (hollowAmount > 0.0) | ||
572 | { | ||
573 | switch (_pbs.HollowShape) | ||
574 | { | ||
575 | case HollowShape.Square: | ||
576 | case HollowShape.Same: | ||
577 | break; | ||
578 | |||
579 | case HollowShape.Circle: | ||
580 | |||
581 | hollowVolume *= 0.78539816339f; | ||
582 | break; | ||
583 | |||
584 | case HollowShape.Triangle: | ||
585 | |||
586 | hollowVolume *= (0.5f * .5f); | ||
587 | break; | ||
588 | |||
589 | default: | ||
590 | hollowVolume = 0; | ||
591 | break; | ||
592 | } | ||
593 | volume *= (1.0f - hollowVolume); | ||
594 | } | ||
595 | } | ||
596 | |||
597 | else if (_pbs.PathCurve == (byte)Extrusion.Curve1) | ||
598 | { | ||
599 | //a tube | ||
600 | |||
601 | volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX); | ||
602 | tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY); | ||
603 | volume -= volume * tmp * tmp; | ||
604 | |||
605 | if (hollowAmount > 0.0) | ||
606 | { | ||
607 | hollowVolume *= hollowAmount; | ||
608 | |||
609 | switch (_pbs.HollowShape) | ||
610 | { | ||
611 | case HollowShape.Square: | ||
612 | case HollowShape.Same: | ||
613 | break; | ||
614 | |||
615 | case HollowShape.Circle: | ||
616 | hollowVolume *= 0.78539816339f; | ||
617 | break; | ||
618 | |||
619 | case HollowShape.Triangle: | ||
620 | hollowVolume *= 0.5f * 0.5f; | ||
621 | break; | ||
622 | default: | ||
623 | hollowVolume = 0; | ||
624 | break; | ||
625 | } | ||
626 | volume *= (1.0f - hollowVolume); | ||
627 | } | ||
628 | } | ||
629 | |||
630 | break; | ||
631 | |||
632 | case ProfileShape.Circle: | ||
633 | |||
634 | if (_pbs.PathCurve == (byte)Extrusion.Straight) | ||
635 | { | ||
636 | volume *= 0.78539816339f; // elipse base | ||
637 | |||
638 | if (hollowAmount > 0.0) | ||
639 | { | ||
640 | switch (_pbs.HollowShape) | ||
641 | { | ||
642 | case HollowShape.Same: | ||
643 | case HollowShape.Circle: | ||
644 | break; | ||
645 | |||
646 | case HollowShape.Square: | ||
647 | hollowVolume *= 0.5f * 2.5984480504799f; | ||
648 | break; | ||
649 | |||
650 | case HollowShape.Triangle: | ||
651 | hollowVolume *= .5f * 1.27323954473516f; | ||
652 | break; | ||
653 | |||
654 | default: | ||
655 | hollowVolume = 0; | ||
656 | break; | ||
657 | } | ||
658 | volume *= (1.0f - hollowVolume); | ||
659 | } | ||
660 | } | ||
661 | |||
662 | else if (_pbs.PathCurve == (byte)Extrusion.Curve1) | ||
663 | { | ||
664 | volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX); | ||
665 | tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); | ||
666 | volume *= (1.0f - tmp * tmp); | ||
667 | |||
668 | if (hollowAmount > 0.0) | ||
669 | { | ||
670 | |||
671 | // calculate the hollow volume by it's shape compared to the prim shape | ||
672 | hollowVolume *= hollowAmount; | ||
673 | |||
674 | switch (_pbs.HollowShape) | ||
675 | { | ||
676 | case HollowShape.Same: | ||
677 | case HollowShape.Circle: | ||
678 | break; | ||
679 | |||
680 | case HollowShape.Square: | ||
681 | hollowVolume *= 0.5f * 2.5984480504799f; | ||
682 | break; | ||
683 | |||
684 | case HollowShape.Triangle: | ||
685 | hollowVolume *= .5f * 1.27323954473516f; | ||
686 | break; | ||
687 | |||
688 | default: | ||
689 | hollowVolume = 0; | ||
690 | break; | ||
691 | } | ||
692 | volume *= (1.0f - hollowVolume); | ||
693 | } | ||
694 | } | ||
695 | break; | ||
696 | |||
697 | case ProfileShape.HalfCircle: | ||
698 | if (_pbs.PathCurve == (byte)Extrusion.Curve1) | ||
699 | { | ||
700 | volume *= 0.5236f; | ||
701 | |||
702 | if (hollowAmount > 0.0) | ||
703 | { | ||
704 | hollowVolume *= hollowAmount; | ||
705 | |||
706 | switch (_pbs.HollowShape) | ||
707 | { | ||
708 | case HollowShape.Circle: | ||
709 | case HollowShape.Triangle: // diference in sl is minor and odd | ||
710 | case HollowShape.Same: | ||
711 | break; | ||
712 | |||
713 | case HollowShape.Square: | ||
714 | hollowVolume *= 0.909f; | ||
715 | break; | ||
716 | |||
717 | // case HollowShape.Triangle: | ||
718 | // hollowVolume *= .827f; | ||
719 | // break; | ||
720 | default: | ||
721 | hollowVolume = 0; | ||
722 | break; | ||
723 | } | ||
724 | volume *= (1.0f - hollowVolume); | ||
725 | } | ||
726 | |||
727 | } | ||
728 | break; | ||
729 | |||
730 | case ProfileShape.EquilateralTriangle: | ||
731 | |||
732 | if (_pbs.PathCurve == (byte)Extrusion.Straight) | ||
733 | { | ||
734 | volume *= 0.32475953f; | ||
735 | |||
736 | if (hollowAmount > 0.0) | ||
737 | { | ||
738 | |||
739 | // calculate the hollow volume by it's shape compared to the prim shape | ||
740 | switch (_pbs.HollowShape) | ||
741 | { | ||
742 | case HollowShape.Same: | ||
743 | case HollowShape.Triangle: | ||
744 | hollowVolume *= .25f; | ||
745 | break; | ||
746 | |||
747 | case HollowShape.Square: | ||
748 | hollowVolume *= 0.499849f * 3.07920140172638f; | ||
749 | break; | ||
750 | |||
751 | case HollowShape.Circle: | ||
752 | // Hollow shape is a perfect cyllinder in respect to the cube's scale | ||
753 | // Cyllinder hollow volume calculation | ||
754 | |||
755 | hollowVolume *= 0.1963495f * 3.07920140172638f; | ||
756 | break; | ||
757 | |||
758 | default: | ||
759 | hollowVolume = 0; | ||
760 | break; | ||
761 | } | ||
762 | volume *= (1.0f - hollowVolume); | ||
763 | } | ||
764 | } | ||
765 | else if (_pbs.PathCurve == (byte)Extrusion.Curve1) | ||
766 | { | ||
767 | volume *= 0.32475953f; | ||
768 | volume *= 0.01f * (float)(200 - _pbs.PathScaleX); | ||
769 | tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); | ||
770 | volume *= (1.0f - tmp * tmp); | ||
771 | |||
772 | if (hollowAmount > 0.0) | ||
773 | { | ||
774 | |||
775 | hollowVolume *= hollowAmount; | ||
776 | |||
777 | switch (_pbs.HollowShape) | ||
778 | { | ||
779 | case HollowShape.Same: | ||
780 | case HollowShape.Triangle: | ||
781 | hollowVolume *= .25f; | ||
782 | break; | ||
783 | |||
784 | case HollowShape.Square: | ||
785 | hollowVolume *= 0.499849f * 3.07920140172638f; | ||
786 | break; | ||
787 | |||
788 | case HollowShape.Circle: | ||
789 | |||
790 | hollowVolume *= 0.1963495f * 3.07920140172638f; | ||
791 | break; | ||
792 | |||
793 | default: | ||
794 | hollowVolume = 0; | ||
795 | break; | ||
796 | } | ||
797 | volume *= (1.0f - hollowVolume); | ||
798 | } | ||
799 | } | ||
800 | break; | ||
801 | |||
802 | default: | ||
803 | break; | ||
804 | } | ||
805 | |||
806 | float taperX1; | ||
807 | float taperY1; | ||
808 | float taperX; | ||
809 | float taperY; | ||
810 | float pathBegin; | ||
811 | float pathEnd; | ||
812 | float profileBegin; | ||
813 | float profileEnd; | ||
814 | |||
815 | if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible) | ||
816 | { | ||
817 | taperX1 = _pbs.PathScaleX * 0.01f; | ||
818 | if (taperX1 > 1.0f) | ||
819 | taperX1 = 2.0f - taperX1; | ||
820 | taperX = 1.0f - taperX1; | ||
821 | |||
822 | taperY1 = _pbs.PathScaleY * 0.01f; | ||
823 | if (taperY1 > 1.0f) | ||
824 | taperY1 = 2.0f - taperY1; | ||
825 | taperY = 1.0f - taperY1; | ||
826 | } | ||
827 | else | ||
828 | { | ||
829 | taperX = _pbs.PathTaperX * 0.01f; | ||
830 | if (taperX < 0.0f) | ||
831 | taperX = -taperX; | ||
832 | taperX1 = 1.0f - taperX; | ||
833 | |||
834 | taperY = _pbs.PathTaperY * 0.01f; | ||
835 | if (taperY < 0.0f) | ||
836 | taperY = -taperY; | ||
837 | taperY1 = 1.0f - taperY; | ||
838 | } | ||
839 | |||
840 | volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); | ||
841 | |||
842 | pathBegin = (float)_pbs.PathBegin * 2.0e-5f; | ||
843 | pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f; | ||
844 | volume *= (pathEnd - pathBegin); | ||
845 | |||
846 | // this is crude aproximation | ||
847 | profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f; | ||
848 | profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f; | ||
849 | volume *= (profileEnd - profileBegin); | ||
850 | |||
851 | repData.volume = volume; | ||
852 | } | ||
853 | |||
854 | private void CalcVolumeData(ODEPhysRepData repData) | ||
855 | { | ||
856 | if (repData.hasOBB) | ||
857 | { | ||
858 | Vector3 OBB = repData.OBB; | ||
859 | } | ||
860 | else | ||
861 | { | ||
862 | Vector3 OBB = repData.size; | ||
863 | OBB.X *= 0.5f; | ||
864 | OBB.Y *= 0.5f; | ||
865 | OBB.Z *= 0.5f; | ||
866 | |||
867 | repData.OBB = OBB; | ||
868 | repData.OBBOffset = Vector3.Zero; | ||
869 | } | ||
870 | |||
871 | CalculateBasicPrimVolume(repData); | ||
872 | } | ||
873 | } | ||
874 | |||
875 | public class ODEAssetRequest | ||
876 | { | ||
877 | ODEMeshWorker m_worker; | ||
878 | private ILog m_log; | ||
879 | ODEPhysRepData repData; | ||
880 | |||
881 | public ODEAssetRequest(ODEMeshWorker pWorker, RequestAssetDelegate provider, | ||
882 | ODEPhysRepData pRepData, ILog plog) | ||
883 | { | ||
884 | m_worker = pWorker; | ||
885 | m_log = plog; | ||
886 | repData = pRepData; | ||
887 | |||
888 | repData.meshState = MeshState.AssetFailed; | ||
889 | if (provider == null) | ||
890 | return; | ||
891 | |||
892 | if (repData.assetID == null) | ||
893 | return; | ||
894 | |||
895 | UUID assetID = (UUID) repData.assetID; | ||
896 | if (assetID == UUID.Zero) | ||
897 | return; | ||
898 | |||
899 | repData.meshState = MeshState.loadingAsset; | ||
900 | provider(assetID, ODEassetReceived); | ||
901 | } | ||
902 | |||
903 | void ODEassetReceived(AssetBase asset) | ||
904 | { | ||
905 | repData.meshState = MeshState.AssetFailed; | ||
906 | if (asset != null) | ||
907 | { | ||
908 | if (asset.Data != null && asset.Data.Length > 0) | ||
909 | { | ||
910 | repData.meshState = MeshState.noNeed; | ||
911 | |||
912 | if (!repData.pbs.SculptEntry) | ||
913 | return; | ||
914 | if (repData.pbs.SculptTexture != repData.assetID) | ||
915 | return; | ||
916 | |||
917 | repData.pbs.SculptData = new byte[asset.Data.Length]; | ||
918 | asset.Data.CopyTo(repData.pbs.SculptData,0); | ||
919 | repData.meshState = MeshState.AssetOK; | ||
920 | m_worker.AssetLoaded(repData); | ||
921 | } | ||
922 | else | ||
923 | m_log.WarnFormat("[PHYSICS]: asset provider returned invalid mesh data for prim {0} asset UUID {1}.", | ||
924 | repData.actor.Name, asset.ID.ToString()); | ||
925 | } | ||
926 | else | ||
927 | m_log.WarnFormat("[PHYSICS]: asset provider returned null asset fo mesh of prim {0}.", | ||
928 | repData.actor.Name); | ||
929 | } | ||
930 | } | ||
931 | } \ No newline at end of file | ||
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs index f2f4725..ce67cc4 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs | |||
@@ -79,7 +79,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
79 | private bool m_lastdoneSelected; | 79 | private bool m_lastdoneSelected; |
80 | internal bool m_outbounds; | 80 | internal bool m_outbounds; |
81 | 81 | ||
82 | private Quaternion m_lastorientation = new Quaternion(); | 82 | private Quaternion m_lastorientation; |
83 | private Quaternion _orientation; | 83 | private Quaternion _orientation; |
84 | 84 | ||
85 | private Vector3 _position; | 85 | private Vector3 _position; |
@@ -91,33 +91,30 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
91 | private Vector3 _size; | 91 | private Vector3 _size; |
92 | private Vector3 _acceleration; | 92 | private Vector3 _acceleration; |
93 | private Vector3 m_angularlock = Vector3.One; | 93 | private Vector3 m_angularlock = Vector3.One; |
94 | private IntPtr Amotor = IntPtr.Zero; | 94 | private IntPtr Amotor; |
95 | 95 | ||
96 | private Vector3 m_force; | 96 | private Vector3 m_force; |
97 | private Vector3 m_forceacc; | 97 | private Vector3 m_forceacc; |
98 | private Vector3 m_angularForceacc; | 98 | private Vector3 m_angularForceacc; |
99 | 99 | ||
100 | private float m_invTimeStep = 50.0f; | 100 | private float m_invTimeStep; |
101 | private float m_timeStep = .02f; | 101 | private float m_timeStep; |
102 | 102 | ||
103 | private Vector3 m_PIDTarget; | 103 | private Vector3 m_PIDTarget; |
104 | private float m_PIDTau; | 104 | private float m_PIDTau; |
105 | private bool m_usePID; | 105 | private bool m_usePID; |
106 | 106 | ||
107 | // KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau), | ||
108 | // and are for non-VEHICLES only. | ||
109 | |||
110 | private float m_PIDHoverHeight; | 107 | private float m_PIDHoverHeight; |
111 | private float m_PIDHoverTau; | 108 | private float m_PIDHoverTau; |
112 | private bool m_useHoverPID; | 109 | private bool m_useHoverPID; |
113 | private PIDHoverType m_PIDHoverType = PIDHoverType.Ground; | 110 | private PIDHoverType m_PIDHoverType; |
114 | private float m_targetHoverHeight; | 111 | private float m_targetHoverHeight; |
115 | private float m_groundHeight; | 112 | private float m_groundHeight; |
116 | private float m_waterHeight; | 113 | private float m_waterHeight; |
117 | private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle. | 114 | private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle. |
118 | 115 | ||
119 | private int body_autodisable_frames = 5; | 116 | private int body_autodisable_frames; |
120 | public int bodydisablecontrol = 0; | 117 | public int bodydisablecontrol; |
121 | 118 | ||
122 | 119 | ||
123 | // Default we're a Geometry | 120 | // Default we're a Geometry |
@@ -147,12 +144,16 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
147 | private IMesh m_mesh; | 144 | private IMesh m_mesh; |
148 | private object m_meshlock = new object(); | 145 | private object m_meshlock = new object(); |
149 | private PrimitiveBaseShape _pbs; | 146 | private PrimitiveBaseShape _pbs; |
147 | |||
148 | private UUID? m_assetID; | ||
149 | private MeshState m_meshState; | ||
150 | |||
150 | public OdeScene _parent_scene; | 151 | public OdeScene _parent_scene; |
151 | 152 | ||
152 | /// <summary> | 153 | /// <summary> |
153 | /// The physics space which contains prim geometry | 154 | /// The physics space which contains prim geometry |
154 | /// </summary> | 155 | /// </summary> |
155 | public IntPtr m_targetSpace = IntPtr.Zero; | 156 | public IntPtr m_targetSpace; |
156 | 157 | ||
157 | public IntPtr prim_geom; | 158 | public IntPtr prim_geom; |
158 | public IntPtr _triMeshData; | 159 | public IntPtr _triMeshData; |
@@ -166,27 +167,32 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
166 | 167 | ||
167 | public IntPtr collide_geom; // for objects: geom if single prim space it linkset | 168 | public IntPtr collide_geom; // for objects: geom if single prim space it linkset |
168 | 169 | ||
169 | private float m_density = 10.000006836f; // Aluminum g/cm3; | 170 | private float m_density; |
170 | private byte m_shapetype; | 171 | private byte m_shapetype; |
171 | public bool _zeroFlag; | 172 | public bool _zeroFlag; |
172 | private bool m_lastUpdateSent; | 173 | private bool m_lastUpdateSent; |
173 | 174 | ||
174 | public IntPtr Body = IntPtr.Zero; | 175 | public IntPtr Body; |
175 | 176 | ||
176 | private Vector3 _target_velocity; | 177 | private Vector3 _target_velocity; |
177 | 178 | ||
178 | public Vector3 primOOBsize; // prim real dimensions from mesh | 179 | public Vector3 m_OBBOffset; |
179 | public Vector3 primOOBoffset; // its centroid out of mesh or rest aabb | 180 | public Vector3 m_OBB; |
180 | public float primOOBradiusSQ; | 181 | public float primOOBradiusSQ; |
182 | |||
183 | private bool m_hasOBB = true; | ||
184 | |||
185 | private float m_physCost; | ||
186 | private float m_streamCost; | ||
187 | |||
181 | public d.Mass primdMass; // prim inertia information on it's own referencial | 188 | public d.Mass primdMass; // prim inertia information on it's own referencial |
182 | float primMass; // prim own mass | 189 | float primMass; // prim own mass |
183 | float primVolume; // prim own volume; | 190 | float primVolume; // prim own volume; |
184 | float _mass; // object mass acording to case | 191 | float _mass; // object mass acording to case |
185 | private bool hasOOBoffsetFromMesh = false; // if true we did compute it form mesh centroid, else from aabb | ||
186 | 192 | ||
187 | public int givefakepos = 0; | 193 | public int givefakepos; |
188 | private Vector3 fakepos; | 194 | private Vector3 fakepos; |
189 | public int givefakeori = 0; | 195 | public int givefakeori; |
190 | private Quaternion fakeori; | 196 | private Quaternion fakeori; |
191 | 197 | ||
192 | private int m_eventsubscription; | 198 | private int m_eventsubscription; |
@@ -271,7 +277,23 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
271 | cdata.mu *= veh.FrictionFactor; | 277 | cdata.mu *= veh.FrictionFactor; |
272 | // cdata.mu *= 0; | 278 | // cdata.mu *= 0; |
273 | } | 279 | } |
274 | } | 280 | } |
281 | |||
282 | public override float PhysicsCost | ||
283 | { | ||
284 | get | ||
285 | { | ||
286 | return m_physCost; | ||
287 | } | ||
288 | } | ||
289 | |||
290 | public override float StreamCost | ||
291 | { | ||
292 | get | ||
293 | { | ||
294 | return m_streamCost; | ||
295 | } | ||
296 | } | ||
275 | 297 | ||
276 | public override int PhysicsActorType | 298 | public override int PhysicsActorType |
277 | { | 299 | { |
@@ -394,7 +416,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
394 | { | 416 | { |
395 | if (value.IsFinite()) | 417 | if (value.IsFinite()) |
396 | { | 418 | { |
397 | AddChange(changes.Size, value); | 419 | _parent_scene.m_meshWorker.ChangeActorPhysRep(this, _pbs, value, m_shapetype); |
398 | } | 420 | } |
399 | else | 421 | else |
400 | { | 422 | { |
@@ -464,7 +486,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
464 | q.Z = dq.Z; | 486 | q.Z = dq.Z; |
465 | q.W = dq.W; | 487 | q.W = dq.W; |
466 | 488 | ||
467 | Vector3 Ptot = primOOBoffset * q; | 489 | Vector3 Ptot = m_OBBOffset * q; |
468 | dtmp = d.GeomGetPosition(prim_geom); | 490 | dtmp = d.GeomGetPosition(prim_geom); |
469 | Ptot.X += dtmp.X; | 491 | Ptot.X += dtmp.X; |
470 | Ptot.Y += dtmp.Y; | 492 | Ptot.Y += dtmp.Y; |
@@ -504,7 +526,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
504 | { | 526 | { |
505 | get | 527 | get |
506 | { | 528 | { |
507 | return primOOBsize; | 529 | return m_OBB; |
508 | } | 530 | } |
509 | } | 531 | } |
510 | 532 | ||
@@ -512,7 +534,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
512 | { | 534 | { |
513 | get | 535 | get |
514 | { | 536 | { |
515 | return primOOBoffset; | 537 | return m_OBBOffset; |
516 | } | 538 | } |
517 | } | 539 | } |
518 | 540 | ||
@@ -528,7 +550,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
528 | { | 550 | { |
529 | set | 551 | set |
530 | { | 552 | { |
531 | AddChange(changes.Shape, value); | 553 | // AddChange(changes.Shape, value); |
554 | _parent_scene.m_meshWorker.ChangeActorPhysRep(this, value, _size, m_shapetype); | ||
532 | } | 555 | } |
533 | } | 556 | } |
534 | 557 | ||
@@ -541,11 +564,10 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
541 | set | 564 | set |
542 | { | 565 | { |
543 | m_shapetype = value; | 566 | m_shapetype = value; |
544 | AddChange(changes.Shape, null); | 567 | _parent_scene.m_meshWorker.ChangeActorPhysRep(this, _pbs, _size, value); |
545 | } | 568 | } |
546 | } | 569 | } |
547 | 570 | ||
548 | |||
549 | public override Vector3 Velocity | 571 | public override Vector3 Velocity |
550 | { | 572 | { |
551 | get | 573 | get |
@@ -619,6 +641,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
619 | { | 641 | { |
620 | fakeori = value; | 642 | fakeori = value; |
621 | givefakeori++; | 643 | givefakeori++; |
644 | |||
645 | value.Normalize(); | ||
646 | |||
622 | AddChange(changes.Orientation, value); | 647 | AddChange(changes.Orientation, value); |
623 | } | 648 | } |
624 | else | 649 | else |
@@ -1012,7 +1037,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1012 | m_invTimeStep = 1f / m_timeStep; | 1037 | m_invTimeStep = 1f / m_timeStep; |
1013 | 1038 | ||
1014 | m_density = parent_scene.geomDefaultDensity; | 1039 | m_density = parent_scene.geomDefaultDensity; |
1015 | // m_tensor = parent_scene.bodyMotorJointMaxforceTensor; | ||
1016 | body_autodisable_frames = parent_scene.bodyFramesAutoDisable; | 1040 | body_autodisable_frames = parent_scene.bodyFramesAutoDisable; |
1017 | 1041 | ||
1018 | prim_geom = IntPtr.Zero; | 1042 | prim_geom = IntPtr.Zero; |
@@ -1064,7 +1088,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1064 | m_colliderfilter = 0; | 1088 | m_colliderfilter = 0; |
1065 | m_NoColide = false; | 1089 | m_NoColide = false; |
1066 | 1090 | ||
1067 | hasOOBoffsetFromMesh = false; | ||
1068 | _triMeshData = IntPtr.Zero; | 1091 | _triMeshData = IntPtr.Zero; |
1069 | 1092 | ||
1070 | m_shapetype = _shapeType; | 1093 | m_shapetype = _shapeType; |
@@ -1079,27 +1102,14 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1079 | mu = parent_scene.m_materialContactsData[(int)Material.Wood].mu; | 1102 | mu = parent_scene.m_materialContactsData[(int)Material.Wood].mu; |
1080 | bounce = parent_scene.m_materialContactsData[(int)Material.Wood].bounce; | 1103 | bounce = parent_scene.m_materialContactsData[(int)Material.Wood].bounce; |
1081 | 1104 | ||
1082 | CalcPrimBodyData(); | 1105 | m_building = true; // control must set this to false when done |
1083 | 1106 | ||
1084 | m_mesh = null; | 1107 | // get basic mass parameters |
1085 | if (_parent_scene.needsMeshing(pbs) && (pbs.SculptData.Length > 0)) | 1108 | ODEPhysRepData repData = _parent_scene.m_meshWorker.NewActorPhysRep(this, _pbs, _size, m_shapetype); |
1086 | { | ||
1087 | bool convex; | ||
1088 | int clod = (int)LevelOfDetail.High; | ||
1089 | if (m_shapetype == 0) | ||
1090 | convex = false; | ||
1091 | else | ||
1092 | { | ||
1093 | convex = true; | ||
1094 | if (_pbs.SculptType != (byte)SculptType.Mesh) | ||
1095 | clod = (int)LevelOfDetail.Low; | ||
1096 | } | ||
1097 | m_mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, clod, true, convex); | ||
1098 | } | ||
1099 | 1109 | ||
1100 | m_building = true; // control must set this to false when done | 1110 | primVolume = repData.volume; |
1101 | 1111 | ||
1102 | AddChange(changes.Add, null); | 1112 | UpdatePrimBodyData(); |
1103 | } | 1113 | } |
1104 | 1114 | ||
1105 | private void resetCollisionAccounting() | 1115 | private void resetCollisionAccounting() |
@@ -1323,76 +1333,88 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1323 | } | 1333 | } |
1324 | } | 1334 | } |
1325 | 1335 | ||
1326 | private bool setMesh(OdeScene parent_scene) | ||
1327 | { | ||
1328 | IntPtr vertices, indices; | ||
1329 | int vertexCount, indexCount; | ||
1330 | int vertexStride, triStride; | ||
1331 | 1336 | ||
1332 | if (Body != IntPtr.Zero) | 1337 | private void SetGeom(IntPtr geom) |
1338 | { | ||
1339 | prim_geom = geom; | ||
1340 | //Console.WriteLine("SetGeom to " + prim_geom + " for " + Name); | ||
1341 | if (prim_geom != IntPtr.Zero) | ||
1333 | { | 1342 | { |
1334 | if (childPrim) | 1343 | |
1344 | if (m_NoColide) | ||
1335 | { | 1345 | { |
1336 | if (_parent != null) | 1346 | d.GeomSetCategoryBits(prim_geom, 0); |
1347 | if (m_isphysical) | ||
1337 | { | 1348 | { |
1338 | OdePrim parent = (OdePrim)_parent; | 1349 | d.GeomSetCollideBits(prim_geom, (uint)CollisionCategories.Land); |
1339 | parent.ChildDelink(this, false); | 1350 | } |
1351 | else | ||
1352 | { | ||
1353 | d.GeomSetCollideBits(prim_geom, 0); | ||
1354 | d.GeomDisable(prim_geom); | ||
1340 | } | 1355 | } |
1341 | } | 1356 | } |
1342 | else | 1357 | else |
1343 | { | 1358 | { |
1344 | DestroyBody(); | 1359 | d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories); |
1360 | d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags); | ||
1345 | } | 1361 | } |
1346 | } | ||
1347 | 1362 | ||
1348 | IMesh mesh = null; | 1363 | UpdatePrimBodyData(); |
1364 | _parent_scene.actor_name_map[prim_geom] = this; | ||
1349 | 1365 | ||
1350 | lock (m_meshlock) | 1366 | /* |
1351 | { | 1367 | // debug |
1352 | if (m_mesh == null) | 1368 | d.AABB aabb; |
1353 | { | 1369 | d.GeomGetAABB(prim_geom, out aabb); |
1354 | bool convex; | 1370 | float x = aabb.MaxX - aabb.MinX; |
1355 | int clod = (int)LevelOfDetail.High; | 1371 | float y = aabb.MaxY - aabb.MinY; |
1372 | float z = aabb.MaxZ - aabb.MinZ; | ||
1373 | if( x > 60.0f || y > 60.0f || z > 60.0f) | ||
1374 | m_log.WarnFormat("[PHYSICS]: large prim geo {0},size {1}, AABBsize <{2},{3},{4}, mesh {5} at {6}", | ||
1375 | Name, _size.ToString(), x, y, z, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh", _position.ToString()); | ||
1376 | else if (x < 0.001f || y < 0.001f || z < 0.001f) | ||
1377 | m_log.WarnFormat("[PHYSICS]: small prim geo {0},size {1}, AABBsize <{2},{3},{4}, mesh {5} at {6}", | ||
1378 | Name, _size.ToString(), x, y, z, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh", _position.ToString()); | ||
1379 | |||
1380 | // | ||
1381 | */ | ||
1356 | 1382 | ||
1357 | if (m_shapetype == 0) | 1383 | } |
1358 | convex = false; | 1384 | else |
1359 | else | 1385 | m_log.Warn("Setting bad Geom"); |
1360 | { | 1386 | } |
1361 | convex = true; | ||
1362 | if (_pbs.SculptType != (byte)SculptType.Mesh) | ||
1363 | clod = (int)LevelOfDetail.Low; | ||
1364 | } | ||
1365 | 1387 | ||
1366 | mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, clod, true, convex); | 1388 | private bool GetMeshGeom() |
1367 | } | 1389 | { |
1368 | else | 1390 | IntPtr vertices, indices; |
1369 | { | 1391 | int vertexCount, indexCount; |
1370 | mesh = m_mesh; | 1392 | int vertexStride, triStride; |
1371 | } | 1393 | |
1394 | IMesh mesh = m_mesh; | ||
1372 | 1395 | ||
1373 | if (mesh == null) | 1396 | if (mesh == null) |
1374 | { | 1397 | return false; |
1375 | m_log.WarnFormat("[PHYSICS]: CreateMesh Failed on prim {0} at <{1},{2},{3}>.", Name, _position.X, _position.Y, _position.Z); | ||
1376 | return false; | ||
1377 | } | ||
1378 | 1398 | ||
1399 | mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); | ||
1400 | mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); | ||
1379 | 1401 | ||
1380 | mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap | 1402 | if (vertexCount == 0 || indexCount == 0) |
1381 | mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage | 1403 | { |
1404 | m_log.WarnFormat("[PHYSICS]: Invalid mesh data on OdePrim {0}, mesh {1}", | ||
1405 | Name, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh"); | ||
1382 | 1406 | ||
1383 | if (vertexCount == 0 || indexCount == 0) | 1407 | m_hasOBB = false; |
1384 | { | 1408 | m_OBBOffset = Vector3.Zero; |
1385 | m_log.WarnFormat("[PHYSICS]: Got invalid mesh on prim {0} at <{1},{2},{3}>. mesh UUID {4}", | 1409 | m_OBB = _size * 0.5f; |
1386 | Name, _position.X, _position.Y, _position.Z, _pbs.SculptTexture.ToString()); | ||
1387 | mesh.releaseSourceMeshData(); | ||
1388 | return false; | ||
1389 | } | ||
1390 | 1410 | ||
1391 | primOOBoffset = mesh.GetCentroid(); | 1411 | m_physCost = 0.1f; |
1392 | hasOOBoffsetFromMesh = true; | 1412 | m_streamCost = 1.0f; |
1393 | 1413 | ||
1394 | mesh.releaseSourceMeshData(); | 1414 | _parent_scene.mesher.ReleaseMesh(mesh); |
1395 | m_mesh = mesh; | 1415 | m_meshState = MeshState.MeshFailed; |
1416 | m_mesh = null; | ||
1417 | return false; | ||
1396 | } | 1418 | } |
1397 | 1419 | ||
1398 | IntPtr geo = IntPtr.Zero; | 1420 | IntPtr geo = IntPtr.Zero; |
@@ -1404,7 +1426,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1404 | d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride); | 1426 | d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride); |
1405 | d.GeomTriMeshDataPreprocess(_triMeshData); | 1427 | d.GeomTriMeshDataPreprocess(_triMeshData); |
1406 | 1428 | ||
1407 | _parent_scene.waitForSpaceUnlock(m_targetSpace); | ||
1408 | geo = d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null); | 1429 | geo = d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null); |
1409 | } | 1430 | } |
1410 | 1431 | ||
@@ -1413,85 +1434,65 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1413 | m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", Name, e); | 1434 | m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", Name, e); |
1414 | if (_triMeshData != IntPtr.Zero) | 1435 | if (_triMeshData != IntPtr.Zero) |
1415 | { | 1436 | { |
1416 | d.GeomTriMeshDataDestroy(_triMeshData); | 1437 | try |
1417 | _triMeshData = IntPtr.Zero; | ||
1418 | } | ||
1419 | return false; | ||
1420 | } | ||
1421 | |||
1422 | SetGeom(geo); | ||
1423 | return true; | ||
1424 | } | ||
1425 | |||
1426 | private void SetGeom(IntPtr geom) | ||
1427 | { | ||
1428 | prim_geom = geom; | ||
1429 | //Console.WriteLine("SetGeom to " + prim_geom + " for " + Name); | ||
1430 | if (prim_geom != IntPtr.Zero) | ||
1431 | { | ||
1432 | |||
1433 | if (m_NoColide) | ||
1434 | { | ||
1435 | d.GeomSetCategoryBits(prim_geom, 0); | ||
1436 | if (m_isphysical) | ||
1437 | { | 1438 | { |
1438 | d.GeomSetCollideBits(prim_geom, (uint)CollisionCategories.Land); | 1439 | d.GeomTriMeshDataDestroy(_triMeshData); |
1439 | } | 1440 | } |
1440 | else | 1441 | catch |
1441 | { | 1442 | { |
1442 | d.GeomSetCollideBits(prim_geom, 0); | ||
1443 | d.GeomDisable(prim_geom); | ||
1444 | } | 1443 | } |
1445 | } | 1444 | } |
1446 | else | 1445 | _triMeshData = IntPtr.Zero; |
1447 | { | ||
1448 | d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories); | ||
1449 | d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags); | ||
1450 | } | ||
1451 | 1446 | ||
1452 | CalcPrimBodyData(); | 1447 | m_hasOBB = false; |
1448 | m_OBBOffset = Vector3.Zero; | ||
1449 | m_OBB = _size * 0.5f; | ||
1450 | m_physCost = 0.1f; | ||
1451 | m_streamCost = 1.0f; | ||
1452 | |||
1453 | _parent_scene.mesher.ReleaseMesh(mesh); | ||
1454 | m_meshState = MeshState.MeshFailed; | ||
1455 | m_mesh = null; | ||
1456 | return false; | ||
1457 | } | ||
1453 | 1458 | ||
1454 | _parent_scene.actor_name_map[prim_geom] = this; | 1459 | m_physCost = 0.0013f * (float)indexCount; |
1460 | // todo | ||
1461 | m_streamCost = 1.0f; | ||
1455 | 1462 | ||
1456 | } | 1463 | SetGeom(geo); |
1457 | else | ||
1458 | m_log.Warn("Setting bad Geom"); | ||
1459 | } | ||
1460 | 1464 | ||
1465 | return true; | ||
1466 | } | ||
1461 | 1467 | ||
1462 | /// <summary> | ||
1463 | /// Create a geometry for the given mesh in the given target space. | ||
1464 | /// </summary> | ||
1465 | /// <param name="m_targetSpace"></param> | ||
1466 | /// <param name="mesh">If null, then a mesh is used that is based on the profile shape data.</param> | ||
1467 | private void CreateGeom() | 1468 | private void CreateGeom() |
1468 | { | 1469 | { |
1469 | if (_triMeshData != IntPtr.Zero) | 1470 | bool hasMesh = false; |
1470 | { | ||
1471 | d.GeomTriMeshDataDestroy(_triMeshData); | ||
1472 | _triMeshData = IntPtr.Zero; | ||
1473 | } | ||
1474 | 1471 | ||
1475 | bool haveMesh = false; | ||
1476 | hasOOBoffsetFromMesh = false; | ||
1477 | m_NoColide = false; | 1472 | m_NoColide = false; |
1478 | 1473 | ||
1479 | if (_parent_scene.needsMeshing(_pbs)) | 1474 | if ((m_meshState & MeshState.MeshNoColide) != 0) |
1475 | m_NoColide = true; | ||
1476 | |||
1477 | else if(m_mesh != null) | ||
1480 | { | 1478 | { |
1481 | haveMesh = setMesh(_parent_scene); // this will give a mesh to non trivial known prims | 1479 | if (GetMeshGeom()) |
1482 | if (!haveMesh) | 1480 | hasMesh = true; |
1481 | else | ||
1483 | m_NoColide = true; | 1482 | m_NoColide = true; |
1484 | } | 1483 | } |
1485 | 1484 | ||
1486 | if (!haveMesh) | 1485 | |
1486 | if (!hasMesh) | ||
1487 | { | 1487 | { |
1488 | IntPtr geo = IntPtr.Zero; | ||
1489 | |||
1488 | if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1 | 1490 | if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1 |
1489 | && _size.X == _size.Y && _size.Y == _size.Z) | 1491 | && _size.X == _size.Y && _size.Y == _size.Z) |
1490 | { // it's a sphere | 1492 | { // it's a sphere |
1491 | _parent_scene.waitForSpaceUnlock(m_targetSpace); | ||
1492 | try | 1493 | try |
1493 | { | 1494 | { |
1494 | SetGeom(d.CreateSphere(m_targetSpace, _size.X * 0.5f)); | 1495 | geo = d.CreateSphere(m_targetSpace, _size.X * 0.5f); |
1495 | } | 1496 | } |
1496 | catch (Exception e) | 1497 | catch (Exception e) |
1497 | { | 1498 | { |
@@ -1501,11 +1502,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1501 | } | 1502 | } |
1502 | else | 1503 | else |
1503 | {// do it as a box | 1504 | {// do it as a box |
1504 | _parent_scene.waitForSpaceUnlock(m_targetSpace); | ||
1505 | try | 1505 | try |
1506 | { | 1506 | { |
1507 | //Console.WriteLine(" CreateGeom 4"); | 1507 | geo = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); |
1508 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); | ||
1509 | } | 1508 | } |
1510 | catch (Exception e) | 1509 | catch (Exception e) |
1511 | { | 1510 | { |
@@ -1513,19 +1512,18 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1513 | return; | 1512 | return; |
1514 | } | 1513 | } |
1515 | } | 1514 | } |
1515 | m_physCost = 0.1f; | ||
1516 | m_streamCost = 1.0f; | ||
1517 | SetGeom(geo); | ||
1516 | } | 1518 | } |
1517 | } | 1519 | } |
1518 | 1520 | ||
1519 | /// <summary> | ||
1520 | /// Set a new geometry for this prim. | ||
1521 | /// </summary> | ||
1522 | /// <param name="geom"></param> | ||
1523 | private void RemoveGeom() | 1521 | private void RemoveGeom() |
1524 | { | 1522 | { |
1525 | if (prim_geom != IntPtr.Zero) | 1523 | if (prim_geom != IntPtr.Zero) |
1526 | { | 1524 | { |
1527 | // _parent_scene.geom_name_map.Remove(prim_geom); | ||
1528 | _parent_scene.actor_name_map.Remove(prim_geom); | 1525 | _parent_scene.actor_name_map.Remove(prim_geom); |
1526 | |||
1529 | try | 1527 | try |
1530 | { | 1528 | { |
1531 | d.GeomDestroy(prim_geom); | 1529 | d.GeomDestroy(prim_geom); |
@@ -1534,11 +1532,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1534 | d.GeomTriMeshDataDestroy(_triMeshData); | 1532 | d.GeomTriMeshDataDestroy(_triMeshData); |
1535 | _triMeshData = IntPtr.Zero; | 1533 | _triMeshData = IntPtr.Zero; |
1536 | } | 1534 | } |
1537 | |||
1538 | } | 1535 | } |
1539 | |||
1540 | |||
1541 | // catch (System.AccessViolationException) | ||
1542 | catch (Exception e) | 1536 | catch (Exception e) |
1543 | { | 1537 | { |
1544 | m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction failed for {0} exception {1}", Name, e); | 1538 | m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction failed for {0} exception {1}", Name, e); |
@@ -1546,29 +1540,26 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1546 | 1540 | ||
1547 | prim_geom = IntPtr.Zero; | 1541 | prim_geom = IntPtr.Zero; |
1548 | collide_geom = IntPtr.Zero; | 1542 | collide_geom = IntPtr.Zero; |
1543 | m_targetSpace = IntPtr.Zero; | ||
1549 | } | 1544 | } |
1550 | else | 1545 | else |
1551 | { | 1546 | { |
1552 | m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction BAD {0}", Name); | 1547 | m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction BAD {0}", Name); |
1553 | } | 1548 | } |
1554 | 1549 | ||
1555 | if (m_mesh != null) | 1550 | lock (m_meshlock) |
1556 | { | 1551 | { |
1557 | _parent_scene.mesher.ReleaseMesh(m_mesh); | 1552 | if (m_mesh != null) |
1558 | m_mesh = null; | 1553 | { |
1554 | _parent_scene.mesher.ReleaseMesh(m_mesh); | ||
1555 | m_mesh = null; | ||
1556 | } | ||
1559 | } | 1557 | } |
1560 | 1558 | ||
1561 | Body = IntPtr.Zero; | 1559 | Body = IntPtr.Zero; |
1562 | hasOOBoffsetFromMesh = false; | 1560 | m_hasOBB = false; |
1563 | } | 1561 | } |
1564 | /* | 1562 | |
1565 | private void ChildSetGeom(OdePrim odePrim) | ||
1566 | { | ||
1567 | // well.. | ||
1568 | DestroyBody(); | ||
1569 | MakeBody(); | ||
1570 | } | ||
1571 | */ | ||
1572 | //sets non physical prim m_targetSpace to right space in spaces grid for static prims | 1563 | //sets non physical prim m_targetSpace to right space in spaces grid for static prims |
1573 | // should only be called for non physical prims unless they are becoming non physical | 1564 | // should only be called for non physical prims unless they are becoming non physical |
1574 | private void SetInStaticSpace(OdePrim prim) | 1565 | private void SetInStaticSpace(OdePrim prim) |
@@ -1631,9 +1622,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1631 | 1622 | ||
1632 | if (Body != IntPtr.Zero) | 1623 | if (Body != IntPtr.Zero) |
1633 | { | 1624 | { |
1634 | // d.BodyDestroy(Body); | ||
1635 | // Body = IntPtr.Zero; | ||
1636 | // do a more complet destruction | ||
1637 | DestroyBody(); | 1625 | DestroyBody(); |
1638 | m_log.Warn("[PHYSICS]: MakeBody called having a body"); | 1626 | m_log.Warn("[PHYSICS]: MakeBody called having a body"); |
1639 | } | 1627 | } |
@@ -2143,339 +2131,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2143 | 2131 | ||
2144 | #region Mass Calculation | 2132 | #region Mass Calculation |
2145 | 2133 | ||
2146 | private float CalculatePrimVolume() | 2134 | private void UpdatePrimBodyData() |
2147 | { | 2135 | { |
2148 | float volume = _size.X * _size.Y * _size.Z; // default | 2136 | primMass = m_density * primVolume; |
2149 | float tmp; | ||
2150 | |||
2151 | float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f; | ||
2152 | float hollowVolume = hollowAmount * hollowAmount; | ||
2153 | |||
2154 | switch (_pbs.ProfileShape) | ||
2155 | { | ||
2156 | case ProfileShape.Square: | ||
2157 | // default box | ||
2158 | |||
2159 | if (_pbs.PathCurve == (byte)Extrusion.Straight) | ||
2160 | { | ||
2161 | if (hollowAmount > 0.0) | ||
2162 | { | ||
2163 | switch (_pbs.HollowShape) | ||
2164 | { | ||
2165 | case HollowShape.Square: | ||
2166 | case HollowShape.Same: | ||
2167 | break; | ||
2168 | |||
2169 | case HollowShape.Circle: | ||
2170 | |||
2171 | hollowVolume *= 0.78539816339f; | ||
2172 | break; | ||
2173 | |||
2174 | case HollowShape.Triangle: | ||
2175 | |||
2176 | hollowVolume *= (0.5f * .5f); | ||
2177 | break; | ||
2178 | |||
2179 | default: | ||
2180 | hollowVolume = 0; | ||
2181 | break; | ||
2182 | } | ||
2183 | volume *= (1.0f - hollowVolume); | ||
2184 | } | ||
2185 | } | ||
2186 | |||
2187 | else if (_pbs.PathCurve == (byte)Extrusion.Curve1) | ||
2188 | { | ||
2189 | //a tube | ||
2190 | |||
2191 | volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX); | ||
2192 | tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY); | ||
2193 | volume -= volume * tmp * tmp; | ||
2194 | |||
2195 | if (hollowAmount > 0.0) | ||
2196 | { | ||
2197 | hollowVolume *= hollowAmount; | ||
2198 | |||
2199 | switch (_pbs.HollowShape) | ||
2200 | { | ||
2201 | case HollowShape.Square: | ||
2202 | case HollowShape.Same: | ||
2203 | break; | ||
2204 | |||
2205 | case HollowShape.Circle: | ||
2206 | hollowVolume *= 0.78539816339f; | ||
2207 | break; | ||
2208 | |||
2209 | case HollowShape.Triangle: | ||
2210 | hollowVolume *= 0.5f * 0.5f; | ||
2211 | break; | ||
2212 | default: | ||
2213 | hollowVolume = 0; | ||
2214 | break; | ||
2215 | } | ||
2216 | volume *= (1.0f - hollowVolume); | ||
2217 | } | ||
2218 | } | ||
2219 | |||
2220 | break; | ||
2221 | |||
2222 | case ProfileShape.Circle: | ||
2223 | |||
2224 | if (_pbs.PathCurve == (byte)Extrusion.Straight) | ||
2225 | { | ||
2226 | volume *= 0.78539816339f; // elipse base | ||
2227 | |||
2228 | if (hollowAmount > 0.0) | ||
2229 | { | ||
2230 | switch (_pbs.HollowShape) | ||
2231 | { | ||
2232 | case HollowShape.Same: | ||
2233 | case HollowShape.Circle: | ||
2234 | break; | ||
2235 | |||
2236 | case HollowShape.Square: | ||
2237 | hollowVolume *= 0.5f * 2.5984480504799f; | ||
2238 | break; | ||
2239 | |||
2240 | case HollowShape.Triangle: | ||
2241 | hollowVolume *= .5f * 1.27323954473516f; | ||
2242 | break; | ||
2243 | |||
2244 | default: | ||
2245 | hollowVolume = 0; | ||
2246 | break; | ||
2247 | } | ||
2248 | volume *= (1.0f - hollowVolume); | ||
2249 | } | ||
2250 | } | ||
2251 | |||
2252 | else if (_pbs.PathCurve == (byte)Extrusion.Curve1) | ||
2253 | { | ||
2254 | volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX); | ||
2255 | tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); | ||
2256 | volume *= (1.0f - tmp * tmp); | ||
2257 | |||
2258 | if (hollowAmount > 0.0) | ||
2259 | { | ||
2260 | |||
2261 | // calculate the hollow volume by it's shape compared to the prim shape | ||
2262 | hollowVolume *= hollowAmount; | ||
2263 | |||
2264 | switch (_pbs.HollowShape) | ||
2265 | { | ||
2266 | case HollowShape.Same: | ||
2267 | case HollowShape.Circle: | ||
2268 | break; | ||
2269 | |||
2270 | case HollowShape.Square: | ||
2271 | hollowVolume *= 0.5f * 2.5984480504799f; | ||
2272 | break; | ||
2273 | |||
2274 | case HollowShape.Triangle: | ||
2275 | hollowVolume *= .5f * 1.27323954473516f; | ||
2276 | break; | ||
2277 | |||
2278 | default: | ||
2279 | hollowVolume = 0; | ||
2280 | break; | ||
2281 | } | ||
2282 | volume *= (1.0f - hollowVolume); | ||
2283 | } | ||
2284 | } | ||
2285 | break; | ||
2286 | |||
2287 | case ProfileShape.HalfCircle: | ||
2288 | if (_pbs.PathCurve == (byte)Extrusion.Curve1) | ||
2289 | { | ||
2290 | volume *= 0.5236f; | ||
2291 | |||
2292 | if (hollowAmount > 0.0) | ||
2293 | { | ||
2294 | hollowVolume *= hollowAmount; | ||
2295 | |||
2296 | switch (_pbs.HollowShape) | ||
2297 | { | ||
2298 | case HollowShape.Circle: | ||
2299 | case HollowShape.Triangle: // diference in sl is minor and odd | ||
2300 | case HollowShape.Same: | ||
2301 | break; | ||
2302 | |||
2303 | case HollowShape.Square: | ||
2304 | hollowVolume *= 0.909f; | ||
2305 | break; | ||
2306 | |||
2307 | // case HollowShape.Triangle: | ||
2308 | // hollowVolume *= .827f; | ||
2309 | // break; | ||
2310 | default: | ||
2311 | hollowVolume = 0; | ||
2312 | break; | ||
2313 | } | ||
2314 | volume *= (1.0f - hollowVolume); | ||
2315 | } | ||
2316 | |||
2317 | } | ||
2318 | break; | ||
2319 | |||
2320 | case ProfileShape.EquilateralTriangle: | ||
2321 | |||
2322 | if (_pbs.PathCurve == (byte)Extrusion.Straight) | ||
2323 | { | ||
2324 | volume *= 0.32475953f; | ||
2325 | |||
2326 | if (hollowAmount > 0.0) | ||
2327 | { | ||
2328 | |||
2329 | // calculate the hollow volume by it's shape compared to the prim shape | ||
2330 | switch (_pbs.HollowShape) | ||
2331 | { | ||
2332 | case HollowShape.Same: | ||
2333 | case HollowShape.Triangle: | ||
2334 | hollowVolume *= .25f; | ||
2335 | break; | ||
2336 | |||
2337 | case HollowShape.Square: | ||
2338 | hollowVolume *= 0.499849f * 3.07920140172638f; | ||
2339 | break; | ||
2340 | |||
2341 | case HollowShape.Circle: | ||
2342 | // Hollow shape is a perfect cyllinder in respect to the cube's scale | ||
2343 | // Cyllinder hollow volume calculation | ||
2344 | |||
2345 | hollowVolume *= 0.1963495f * 3.07920140172638f; | ||
2346 | break; | ||
2347 | |||
2348 | default: | ||
2349 | hollowVolume = 0; | ||
2350 | break; | ||
2351 | } | ||
2352 | volume *= (1.0f - hollowVolume); | ||
2353 | } | ||
2354 | } | ||
2355 | else if (_pbs.PathCurve == (byte)Extrusion.Curve1) | ||
2356 | { | ||
2357 | volume *= 0.32475953f; | ||
2358 | volume *= 0.01f * (float)(200 - _pbs.PathScaleX); | ||
2359 | tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); | ||
2360 | volume *= (1.0f - tmp * tmp); | ||
2361 | |||
2362 | if (hollowAmount > 0.0) | ||
2363 | { | ||
2364 | |||
2365 | hollowVolume *= hollowAmount; | ||
2366 | |||
2367 | switch (_pbs.HollowShape) | ||
2368 | { | ||
2369 | case HollowShape.Same: | ||
2370 | case HollowShape.Triangle: | ||
2371 | hollowVolume *= .25f; | ||
2372 | break; | ||
2373 | |||
2374 | case HollowShape.Square: | ||
2375 | hollowVolume *= 0.499849f * 3.07920140172638f; | ||
2376 | break; | ||
2377 | |||
2378 | case HollowShape.Circle: | ||
2379 | |||
2380 | hollowVolume *= 0.1963495f * 3.07920140172638f; | ||
2381 | break; | ||
2382 | |||
2383 | default: | ||
2384 | hollowVolume = 0; | ||
2385 | break; | ||
2386 | } | ||
2387 | volume *= (1.0f - hollowVolume); | ||
2388 | } | ||
2389 | } | ||
2390 | break; | ||
2391 | |||
2392 | default: | ||
2393 | break; | ||
2394 | } | ||
2395 | |||
2396 | float taperX1; | ||
2397 | float taperY1; | ||
2398 | float taperX; | ||
2399 | float taperY; | ||
2400 | float pathBegin; | ||
2401 | float pathEnd; | ||
2402 | float profileBegin; | ||
2403 | float profileEnd; | ||
2404 | |||
2405 | if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible) | ||
2406 | { | ||
2407 | taperX1 = _pbs.PathScaleX * 0.01f; | ||
2408 | if (taperX1 > 1.0f) | ||
2409 | taperX1 = 2.0f - taperX1; | ||
2410 | taperX = 1.0f - taperX1; | ||
2411 | |||
2412 | taperY1 = _pbs.PathScaleY * 0.01f; | ||
2413 | if (taperY1 > 1.0f) | ||
2414 | taperY1 = 2.0f - taperY1; | ||
2415 | taperY = 1.0f - taperY1; | ||
2416 | } | ||
2417 | else | ||
2418 | { | ||
2419 | taperX = _pbs.PathTaperX * 0.01f; | ||
2420 | if (taperX < 0.0f) | ||
2421 | taperX = -taperX; | ||
2422 | taperX1 = 1.0f - taperX; | ||
2423 | |||
2424 | taperY = _pbs.PathTaperY * 0.01f; | ||
2425 | if (taperY < 0.0f) | ||
2426 | taperY = -taperY; | ||
2427 | taperY1 = 1.0f - taperY; | ||
2428 | } | ||
2429 | |||
2430 | volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); | ||
2431 | |||
2432 | pathBegin = (float)_pbs.PathBegin * 2.0e-5f; | ||
2433 | pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f; | ||
2434 | volume *= (pathEnd - pathBegin); | ||
2435 | |||
2436 | // this is crude aproximation | ||
2437 | profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f; | ||
2438 | profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f; | ||
2439 | volume *= (profileEnd - profileBegin); | ||
2440 | |||
2441 | return volume; | ||
2442 | } | ||
2443 | |||
2444 | |||
2445 | private void CalcPrimBodyData() | ||
2446 | { | ||
2447 | float volume; | ||
2448 | |||
2449 | if (prim_geom == IntPtr.Zero) | ||
2450 | { | ||
2451 | // Ubit let's have a initial basic OOB | ||
2452 | primOOBsize.X = _size.X; | ||
2453 | primOOBsize.Y = _size.Y; | ||
2454 | primOOBsize.Z = _size.Z; | ||
2455 | primOOBoffset = Vector3.Zero; | ||
2456 | } | ||
2457 | else | ||
2458 | { | ||
2459 | d.AABB AABB; | ||
2460 | d.GeomGetAABB(prim_geom, out AABB); // get the AABB from engine geom | ||
2461 | |||
2462 | primOOBsize.X = (AABB.MaxX - AABB.MinX); | ||
2463 | primOOBsize.Y = (AABB.MaxY - AABB.MinY); | ||
2464 | primOOBsize.Z = (AABB.MaxZ - AABB.MinZ); | ||
2465 | if (!hasOOBoffsetFromMesh) | ||
2466 | { | ||
2467 | primOOBoffset.X = (AABB.MaxX + AABB.MinX) * 0.5f; | ||
2468 | primOOBoffset.Y = (AABB.MaxY + AABB.MinY) * 0.5f; | ||
2469 | primOOBoffset.Z = (AABB.MaxZ + AABB.MinZ) * 0.5f; | ||
2470 | } | ||
2471 | } | ||
2472 | |||
2473 | // also its own inertia and mass | ||
2474 | // keep using basic shape mass for now | ||
2475 | volume = CalculatePrimVolume(); | ||
2476 | |||
2477 | primVolume = volume; | ||
2478 | primMass = m_density * volume; | ||
2479 | 2137 | ||
2480 | if (primMass <= 0) | 2138 | if (primMass <= 0) |
2481 | primMass = 0.0001f;//ckrinke: Mass must be greater then zero. | 2139 | primMass = 0.0001f;//ckrinke: Mass must be greater then zero. |
@@ -2484,17 +2142,31 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2484 | 2142 | ||
2485 | _mass = primMass; // just in case | 2143 | _mass = primMass; // just in case |
2486 | 2144 | ||
2487 | d.MassSetBoxTotal(out primdMass, primMass, primOOBsize.X, primOOBsize.Y, primOOBsize.Z); | 2145 | d.MassSetBoxTotal(out primdMass, primMass, m_OBB.X, m_OBB.Y, m_OBB.Z); |
2488 | 2146 | ||
2489 | d.MassTranslate(ref primdMass, | 2147 | d.MassTranslate(ref primdMass, |
2490 | primOOBoffset.X, | 2148 | m_OBBOffset.X, |
2491 | primOOBoffset.Y, | 2149 | m_OBBOffset.Y, |
2492 | primOOBoffset.Z); | 2150 | m_OBBOffset.Z); |
2493 | 2151 | ||
2494 | primOOBsize *= 0.5f; // let obb size be a corner coords | 2152 | primOOBradiusSQ = m_OBB.LengthSquared(); |
2495 | primOOBradiusSQ = primOOBsize.LengthSquared(); | ||
2496 | } | ||
2497 | 2153 | ||
2154 | if (_triMeshData != IntPtr.Zero) | ||
2155 | { | ||
2156 | float pc = m_physCost; | ||
2157 | float psf = primOOBradiusSQ; | ||
2158 | psf *= 1.33f * .2f; | ||
2159 | pc *= psf; | ||
2160 | if (pc < 0.1f) | ||
2161 | pc = 0.1f; | ||
2162 | |||
2163 | m_physCost = pc; | ||
2164 | } | ||
2165 | else | ||
2166 | m_physCost = 0.1f; | ||
2167 | |||
2168 | m_streamCost = 1.0f; | ||
2169 | } | ||
2498 | 2170 | ||
2499 | #endregion | 2171 | #endregion |
2500 | 2172 | ||
@@ -2575,6 +2247,14 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2575 | _orientation.Y = qtmp.Y; | 2247 | _orientation.Y = qtmp.Y; |
2576 | _orientation.Z = qtmp.Z; | 2248 | _orientation.Z = qtmp.Z; |
2577 | _orientation.W = qtmp.W; | 2249 | _orientation.W = qtmp.W; |
2250 | /* | ||
2251 | // Debug | ||
2252 | float qlen = _orientation.Length(); | ||
2253 | if (qlen > 1.01f || qlen < 0.99) | ||
2254 | m_log.WarnFormat("[PHYSICS]: Got nonnorm quaternion from geom in Object {0} norm {1}", Name, qlen); | ||
2255 | // | ||
2256 | */ | ||
2257 | _orientation.Normalize(); | ||
2578 | 2258 | ||
2579 | d.Vector3 lpos = d.GeomGetPosition(prim_geom); | 2259 | d.Vector3 lpos = d.GeomGetPosition(prim_geom); |
2580 | _position.X = lpos.X; | 2260 | _position.X = lpos.X; |
@@ -2684,27 +2364,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2684 | 2364 | ||
2685 | private void changeadd() | 2365 | private void changeadd() |
2686 | { | 2366 | { |
2687 | CreateGeom(); | ||
2688 | |||
2689 | if (prim_geom != IntPtr.Zero) | ||
2690 | { | ||
2691 | d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); | ||
2692 | d.Quaternion myrot = new d.Quaternion(); | ||
2693 | myrot.X = _orientation.X; | ||
2694 | myrot.Y = _orientation.Y; | ||
2695 | myrot.Z = _orientation.Z; | ||
2696 | myrot.W = _orientation.W; | ||
2697 | d.GeomSetQuaternion(prim_geom, ref myrot); | ||
2698 | |||
2699 | if (!m_isphysical) | ||
2700 | { | ||
2701 | SetInStaticSpace(this); | ||
2702 | UpdateCollisionCatFlags(); | ||
2703 | ApplyCollisionCatFlags(); | ||
2704 | } | ||
2705 | else | ||
2706 | MakeBody(); | ||
2707 | } | ||
2708 | } | 2367 | } |
2709 | 2368 | ||
2710 | private void changeAngularLock(Vector3 newLock) | 2369 | private void changeAngularLock(Vector3 newLock) |
@@ -2774,6 +2433,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2774 | _target_velocity = Vector3.Zero; | 2433 | _target_velocity = Vector3.Zero; |
2775 | if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) | 2434 | if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) |
2776 | m_vehicle.Stop(); | 2435 | m_vehicle.Stop(); |
2436 | |||
2437 | _zeroFlag = false; | ||
2438 | base.RequestPhysicsterseUpdate(); | ||
2777 | } | 2439 | } |
2778 | 2440 | ||
2779 | if (Body != IntPtr.Zero) | 2441 | if (Body != IntPtr.Zero) |
@@ -3148,7 +2810,63 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
3148 | resetCollisionAccounting(); | 2810 | resetCollisionAccounting(); |
3149 | } | 2811 | } |
3150 | 2812 | ||
3151 | private void changeprimsizeshape() | 2813 | private void changeSize(Vector3 newSize) |
2814 | { | ||
2815 | } | ||
2816 | |||
2817 | private void changeShape(PrimitiveBaseShape newShape) | ||
2818 | { | ||
2819 | } | ||
2820 | |||
2821 | private void changeAddPhysRep(ODEPhysRepData repData) | ||
2822 | { | ||
2823 | _size = repData.size; //?? | ||
2824 | _pbs = repData.pbs; | ||
2825 | m_shapetype = repData.shapetype; | ||
2826 | |||
2827 | m_mesh = repData.mesh; | ||
2828 | |||
2829 | m_assetID = repData.assetID; | ||
2830 | m_meshState = repData.meshState; | ||
2831 | |||
2832 | m_hasOBB = repData.hasOBB; | ||
2833 | m_OBBOffset = repData.OBBOffset; | ||
2834 | m_OBB = repData.OBB; | ||
2835 | |||
2836 | primVolume = repData.volume; | ||
2837 | |||
2838 | CreateGeom(); | ||
2839 | |||
2840 | if (prim_geom != IntPtr.Zero) | ||
2841 | { | ||
2842 | d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); | ||
2843 | d.Quaternion myrot = new d.Quaternion(); | ||
2844 | myrot.X = _orientation.X; | ||
2845 | myrot.Y = _orientation.Y; | ||
2846 | myrot.Z = _orientation.Z; | ||
2847 | myrot.W = _orientation.W; | ||
2848 | d.GeomSetQuaternion(prim_geom, ref myrot); | ||
2849 | } | ||
2850 | |||
2851 | if (!m_isphysical) | ||
2852 | { | ||
2853 | SetInStaticSpace(this); | ||
2854 | UpdateCollisionCatFlags(); | ||
2855 | ApplyCollisionCatFlags(); | ||
2856 | } | ||
2857 | else | ||
2858 | MakeBody(); | ||
2859 | |||
2860 | if ((m_meshState & MeshState.NeedMask) != 0) | ||
2861 | { | ||
2862 | repData.size = _size; | ||
2863 | repData.pbs = _pbs; | ||
2864 | repData.shapetype = m_shapetype; | ||
2865 | _parent_scene.m_meshWorker.RequestMesh(repData); | ||
2866 | } | ||
2867 | } | ||
2868 | |||
2869 | private void changePhysRepData(ODEPhysRepData repData) | ||
3152 | { | 2870 | { |
3153 | CheckDelaySelect(); | 2871 | CheckDelaySelect(); |
3154 | 2872 | ||
@@ -3170,16 +2888,22 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
3170 | 2888 | ||
3171 | RemoveGeom(); | 2889 | RemoveGeom(); |
3172 | 2890 | ||
3173 | // we don't need to do space calculation because the client sends a position update also. | 2891 | _size = repData.size; |
3174 | if (_size.X <= 0) | 2892 | _pbs = repData.pbs; |
3175 | _size.X = 0.01f; | 2893 | m_shapetype = repData.shapetype; |
3176 | if (_size.Y <= 0) | ||
3177 | _size.Y = 0.01f; | ||
3178 | if (_size.Z <= 0) | ||
3179 | _size.Z = 0.01f; | ||
3180 | // Construction of new prim | ||
3181 | 2894 | ||
3182 | CreateGeom(); | 2895 | m_mesh = repData.mesh; |
2896 | |||
2897 | m_assetID = repData.assetID; | ||
2898 | m_meshState = repData.meshState; | ||
2899 | |||
2900 | m_hasOBB = repData.hasOBB; | ||
2901 | m_OBBOffset = repData.OBBOffset; | ||
2902 | m_OBB = repData.OBB; | ||
2903 | |||
2904 | primVolume = repData.volume; | ||
2905 | |||
2906 | CreateGeom(); | ||
3183 | 2907 | ||
3184 | if (prim_geom != IntPtr.Zero) | 2908 | if (prim_geom != IntPtr.Zero) |
3185 | { | 2909 | { |
@@ -3202,29 +2926,24 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
3202 | } | 2926 | } |
3203 | } | 2927 | } |
3204 | else | 2928 | else |
3205 | MakeBody(); | 2929 | MakeBody(); |
3206 | } | 2930 | } |
3207 | |||
3208 | else | 2931 | else |
3209 | { | 2932 | { |
2933 | SetInStaticSpace(this); | ||
3210 | UpdateCollisionCatFlags(); | 2934 | UpdateCollisionCatFlags(); |
3211 | ApplyCollisionCatFlags(); | 2935 | ApplyCollisionCatFlags(); |
3212 | } | 2936 | } |
3213 | 2937 | ||
3214 | resetCollisionAccounting(); | 2938 | resetCollisionAccounting(); |
3215 | } | ||
3216 | |||
3217 | private void changeSize(Vector3 newSize) | ||
3218 | { | ||
3219 | _size = newSize; | ||
3220 | changeprimsizeshape(); | ||
3221 | } | ||
3222 | 2939 | ||
3223 | private void changeShape(PrimitiveBaseShape newShape) | 2940 | if ((m_meshState & MeshState.NeedMask) != 0) |
3224 | { | 2941 | { |
3225 | if(newShape != null) | 2942 | repData.size = _size; |
3226 | _pbs = newShape; | 2943 | repData.pbs = _pbs; |
3227 | changeprimsizeshape(); | 2944 | repData.shapetype = m_shapetype; |
2945 | _parent_scene.m_meshWorker.RequestMesh(repData); | ||
2946 | } | ||
3228 | } | 2947 | } |
3229 | 2948 | ||
3230 | private void changeFloatOnWater(bool newval) | 2949 | private void changeFloatOnWater(bool newval) |
@@ -3891,7 +3610,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
3891 | 3610 | ||
3892 | public bool DoAChange(changes what, object arg) | 3611 | public bool DoAChange(changes what, object arg) |
3893 | { | 3612 | { |
3894 | if (prim_geom == IntPtr.Zero && what != changes.Add && what != changes.Remove) | 3613 | if (prim_geom == IntPtr.Zero && what != changes.Add && what != changes.AddPhysRep && what != changes.Remove) |
3895 | { | 3614 | { |
3896 | return false; | 3615 | return false; |
3897 | } | 3616 | } |
@@ -3902,6 +3621,11 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
3902 | case changes.Add: | 3621 | case changes.Add: |
3903 | changeadd(); | 3622 | changeadd(); |
3904 | break; | 3623 | break; |
3624 | |||
3625 | case changes.AddPhysRep: | ||
3626 | changeAddPhysRep((ODEPhysRepData)arg); | ||
3627 | break; | ||
3628 | |||
3905 | case changes.Remove: | 3629 | case changes.Remove: |
3906 | //If its being removed, we don't want to rebuild the physical rep at all, so ignore this stuff... | 3630 | //If its being removed, we don't want to rebuild the physical rep at all, so ignore this stuff... |
3907 | //When we return true, it destroys all of the prims in the linkset anyway | 3631 | //When we return true, it destroys all of the prims in the linkset anyway |
@@ -3984,6 +3708,10 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
3984 | changeShape((PrimitiveBaseShape)arg); | 3708 | changeShape((PrimitiveBaseShape)arg); |
3985 | break; | 3709 | break; |
3986 | 3710 | ||
3711 | case changes.PhysRepData: | ||
3712 | changePhysRepData((ODEPhysRepData) arg); | ||
3713 | break; | ||
3714 | |||
3987 | case changes.CollidesWater: | 3715 | case changes.CollidesWater: |
3988 | changeFloatOnWater((bool)arg); | 3716 | changeFloatOnWater((bool)arg); |
3989 | break; | 3717 | break; |
@@ -4072,6 +3800,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
4072 | donullchange(); | 3800 | donullchange(); |
4073 | break; | 3801 | break; |
4074 | 3802 | ||
3803 | |||
3804 | |||
4075 | default: | 3805 | default: |
4076 | donullchange(); | 3806 | donullchange(); |
4077 | break; | 3807 | break; |
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs index 21fe9c0..799a324 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs | |||
@@ -129,7 +129,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
129 | req.length = length; | 129 | req.length = length; |
130 | req.Normal = direction; | 130 | req.Normal = direction; |
131 | req.Origin = position; | 131 | req.Origin = position; |
132 | req.filter = RayFilterFlags.AllPrims; | 132 | req.filter = RayFilterFlags.AllPrims | RayFilterFlags.land; |
133 | 133 | ||
134 | m_PendingRequests.Enqueue(req); | 134 | m_PendingRequests.Enqueue(req); |
135 | } | 135 | } |
@@ -288,7 +288,10 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
288 | catflags |= CollisionCategories.Water; | 288 | catflags |= CollisionCategories.Water; |
289 | 289 | ||
290 | if (catflags != 0) | 290 | if (catflags != 0) |
291 | { | ||
292 | d.GeomSetCollideBits(ray, (uint)catflags); | ||
291 | doSpaceRay(req); | 293 | doSpaceRay(req); |
294 | } | ||
292 | } | 295 | } |
293 | else | 296 | else |
294 | { | 297 | { |
@@ -314,7 +317,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
314 | /// | 317 | /// |
315 | 318 | ||
316 | private const RayFilterFlags FilterActiveSpace = RayFilterFlags.agent | RayFilterFlags.physical | RayFilterFlags.LSLPhanton; | 319 | private const RayFilterFlags FilterActiveSpace = RayFilterFlags.agent | RayFilterFlags.physical | RayFilterFlags.LSLPhanton; |
317 | private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.land | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton; | 320 | // private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.land | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton; |
321 | private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton; | ||
318 | 322 | ||
319 | private void doSpaceRay(ODERayRequest req) | 323 | private void doSpaceRay(ODERayRequest req) |
320 | { | 324 | { |
@@ -323,6 +327,16 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
323 | d.SpaceCollide2(ray, m_scene.ActiveSpace, IntPtr.Zero, nearCallback); | 327 | d.SpaceCollide2(ray, m_scene.ActiveSpace, IntPtr.Zero, nearCallback); |
324 | if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount)) | 328 | if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount)) |
325 | d.SpaceCollide2(ray, m_scene.StaticSpace, IntPtr.Zero, nearCallback); | 329 | d.SpaceCollide2(ray, m_scene.StaticSpace, IntPtr.Zero, nearCallback); |
330 | if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount)) | ||
331 | { | ||
332 | // current ode land to ray collisions is very bad | ||
333 | // so for now limit its range badly | ||
334 | |||
335 | if (req.length > 30.0f) | ||
336 | d.GeomRaySetLength(ray, 30.0f); | ||
337 | |||
338 | d.SpaceCollide2(ray, m_scene.GroundSpace, IntPtr.Zero, nearCallback); | ||
339 | } | ||
326 | 340 | ||
327 | if (req.callbackMethod is RaycastCallback) | 341 | if (req.callbackMethod is RaycastCallback) |
328 | { | 342 | { |
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs index f126644..b98f177 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs | |||
@@ -60,6 +60,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
60 | public int lastframe; | 60 | public int lastframe; |
61 | } | 61 | } |
62 | 62 | ||
63 | |||
63 | // colision flags of things others can colide with | 64 | // colision flags of things others can colide with |
64 | // rays, sensors, probes removed since can't be colided with | 65 | // rays, sensors, probes removed since can't be colided with |
65 | // The top space where things are placed provided further selection | 66 | // The top space where things are placed provided further selection |
@@ -109,7 +110,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
109 | 110 | ||
110 | light = 7 // compatibility with old viewers | 111 | light = 7 // compatibility with old viewers |
111 | } | 112 | } |
112 | 113 | ||
113 | public enum changes : int | 114 | public enum changes : int |
114 | { | 115 | { |
115 | Add = 0, // arg null. finishs the prim creation. should be used internally only ( to remove later ?) | 116 | Add = 0, // arg null. finishs the prim creation. should be used internally only ( to remove later ?) |
@@ -147,6 +148,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
147 | 148 | ||
148 | Size, | 149 | Size, |
149 | Shape, | 150 | Shape, |
151 | PhysRepData, | ||
152 | AddPhysRep, | ||
150 | 153 | ||
151 | CollidesWater, | 154 | CollidesWater, |
152 | VolumeDtc, | 155 | VolumeDtc, |
@@ -230,11 +233,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
230 | private float minimumGroundFlightOffset = 3f; | 233 | private float minimumGroundFlightOffset = 3f; |
231 | public float maximumMassObject = 10000.01f; | 234 | public float maximumMassObject = 10000.01f; |
232 | 235 | ||
233 | public bool meshSculptedPrim = true; | ||
234 | public bool forceSimplePrimMeshing = false; | ||
235 | |||
236 | public float meshSculptLOD = 32; | ||
237 | public float MeshSculptphysicalLOD = 32; | ||
238 | 236 | ||
239 | public float geomDefaultDensity = 10.000006836f; | 237 | public float geomDefaultDensity = 10.000006836f; |
240 | 238 | ||
@@ -302,6 +300,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
302 | public IntPtr TopSpace; // the global space | 300 | public IntPtr TopSpace; // the global space |
303 | public IntPtr ActiveSpace; // space for active prims | 301 | public IntPtr ActiveSpace; // space for active prims |
304 | public IntPtr StaticSpace; // space for the static things around | 302 | public IntPtr StaticSpace; // space for the static things around |
303 | public IntPtr GroundSpace; // space for ground | ||
305 | 304 | ||
306 | // some speedup variables | 305 | // some speedup variables |
307 | private int spaceGridMaxX; | 306 | private int spaceGridMaxX; |
@@ -313,7 +312,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
313 | private IntPtr[] staticPrimspaceOffRegion; | 312 | private IntPtr[] staticPrimspaceOffRegion; |
314 | 313 | ||
315 | public Object OdeLock; | 314 | public Object OdeLock; |
316 | private static Object SimulationLock; | 315 | public static Object SimulationLock; |
317 | 316 | ||
318 | public IMesher mesher; | 317 | public IMesher mesher; |
319 | 318 | ||
@@ -328,7 +327,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
328 | private PhysicsScene m_parentScene = null; | 327 | private PhysicsScene m_parentScene = null; |
329 | 328 | ||
330 | private ODERayCastRequestManager m_rayCastManager; | 329 | private ODERayCastRequestManager m_rayCastManager; |
331 | 330 | public ODEMeshWorker m_meshWorker; | |
332 | 331 | ||
333 | /* maybe needed if ode uses tls | 332 | /* maybe needed if ode uses tls |
334 | private void checkThread() | 333 | private void checkThread() |
@@ -361,6 +360,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
361 | nearCallback = near; | 360 | nearCallback = near; |
362 | 361 | ||
363 | m_rayCastManager = new ODERayCastRequestManager(this); | 362 | m_rayCastManager = new ODERayCastRequestManager(this); |
363 | |||
364 | |||
364 | lock (OdeLock) | 365 | lock (OdeLock) |
365 | { | 366 | { |
366 | // Create the world and the first space | 367 | // Create the world and the first space |
@@ -372,6 +373,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
372 | // now the major subspaces | 373 | // now the major subspaces |
373 | ActiveSpace = d.HashSpaceCreate(TopSpace); | 374 | ActiveSpace = d.HashSpaceCreate(TopSpace); |
374 | StaticSpace = d.HashSpaceCreate(TopSpace); | 375 | StaticSpace = d.HashSpaceCreate(TopSpace); |
376 | GroundSpace = d.HashSpaceCreate(TopSpace); | ||
375 | } | 377 | } |
376 | catch | 378 | catch |
377 | { | 379 | { |
@@ -381,10 +383,12 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
381 | d.HashSpaceSetLevels(TopSpace, -2, 8); | 383 | d.HashSpaceSetLevels(TopSpace, -2, 8); |
382 | d.HashSpaceSetLevels(ActiveSpace, -2, 8); | 384 | d.HashSpaceSetLevels(ActiveSpace, -2, 8); |
383 | d.HashSpaceSetLevels(StaticSpace, -2, 8); | 385 | d.HashSpaceSetLevels(StaticSpace, -2, 8); |
386 | d.HashSpaceSetLevels(GroundSpace, 0, 8); | ||
384 | 387 | ||
385 | // demote to second level | 388 | // demote to second level |
386 | d.SpaceSetSublevel(ActiveSpace, 1); | 389 | d.SpaceSetSublevel(ActiveSpace, 1); |
387 | d.SpaceSetSublevel(StaticSpace, 1); | 390 | d.SpaceSetSublevel(StaticSpace, 1); |
391 | d.SpaceSetSublevel(GroundSpace, 1); | ||
388 | 392 | ||
389 | d.GeomSetCategoryBits(ActiveSpace, (uint)(CollisionCategories.Space | | 393 | d.GeomSetCategoryBits(ActiveSpace, (uint)(CollisionCategories.Space | |
390 | CollisionCategories.Geom | | 394 | CollisionCategories.Geom | |
@@ -402,6 +406,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
402 | )); | 406 | )); |
403 | d.GeomSetCollideBits(StaticSpace, 0); | 407 | d.GeomSetCollideBits(StaticSpace, 0); |
404 | 408 | ||
409 | d.GeomSetCategoryBits(GroundSpace, (uint)(CollisionCategories.Land)); | ||
410 | d.GeomSetCollideBits(GroundSpace, 0); | ||
411 | |||
405 | contactgroup = d.JointGroupCreate(0); | 412 | contactgroup = d.JointGroupCreate(0); |
406 | //contactgroup | 413 | //contactgroup |
407 | 414 | ||
@@ -440,9 +447,11 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
440 | 447 | ||
441 | int contactsPerCollision = 80; | 448 | int contactsPerCollision = 80; |
442 | 449 | ||
450 | IConfig physicsconfig = null; | ||
451 | |||
443 | if (m_config != null) | 452 | if (m_config != null) |
444 | { | 453 | { |
445 | IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"]; | 454 | physicsconfig = m_config.Configs["ODEPhysicsSettings"]; |
446 | if (physicsconfig != null) | 455 | if (physicsconfig != null) |
447 | { | 456 | { |
448 | gravityx = physicsconfig.GetFloat("world_gravityx", gravityx); | 457 | gravityx = physicsconfig.GetFloat("world_gravityx", gravityx); |
@@ -469,27 +478,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
469 | 478 | ||
470 | geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", geomDefaultDensity); | 479 | geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", geomDefaultDensity); |
471 | bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", bodyFramesAutoDisable); | 480 | bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", bodyFramesAutoDisable); |
472 | /* | 481 | |
473 | bodyPIDD = physicsconfig.GetFloat("body_pid_derivative", bodyPIDD); | ||
474 | bodyPIDG = physicsconfig.GetFloat("body_pid_gain", bodyPIDG); | ||
475 | */ | ||
476 | forceSimplePrimMeshing = physicsconfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing); | ||
477 | meshSculptedPrim = physicsconfig.GetBoolean("mesh_sculpted_prim", meshSculptedPrim); | ||
478 | meshSculptLOD = physicsconfig.GetFloat("mesh_lod", meshSculptLOD); | ||
479 | MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD); | ||
480 | /* | ||
481 | if (Environment.OSVersion.Platform == PlatformID.Unix) | ||
482 | { | ||
483 | avPIDD = physicsconfig.GetFloat("av_pid_derivative_linux", avPIDD); | ||
484 | avPIDP = physicsconfig.GetFloat("av_pid_proportional_linux", avPIDP); | ||
485 | } | ||
486 | else | ||
487 | { | ||
488 | |||
489 | avPIDD = physicsconfig.GetFloat("av_pid_derivative_win", avPIDD); | ||
490 | avPIDP = physicsconfig.GetFloat("av_pid_proportional_win", avPIDP); | ||
491 | } | ||
492 | */ | ||
493 | physics_logging = physicsconfig.GetBoolean("physics_logging", false); | 482 | physics_logging = physicsconfig.GetBoolean("physics_logging", false); |
494 | physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0); | 483 | physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0); |
495 | physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false); | 484 | physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false); |
@@ -499,6 +488,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
499 | } | 488 | } |
500 | } | 489 | } |
501 | 490 | ||
491 | m_meshWorker = new ODEMeshWorker(this, m_log, meshmerizer, physicsconfig); | ||
492 | |||
502 | HalfOdeStep = ODE_STEPSIZE * 0.5f; | 493 | HalfOdeStep = ODE_STEPSIZE * 0.5f; |
503 | odetimestepMS = (int)(1000.0f * ODE_STEPSIZE +0.5f); | 494 | odetimestepMS = (int)(1000.0f * ODE_STEPSIZE +0.5f); |
504 | 495 | ||
@@ -727,6 +718,32 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
727 | 718 | ||
728 | if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) | 719 | if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) |
729 | return; | 720 | return; |
721 | /* | ||
722 | // debug | ||
723 | PhysicsActor dp2; | ||
724 | if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass) | ||
725 | { | ||
726 | d.AABB aabb; | ||
727 | d.GeomGetAABB(g2, out aabb); | ||
728 | float x = aabb.MaxX - aabb.MinX; | ||
729 | float y = aabb.MaxY - aabb.MinY; | ||
730 | float z = aabb.MaxZ - aabb.MinZ; | ||
731 | if (x > 60.0f || y > 60.0f || z > 60.0f) | ||
732 | { | ||
733 | if (!actor_name_map.TryGetValue(g2, out dp2)) | ||
734 | m_log.WarnFormat("[PHYSICS]: failed actor mapping for geom 2"); | ||
735 | else | ||
736 | m_log.WarnFormat("[PHYSICS]: land versus large prim geo {0},size {1}, AABBsize <{2},{3},{4}>, at {5} ori {6},({7})", | ||
737 | dp2.Name, dp2.Size, x, y, z, | ||
738 | dp2.Position.ToString(), | ||
739 | dp2.Orientation.ToString(), | ||
740 | dp2.Orientation.Length()); | ||
741 | return; | ||
742 | } | ||
743 | } | ||
744 | // | ||
745 | */ | ||
746 | |||
730 | 747 | ||
731 | if(d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc || | 748 | if(d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc || |
732 | d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc) | 749 | d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc) |
@@ -1225,6 +1242,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1225 | chr.CollidingObj = false; | 1242 | chr.CollidingObj = false; |
1226 | // do colisions with static space | 1243 | // do colisions with static space |
1227 | d.SpaceCollide2(StaticSpace, chr.Shell, IntPtr.Zero, nearCallback); | 1244 | d.SpaceCollide2(StaticSpace, chr.Shell, IntPtr.Zero, nearCallback); |
1245 | // no coll with gnd | ||
1228 | } | 1246 | } |
1229 | } | 1247 | } |
1230 | catch (AccessViolationException) | 1248 | catch (AccessViolationException) |
@@ -1253,7 +1271,10 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1253 | if (!prm.m_outbounds) | 1271 | if (!prm.m_outbounds) |
1254 | { | 1272 | { |
1255 | if (d.BodyIsEnabled(prm.Body)) | 1273 | if (d.BodyIsEnabled(prm.Body)) |
1274 | { | ||
1256 | d.SpaceCollide2(StaticSpace, prm.collide_geom, IntPtr.Zero, nearCallback); | 1275 | d.SpaceCollide2(StaticSpace, prm.collide_geom, IntPtr.Zero, nearCallback); |
1276 | d.SpaceCollide2(GroundSpace, prm.collide_geom, IntPtr.Zero, nearCallback); | ||
1277 | } | ||
1257 | } | 1278 | } |
1258 | } | 1279 | } |
1259 | } | 1280 | } |
@@ -1295,6 +1316,15 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1295 | _collisionEventPrimRemove.Add(obj); | 1316 | _collisionEventPrimRemove.Add(obj); |
1296 | } | 1317 | } |
1297 | 1318 | ||
1319 | public override float TimeDilation | ||
1320 | { | ||
1321 | get { return m_timeDilation; } | ||
1322 | } | ||
1323 | |||
1324 | public override bool SupportsNINJAJoints | ||
1325 | { | ||
1326 | get { return false; } | ||
1327 | } | ||
1298 | 1328 | ||
1299 | #region Add/Remove Entities | 1329 | #region Add/Remove Entities |
1300 | 1330 | ||
@@ -1350,117 +1380,59 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1350 | ((OdeCharacter) actor).Destroy(); | 1380 | ((OdeCharacter) actor).Destroy(); |
1351 | } | 1381 | } |
1352 | 1382 | ||
1353 | private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation, | ||
1354 | PrimitiveBaseShape pbs, bool isphysical, uint localID) | ||
1355 | { | ||
1356 | Vector3 pos = position; | ||
1357 | Vector3 siz = size; | ||
1358 | Quaternion rot = rotation; | ||
1359 | 1383 | ||
1360 | OdePrim newPrim; | 1384 | public void addActivePrim(OdePrim activatePrim) |
1361 | lock (OdeLock) | 1385 | { |
1386 | // adds active prim.. | ||
1387 | lock (_activeprims) | ||
1362 | { | 1388 | { |
1363 | newPrim = new OdePrim(name, this, pos, siz, rot, pbs, isphysical,false,0,localID); | 1389 | if (!_activeprims.Contains(activatePrim)) |
1364 | 1390 | _activeprims.Add(activatePrim); | |
1365 | lock (_prims) | ||
1366 | _prims.Add(newPrim); | ||
1367 | } | 1391 | } |
1368 | return newPrim; | ||
1369 | } | 1392 | } |
1370 | 1393 | ||
1371 | private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation, | 1394 | public void addActiveGroups(OdePrim activatePrim) |
1372 | PrimitiveBaseShape pbs, bool isphysical, bool isPhantom, uint localID) | ||
1373 | { | 1395 | { |
1374 | Vector3 pos = position; | 1396 | lock (_activegroups) |
1375 | Vector3 siz = size; | ||
1376 | Quaternion rot = rotation; | ||
1377 | |||
1378 | OdePrim newPrim; | ||
1379 | lock (OdeLock) | ||
1380 | { | 1397 | { |
1381 | newPrim = new OdePrim(name, this, pos, siz, rot, pbs, isphysical, isPhantom, 0, localID); | 1398 | if (!_activegroups.Contains(activatePrim)) |
1382 | 1399 | _activegroups.Add(activatePrim); | |
1383 | lock (_prims) | ||
1384 | _prims.Add(newPrim); | ||
1385 | } | 1400 | } |
1386 | return newPrim; | ||
1387 | } | 1401 | } |
1388 | 1402 | ||
1389 | private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation, | 1403 | private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation, |
1390 | PrimitiveBaseShape pbs, bool isphysical, bool isPhantom, byte shapeType, uint localID) | 1404 | PrimitiveBaseShape pbs, bool isphysical, bool isPhantom, byte shapeType, uint localID) |
1391 | { | 1405 | { |
1392 | Vector3 pos = position; | ||
1393 | Vector3 siz = size; | ||
1394 | Quaternion rot = rotation; | ||
1395 | |||
1396 | OdePrim newPrim; | 1406 | OdePrim newPrim; |
1397 | lock (OdeLock) | 1407 | lock (OdeLock) |
1398 | { | 1408 | { |
1399 | newPrim = new OdePrim(name, this, pos, siz, rot, pbs, isphysical, isPhantom, shapeType, localID); | 1409 | newPrim = new OdePrim(name, this, position, size, rotation, pbs, isphysical, isPhantom, shapeType, localID); |
1400 | |||
1401 | lock (_prims) | 1410 | lock (_prims) |
1402 | _prims.Add(newPrim); | 1411 | _prims.Add(newPrim); |
1403 | } | 1412 | } |
1404 | return newPrim; | 1413 | return newPrim; |
1405 | } | 1414 | } |
1406 | 1415 | ||
1407 | public void addActivePrim(OdePrim activatePrim) | ||
1408 | { | ||
1409 | // adds active prim.. | ||
1410 | lock (_activeprims) | ||
1411 | { | ||
1412 | if (!_activeprims.Contains(activatePrim)) | ||
1413 | _activeprims.Add(activatePrim); | ||
1414 | } | ||
1415 | } | ||
1416 | |||
1417 | public void addActiveGroups(OdePrim activatePrim) | ||
1418 | { | ||
1419 | lock (_activegroups) | ||
1420 | { | ||
1421 | if (!_activegroups.Contains(activatePrim)) | ||
1422 | _activegroups.Add(activatePrim); | ||
1423 | } | ||
1424 | } | ||
1425 | |||
1426 | public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, | 1416 | public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, |
1427 | Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, uint localid) | 1417 | Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, uint localid) |
1428 | { | 1418 | { |
1429 | return AddPrim(primName, position, size, rotation, pbs, isPhysical, isPhantom, localid); | 1419 | return AddPrim(primName, position, size, rotation, pbs, isPhysical, isPhantom, 0 , localid); |
1430 | } | 1420 | } |
1431 | 1421 | ||
1432 | 1422 | ||
1433 | public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, | 1423 | public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, |
1434 | Vector3 size, Quaternion rotation, bool isPhysical, uint localid) | 1424 | Vector3 size, Quaternion rotation, bool isPhysical, uint localid) |
1435 | { | 1425 | { |
1436 | #if SPAM | 1426 | return AddPrim(primName, position, size, rotation, pbs, isPhysical,false, 0, localid); |
1437 | m_log.DebugFormat("[PHYSICS]: Adding physics actor to {0}", primName); | ||
1438 | #endif | ||
1439 | |||
1440 | return AddPrim(primName, position, size, rotation, pbs, isPhysical, localid); | ||
1441 | } | 1427 | } |
1442 | 1428 | ||
1443 | public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, | 1429 | public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, |
1444 | Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, byte shapeType, uint localid) | 1430 | Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, byte shapeType, uint localid) |
1445 | { | 1431 | { |
1446 | #if SPAM | ||
1447 | m_log.DebugFormat("[PHYSICS]: Adding physics actor to {0}", primName); | ||
1448 | #endif | ||
1449 | 1432 | ||
1450 | return AddPrim(primName, position, size, rotation, pbs, isPhysical,isPhantom, shapeType, localid); | 1433 | return AddPrim(primName, position, size, rotation, pbs, isPhysical,isPhantom, shapeType, localid); |
1451 | } | 1434 | } |
1452 | 1435 | ||
1453 | public override float TimeDilation | ||
1454 | { | ||
1455 | get { return m_timeDilation; } | ||
1456 | } | ||
1457 | |||
1458 | public override bool SupportsNINJAJoints | ||
1459 | { | ||
1460 | get { return false; } | ||
1461 | } | ||
1462 | |||
1463 | |||
1464 | public void remActivePrim(OdePrim deactivatePrim) | 1436 | public void remActivePrim(OdePrim deactivatePrim) |
1465 | { | 1437 | { |
1466 | lock (_activeprims) | 1438 | lock (_activeprims) |
@@ -1513,6 +1485,28 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1513 | } | 1485 | } |
1514 | 1486 | ||
1515 | } | 1487 | } |
1488 | |||
1489 | public bool havePrim(OdePrim prm) | ||
1490 | { | ||
1491 | lock (_prims) | ||
1492 | return _prims.Contains(prm); | ||
1493 | } | ||
1494 | |||
1495 | public bool haveActor(PhysicsActor actor) | ||
1496 | { | ||
1497 | if (actor is OdePrim) | ||
1498 | { | ||
1499 | lock (_prims) | ||
1500 | return _prims.Contains((OdePrim)actor); | ||
1501 | } | ||
1502 | else if (actor is OdeCharacter) | ||
1503 | { | ||
1504 | lock (_characters) | ||
1505 | return _characters.Contains((OdeCharacter)actor); | ||
1506 | } | ||
1507 | return false; | ||
1508 | } | ||
1509 | |||
1516 | #endregion | 1510 | #endregion |
1517 | 1511 | ||
1518 | #region Space Separation Calculation | 1512 | #region Space Separation Calculation |
@@ -1615,135 +1609,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1615 | 1609 | ||
1616 | #endregion | 1610 | #endregion |
1617 | 1611 | ||
1618 | /// <summary> | ||
1619 | /// Routine to figure out if we need to mesh this prim with our mesher | ||
1620 | /// </summary> | ||
1621 | /// <param name="pbs"></param> | ||
1622 | /// <returns></returns> | ||
1623 | public bool needsMeshing(PrimitiveBaseShape pbs) | ||
1624 | { | ||
1625 | // check sculpts or meshs | ||
1626 | if (pbs.SculptEntry) | ||
1627 | { | ||
1628 | if (meshSculptedPrim) | ||
1629 | return true; | ||
1630 | |||
1631 | if (pbs.SculptType == (byte)SculptType.Mesh) // always do meshs | ||
1632 | return true; | ||
1633 | |||
1634 | return false; | ||
1635 | } | ||
1636 | |||
1637 | if (forceSimplePrimMeshing) | ||
1638 | return true; | ||
1639 | |||
1640 | // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim | ||
1641 | |||
1642 | if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) | ||
1643 | || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 | ||
1644 | && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)) | ||
1645 | { | ||
1646 | |||
1647 | if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 | ||
1648 | && pbs.ProfileHollow == 0 | ||
1649 | && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 | ||
1650 | && pbs.PathBegin == 0 && pbs.PathEnd == 0 | ||
1651 | && pbs.PathTaperX == 0 && pbs.PathTaperY == 0 | ||
1652 | && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 | ||
1653 | && pbs.PathShearX == 0 && pbs.PathShearY == 0) | ||
1654 | { | ||
1655 | #if SPAM | ||
1656 | m_log.Warn("NonMesh"); | ||
1657 | #endif | ||
1658 | return false; | ||
1659 | } | ||
1660 | } | ||
1661 | |||
1662 | // following code doesn't give meshs to boxes and spheres ever | ||
1663 | // and it's odd.. so for now just return true if asked to force meshs | ||
1664 | // hopefully mesher will fail if doesn't suport so things still get basic boxes | ||
1665 | |||
1666 | int iPropertiesNotSupportedDefault = 0; | ||
1667 | |||
1668 | if (pbs.ProfileHollow != 0) | ||
1669 | iPropertiesNotSupportedDefault++; | ||
1670 | |||
1671 | if ((pbs.PathBegin != 0) || pbs.PathEnd != 0) | ||
1672 | iPropertiesNotSupportedDefault++; | ||
1673 | |||
1674 | if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0)) | ||
1675 | iPropertiesNotSupportedDefault++; | ||
1676 | |||
1677 | if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0) | ||
1678 | iPropertiesNotSupportedDefault++; | ||
1679 | |||
1680 | if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100)) | ||
1681 | iPropertiesNotSupportedDefault++; | ||
1682 | |||
1683 | if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0)) | ||
1684 | iPropertiesNotSupportedDefault++; | ||
1685 | |||
1686 | if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight) | ||
1687 | iPropertiesNotSupportedDefault++; | ||
1688 | |||
1689 | if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X)) | ||
1690 | iPropertiesNotSupportedDefault++; | ||
1691 | |||
1692 | if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte) Extrusion.Curve1) | ||
1693 | iPropertiesNotSupportedDefault++; | ||
1694 | |||
1695 | // test for torus | ||
1696 | if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square) | ||
1697 | { | ||
1698 | if (pbs.PathCurve == (byte)Extrusion.Curve1) | ||
1699 | { | ||
1700 | iPropertiesNotSupportedDefault++; | ||
1701 | } | ||
1702 | } | ||
1703 | else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) | ||
1704 | { | ||
1705 | if (pbs.PathCurve == (byte)Extrusion.Straight) | ||
1706 | { | ||
1707 | iPropertiesNotSupportedDefault++; | ||
1708 | } | ||
1709 | |||
1710 | // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits | ||
1711 | else if (pbs.PathCurve == (byte)Extrusion.Curve1) | ||
1712 | { | ||
1713 | iPropertiesNotSupportedDefault++; | ||
1714 | } | ||
1715 | } | ||
1716 | else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) | ||
1717 | { | ||
1718 | if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2) | ||
1719 | { | ||
1720 | iPropertiesNotSupportedDefault++; | ||
1721 | } | ||
1722 | } | ||
1723 | else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) | ||
1724 | { | ||
1725 | if (pbs.PathCurve == (byte)Extrusion.Straight) | ||
1726 | { | ||
1727 | iPropertiesNotSupportedDefault++; | ||
1728 | } | ||
1729 | else if (pbs.PathCurve == (byte)Extrusion.Curve1) | ||
1730 | { | ||
1731 | iPropertiesNotSupportedDefault++; | ||
1732 | } | ||
1733 | } | ||
1734 | |||
1735 | if (iPropertiesNotSupportedDefault == 0) | ||
1736 | { | ||
1737 | #if SPAM | ||
1738 | m_log.Warn("NonMesh"); | ||
1739 | #endif | ||
1740 | return false; | ||
1741 | } | ||
1742 | #if SPAM | ||
1743 | m_log.Debug("Mesh"); | ||
1744 | #endif | ||
1745 | return true; | ||
1746 | } | ||
1747 | 1612 | ||
1748 | /// <summary> | 1613 | /// <summary> |
1749 | /// Called to queue a change to a actor | 1614 | /// Called to queue a change to a actor |
@@ -1766,8 +1631,52 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1766 | /// </summary> | 1631 | /// </summary> |
1767 | /// <param name="prim"></param> | 1632 | /// <param name="prim"></param> |
1768 | public override void AddPhysicsActorTaint(PhysicsActor prim) | 1633 | public override void AddPhysicsActorTaint(PhysicsActor prim) |
1634 | { | ||
1635 | } | ||
1636 | |||
1637 | // does all pending changes generated during region load process | ||
1638 | public override void PrepareSimulation() | ||
1639 | { | ||
1640 | lock (OdeLock) | ||
1769 | { | 1641 | { |
1642 | if (world == IntPtr.Zero) | ||
1643 | { | ||
1644 | ChangesQueue.Clear(); | ||
1645 | return; | ||
1646 | } | ||
1647 | |||
1648 | ODEchangeitem item; | ||
1649 | |||
1650 | int donechanges = 0; | ||
1651 | if (ChangesQueue.Count > 0) | ||
1652 | { | ||
1653 | m_log.InfoFormat("[ODE] start processing pending actor operations"); | ||
1654 | int tstart = Util.EnvironmentTickCount(); | ||
1655 | |||
1656 | while (ChangesQueue.Dequeue(out item)) | ||
1657 | { | ||
1658 | if (item.actor != null) | ||
1659 | { | ||
1660 | try | ||
1661 | { | ||
1662 | if (item.actor is OdeCharacter) | ||
1663 | ((OdeCharacter)item.actor).DoAChange(item.what, item.arg); | ||
1664 | else if (((OdePrim)item.actor).DoAChange(item.what, item.arg)) | ||
1665 | RemovePrimThreadLocked((OdePrim)item.actor); | ||
1666 | } | ||
1667 | catch | ||
1668 | { | ||
1669 | m_log.WarnFormat("[PHYSICS]: Operation failed for a actor {0} {1}", | ||
1670 | item.actor.Name, item.what.ToString()); | ||
1671 | } | ||
1672 | } | ||
1673 | donechanges++; | ||
1674 | } | ||
1675 | int time = Util.EnvironmentTickCountSubtract(tstart); | ||
1676 | m_log.InfoFormat("[ODE] finished {0} operations in {1}ms", donechanges, time); | ||
1677 | } | ||
1770 | } | 1678 | } |
1679 | } | ||
1771 | 1680 | ||
1772 | /// <summary> | 1681 | /// <summary> |
1773 | /// This is our main simulate loop | 1682 | /// This is our main simulate loop |
@@ -1813,21 +1722,17 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1813 | lock(OdeLock) | 1722 | lock(OdeLock) |
1814 | { | 1723 | { |
1815 | if (world == IntPtr.Zero) | 1724 | if (world == IntPtr.Zero) |
1725 | { | ||
1726 | ChangesQueue.Clear(); | ||
1816 | return 0; | 1727 | return 0; |
1728 | } | ||
1817 | 1729 | ||
1818 | // adjust number of iterations per step | 1730 | ODEchangeitem item; |
1731 | |||
1732 | |||
1733 | |||
1734 | d.WorldSetQuickStepNumIterations(world, curphysiteractions); | ||
1819 | 1735 | ||
1820 | // try | ||
1821 | // { | ||
1822 | d.WorldSetQuickStepNumIterations(world, curphysiteractions); | ||
1823 | /* } | ||
1824 | catch (StackOverflowException) | ||
1825 | { | ||
1826 | m_log.Error("[PHYSICS]: The operating system wasn't able to allocate enough memory for the simulation. Restarting the sim."); | ||
1827 | // ode.drelease(world); | ||
1828 | base.TriggerPhysicsBasedRestart(); | ||
1829 | } | ||
1830 | */ | ||
1831 | while (step_time > HalfOdeStep && nodeframes < 10) //limit number of steps so we don't say here for ever | 1736 | while (step_time > HalfOdeStep && nodeframes < 10) //limit number of steps so we don't say here for ever |
1832 | { | 1737 | { |
1833 | try | 1738 | try |
@@ -1835,14 +1740,12 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1835 | // clear pointer/counter to contacts to pass into joints | 1740 | // clear pointer/counter to contacts to pass into joints |
1836 | m_global_contactcount = 0; | 1741 | m_global_contactcount = 0; |
1837 | 1742 | ||
1838 | ODEchangeitem item; | 1743 | if (ChangesQueue.Count > 0) |
1839 | |||
1840 | if(ChangesQueue.Count >0) | ||
1841 | { | 1744 | { |
1842 | int ttmpstart = Util.EnvironmentTickCount(); | 1745 | int ttmpstart = Util.EnvironmentTickCount(); |
1843 | int ttmp; | 1746 | int ttmp; |
1844 | 1747 | ||
1845 | while(ChangesQueue.Dequeue(out item)) | 1748 | while (ChangesQueue.Dequeue(out item)) |
1846 | { | 1749 | { |
1847 | if (item.actor != null) | 1750 | if (item.actor != null) |
1848 | { | 1751 | { |
@@ -1851,12 +1754,13 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1851 | if (item.actor is OdeCharacter) | 1754 | if (item.actor is OdeCharacter) |
1852 | ((OdeCharacter)item.actor).DoAChange(item.what, item.arg); | 1755 | ((OdeCharacter)item.actor).DoAChange(item.what, item.arg); |
1853 | else if (((OdePrim)item.actor).DoAChange(item.what, item.arg)) | 1756 | else if (((OdePrim)item.actor).DoAChange(item.what, item.arg)) |
1854 | RemovePrimThreadLocked((OdePrim)item.actor); | 1757 | RemovePrimThreadLocked((OdePrim)item.actor); |
1855 | } | 1758 | } |
1856 | catch | 1759 | catch |
1857 | { | 1760 | { |
1858 | m_log.Warn("[PHYSICS]: doChange failed for a actor"); | 1761 | m_log.WarnFormat("[PHYSICS]: doChange failed for a actor {0} {1}", |
1859 | }; | 1762 | item.actor.Name, item.what.ToString()); |
1763 | } | ||
1860 | } | 1764 | } |
1861 | ttmp = Util.EnvironmentTickCountSubtract(ttmpstart); | 1765 | ttmp = Util.EnvironmentTickCountSubtract(ttmpstart); |
1862 | if (ttmp > 20) | 1766 | if (ttmp > 20) |
@@ -1994,10 +1898,47 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1994 | mesher.ExpireReleaseMeshs(); | 1898 | mesher.ExpireReleaseMeshs(); |
1995 | m_lastMeshExpire = now; | 1899 | m_lastMeshExpire = now; |
1996 | } | 1900 | } |
1901 | |||
1902 | // information block running in debug only | ||
1997 | /* | 1903 | /* |
1998 | int nactivegeoms = d.SpaceGetNumGeoms(ActiveSpace); | 1904 | int ntopactivegeoms = d.SpaceGetNumGeoms(ActiveSpace); |
1999 | int nstaticgeoms = d.SpaceGetNumGeoms(StaticSpace); | 1905 | int ntopstaticgeoms = d.SpaceGetNumGeoms(StaticSpace); |
1906 | int ngroundgeoms = d.SpaceGetNumGeoms(GroundSpace); | ||
1907 | |||
1908 | int nactivegeoms = 0; | ||
1909 | int nactivespaces = 0; | ||
1910 | |||
1911 | int nstaticgeoms = 0; | ||
1912 | int nstaticspaces = 0; | ||
1913 | IntPtr sp; | ||
1914 | |||
1915 | for (int i = 0; i < ntopactivegeoms; i++) | ||
1916 | { | ||
1917 | sp = d.SpaceGetGeom(ActiveSpace, i); | ||
1918 | if (d.GeomIsSpace(sp)) | ||
1919 | { | ||
1920 | nactivespaces++; | ||
1921 | nactivegeoms += d.SpaceGetNumGeoms(sp); | ||
1922 | } | ||
1923 | else | ||
1924 | nactivegeoms++; | ||
1925 | } | ||
1926 | |||
1927 | for (int i = 0; i < ntopstaticgeoms; i++) | ||
1928 | { | ||
1929 | sp = d.SpaceGetGeom(StaticSpace, i); | ||
1930 | if (d.GeomIsSpace(sp)) | ||
1931 | { | ||
1932 | nstaticspaces++; | ||
1933 | nstaticgeoms += d.SpaceGetNumGeoms(sp); | ||
1934 | } | ||
1935 | else | ||
1936 | nstaticgeoms++; | ||
1937 | } | ||
1938 | |||
2000 | int ntopgeoms = d.SpaceGetNumGeoms(TopSpace); | 1939 | int ntopgeoms = d.SpaceGetNumGeoms(TopSpace); |
1940 | |||
1941 | int totgeoms = nstaticgeoms + nactivegeoms + ngroundgeoms + 1; // one ray | ||
2001 | int nbodies = d.NTotalBodies; | 1942 | int nbodies = d.NTotalBodies; |
2002 | int ngeoms = d.NTotalGeoms; | 1943 | int ngeoms = d.NTotalGeoms; |
2003 | */ | 1944 | */ |
@@ -2294,7 +2235,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2294 | offset, thickness, wrap); | 2235 | offset, thickness, wrap); |
2295 | 2236 | ||
2296 | d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1); | 2237 | d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1); |
2297 | GroundGeom = d.CreateHeightfield(StaticSpace, HeightmapData, 1); | 2238 | |
2239 | GroundGeom = d.CreateHeightfield(GroundSpace, HeightmapData, 1); | ||
2240 | |||
2298 | if (GroundGeom != IntPtr.Zero) | 2241 | if (GroundGeom != IntPtr.Zero) |
2299 | { | 2242 | { |
2300 | d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land)); | 2243 | d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land)); |
@@ -2415,12 +2358,13 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2415 | thickness, wrap); | 2358 | thickness, wrap); |
2416 | 2359 | ||
2417 | // d.GeomUbitTerrainDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1); | 2360 | // d.GeomUbitTerrainDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1); |
2418 | GroundGeom = d.CreateUbitTerrain(StaticSpace, HeightmapData, 1); | 2361 | GroundGeom = d.CreateUbitTerrain(GroundSpace, HeightmapData, 1); |
2419 | if (GroundGeom != IntPtr.Zero) | 2362 | if (GroundGeom != IntPtr.Zero) |
2420 | { | 2363 | { |
2421 | d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land)); | 2364 | d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land)); |
2422 | d.GeomSetCollideBits(GroundGeom, 0); | 2365 | d.GeomSetCollideBits(GroundGeom, 0); |
2423 | 2366 | ||
2367 | |||
2424 | PhysicsActor pa = new NullPhysicsActor(); | 2368 | PhysicsActor pa = new NullPhysicsActor(); |
2425 | pa.Name = "Terrain"; | 2369 | pa.Name = "Terrain"; |
2426 | pa.PhysicsActorType = (int)ActorTypes.Ground; | 2370 | pa.PhysicsActorType = (int)ActorTypes.Ground; |
@@ -2599,6 +2543,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2599 | */ | 2543 | */ |
2600 | public override void Dispose() | 2544 | public override void Dispose() |
2601 | { | 2545 | { |
2546 | if (m_meshWorker != null) | ||
2547 | m_meshWorker.Stop(); | ||
2548 | |||
2602 | lock (OdeLock) | 2549 | lock (OdeLock) |
2603 | { | 2550 | { |
2604 | m_rayCastManager.Dispose(); | 2551 | m_rayCastManager.Dispose(); |
@@ -2633,6 +2580,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2633 | d.GeomDestroy(GroundGeom); | 2580 | d.GeomDestroy(GroundGeom); |
2634 | } | 2581 | } |
2635 | 2582 | ||
2583 | |||
2636 | RegionTerrain.Clear(); | 2584 | RegionTerrain.Clear(); |
2637 | 2585 | ||
2638 | if (TerrainHeightFieldHeightsHandlers.Count > 0) | 2586 | if (TerrainHeightFieldHeightsHandlers.Count > 0) |