aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics')
-rw-r--r--OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs4
-rw-r--r--OpenSim/Region/Physics/Manager/IMesher.cs13
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsActor.cs17
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsScene.cs5
-rw-r--r--OpenSim/Region/Physics/Manager/ZeroMesher.cs9
-rw-r--r--OpenSim/Region/Physics/Meshing/Mesh.cs7
-rw-r--r--OpenSim/Region/Physics/Meshing/Meshmerizer.cs31
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEPrim.cs55
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs11
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdeScene.cs2
-rw-r--r--OpenSim/Region/Physics/UbitMeshing/Mesh.cs517
-rw-r--r--OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs501
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs1
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs931
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs858
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs18
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs454
17 files changed, 2271 insertions, 1163 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 eb02536..7a0857f 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -100,6 +100,9 @@ namespace OpenSim.Region.Physics.OdePlugin
100 private Vector3 m_taintAngularLock = Vector3.One; 100 private Vector3 m_taintAngularLock = Vector3.One;
101 private IntPtr Amotor = IntPtr.Zero; 101 private IntPtr Amotor = IntPtr.Zero;
102 102
103 private object m_assetsLock = new object();
104 private bool m_assetFailed = false;
105
103 private Vector3 m_PIDTarget; 106 private Vector3 m_PIDTarget;
104 private float m_PIDTau; 107 private float m_PIDTau;
105 private float PID_D = 35f; 108 private float PID_D = 35f;
@@ -282,6 +285,7 @@ namespace OpenSim.Region.Physics.OdePlugin
282 } 285 }
283 286
284 m_taintadd = true; 287 m_taintadd = true;
288 m_assetFailed = false;
285 _parent_scene.AddPhysicsActorTaint(this); 289 _parent_scene.AddPhysicsActorTaint(this);
286 } 290 }
287 291
@@ -604,8 +608,8 @@ namespace OpenSim.Region.Physics.OdePlugin
604 break; 608 break;
605 609
606 case HollowShape.Circle: 610 case HollowShape.Circle:
607 // 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
608 // Cylinder hollow volume calculation 612 // Cyllinder hollow volume calculation
609 613
610 hollowVolume *= 0.1963495f * 3.07920140172638f; 614 hollowVolume *= 0.1963495f * 3.07920140172638f;
611 break; 615 break;
@@ -1498,6 +1502,8 @@ Console.WriteLine("CreateGeom:");
1498 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);
1499 // 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.
1500 // m_log.Debug(m_localID); 1504 // m_log.Debug(m_localID);
1505 if (mesh == null)
1506 CheckMeshAsset();
1501 } 1507 }
1502 1508
1503#if SPAM 1509#if SPAM
@@ -1997,7 +2003,12 @@ Console.WriteLine(" JointCreateFixed");
1997 // 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
1998 2004
1999 if (_parent_scene.needsMeshing(_pbs)) 2005 if (_parent_scene.needsMeshing(_pbs))
2006 {
2000 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
2001 } 2012 }
2002 2013
2003 CreateGeom(m_targetSpace, mesh); 2014 CreateGeom(m_targetSpace, mesh);
@@ -2057,6 +2068,8 @@ Console.WriteLine(" JointCreateFixed");
2057 /// </summary> 2068 /// </summary>
2058 private void changeshape() 2069 private void changeshape()
2059 { 2070 {
2071 m_taintshape = false;
2072
2060 // Cleanup of old prim geometry and Bodies 2073 // Cleanup of old prim geometry and Bodies
2061 if (IsPhysical && Body != IntPtr.Zero) 2074 if (IsPhysical && Body != IntPtr.Zero)
2062 { 2075 {
@@ -2084,6 +2097,7 @@ Console.WriteLine(" JointCreateFixed");
2084 2097
2085 IMesh mesh = null; 2098 IMesh mesh = null;
2086 2099
2100
2087 if (_parent_scene.needsMeshing(_pbs)) 2101 if (_parent_scene.needsMeshing(_pbs))
2088 { 2102 {
2089 // 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
@@ -2094,6 +2108,8 @@ Console.WriteLine(" JointCreateFixed");
2094 2108
2095 // createmesh returns null when it doesn't mesh. 2109 // createmesh returns null when it doesn't mesh.
2096 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();
2097 } 2113 }
2098 2114
2099 CreateGeom(m_targetSpace, mesh); 2115 CreateGeom(m_targetSpace, mesh);
@@ -2130,7 +2146,7 @@ Console.WriteLine(" JointCreateFixed");
2130 } 2146 }
2131 2147
2132 resetCollisionAccounting(); 2148 resetCollisionAccounting();
2133 m_taintshape = false; 2149// m_taintshape = false;
2134 } 2150 }
2135 2151
2136 /// <summary> 2152 /// <summary>
@@ -2396,6 +2412,7 @@ Console.WriteLine(" JointCreateFixed");
2396 set 2412 set
2397 { 2413 {
2398 _pbs = value; 2414 _pbs = value;
2415 m_assetFailed = false;
2399 m_taintshape = true; 2416 m_taintshape = true;
2400 } 2417 }
2401 } 2418 }
@@ -3234,5 +3251,37 @@ Console.WriteLine(" JointCreateFixed");
3234 { 3251 {
3235 m_material = pMaterial; 3252 m_material = pMaterial;
3236 } 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 }
3237 } 3286 }
3238} \ 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 cbe21e2..d53bd90 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
@@ -4320,4 +4320,4 @@ namespace OpenSim.Region.Physics.OdePlugin
4320 m_stats[ODEPrimUpdateFrameMsStatName] = 0; 4320 m_stats[ODEPrimUpdateFrameMsStatName] = 0;
4321 } 4321 }
4322 } 4322 }
4323} \ No newline at end of file 4323}
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;
32using OpenSim.Region.Physics.Manager; 32using OpenSim.Region.Physics.Manager;
33using PrimMesher; 33using PrimMesher;
34using OpenMetaverse; 34using OpenMetaverse;
35using System.Runtime.Serialization;
36using System.Runtime.Serialization.Formatters.Binary;
35 37
36namespace OpenSim.Region.Physics.Meshing 38namespace 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;
42using System.IO; 42using System.IO;
43using ComponentAce.Compression.Libs.zlib; 43using ComponentAce.Compression.Libs.zlib;
44using OpenSim.Region.Physics.ConvexDecompositionDotNet; 44using OpenSim.Region.Physics.ConvexDecompositionDotNet;
45using System.Runtime.Serialization;
46using System.Runtime.Serialization.Formatters.Binary;
45 47
46namespace OpenSim.Region.Physics.Meshing 48namespace 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
5using System;
6using System.Threading;
7using System.Collections.Generic;
8using System.IO;
9using System.Reflection;
10using System.Runtime.InteropServices;
11using System.Text;
12using OpenSim.Framework;
13using OpenSim.Region.Physics.Manager;
14using OdeAPI;
15using log4net;
16using Nini.Config;
17using OpenMetaverse;
18
19namespace 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)