diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs')
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs | 203 |
1 files changed, 148 insertions, 55 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs index e427dbc..a7b3f02 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs | |||
@@ -39,6 +39,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
39 | { | 39 | { |
40 | public abstract class BSShape | 40 | public abstract class BSShape |
41 | { | 41 | { |
42 | private static string LogHeader = "[BULLETSIM SHAPE]"; | ||
43 | |||
42 | public int referenceCount { get; set; } | 44 | public int referenceCount { get; set; } |
43 | public DateTime lastReferenced { get; set; } | 45 | public DateTime lastReferenced { get; set; } |
44 | public BulletShape physShapeInfo { get; set; } | 46 | public BulletShape physShapeInfo { get; set; } |
@@ -56,49 +58,6 @@ public abstract class BSShape | |||
56 | physShapeInfo = pShape; | 58 | physShapeInfo = pShape; |
57 | } | 59 | } |
58 | 60 | ||
59 | // Get a reference to a physical shape. Create if it doesn't exist | ||
60 | public static BSShape GetShapeReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) | ||
61 | { | ||
62 | BSShape ret = null; | ||
63 | |||
64 | if (prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE) | ||
65 | { | ||
66 | // an avatar capsule is close to a native shape (it is not shared) | ||
67 | ret = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_CAPSULE, | ||
68 | FixedShapeKey.KEY_CAPSULE); | ||
69 | physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret); | ||
70 | } | ||
71 | |||
72 | // Compound shapes are handled special as they are rebuilt from scratch. | ||
73 | // This isn't too great a hardship since most of the child shapes will have already been created. | ||
74 | if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND) | ||
75 | { | ||
76 | // Getting a reference to a compound shape gets you the compound shape with the root prim shape added | ||
77 | ret = BSShapeCompound.GetReference(physicsScene, prim); | ||
78 | physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret); | ||
79 | } | ||
80 | |||
81 | // Avatars have their own unique shape | ||
82 | if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_AVATAR) | ||
83 | { | ||
84 | // Getting a reference to a compound shape gets you the compound shape with the root prim shape added | ||
85 | ret = BSShapeAvatar.GetReference(prim); | ||
86 | physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,avatarShape,shape={1}", prim.LocalID, ret); | ||
87 | } | ||
88 | |||
89 | if (ret == null) | ||
90 | ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim); | ||
91 | |||
92 | return ret; | ||
93 | } | ||
94 | private static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) | ||
95 | { | ||
96 | // TODO: work needed here!! | ||
97 | BSShapeMesh.GetReference(physicsScene, forceRebuild, prim); | ||
98 | BSShapeHull.GetReference(physicsScene, forceRebuild, prim); | ||
99 | return null; | ||
100 | } | ||
101 | |||
102 | // Called when this shape is being used again. | 61 | // Called when this shape is being used again. |
103 | public virtual void IncrementReference() | 62 | public virtual void IncrementReference() |
104 | { | 63 | { |
@@ -116,6 +75,27 @@ public abstract class BSShape | |||
116 | // Release the use of a physical shape. | 75 | // Release the use of a physical shape. |
117 | public abstract void Dereference(BSScene physicsScene); | 76 | public abstract void Dereference(BSScene physicsScene); |
118 | 77 | ||
78 | // Return 'true' if there is an allocated physics physical shape under this class instance. | ||
79 | public virtual bool HasPhysicalShape | ||
80 | { | ||
81 | get | ||
82 | { | ||
83 | if (physShapeInfo != null) | ||
84 | return physShapeInfo.HasPhysicalShape; | ||
85 | return false; | ||
86 | } | ||
87 | } | ||
88 | public virtual BSPhysicsShapeType ShapeType | ||
89 | { | ||
90 | get | ||
91 | { | ||
92 | BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN; | ||
93 | if (physShapeInfo != null && physShapeInfo.HasPhysicalShape) | ||
94 | ret = physShapeInfo.shapeType; | ||
95 | return ret; | ||
96 | } | ||
97 | } | ||
98 | |||
119 | // Returns a string for debugging that uniquily identifies the memory used by this instance | 99 | // Returns a string for debugging that uniquily identifies the memory used by this instance |
120 | public virtual string AddrString | 100 | public virtual string AddrString |
121 | { | 101 | { |
@@ -132,6 +112,119 @@ public abstract class BSShape | |||
132 | buff.Append(">"); | 112 | buff.Append(">"); |
133 | return buff.ToString(); | 113 | return buff.ToString(); |
134 | } | 114 | } |
115 | |||
116 | // Create a hash of all the shape parameters to be used as a key for this particular shape. | ||
117 | public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) | ||
118 | { | ||
119 | // level of detail based on size and type of the object | ||
120 | float lod = BSParam.MeshLOD; | ||
121 | if (pbs.SculptEntry) | ||
122 | lod = BSParam.SculptLOD; | ||
123 | |||
124 | // Mega prims usually get more detail because one can interact with shape approximations at this size. | ||
125 | float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z)); | ||
126 | if (maxAxis > BSParam.MeshMegaPrimThreshold) | ||
127 | lod = BSParam.MeshMegaPrimLOD; | ||
128 | |||
129 | retLod = lod; | ||
130 | return pbs.GetMeshKey(size, lod); | ||
131 | } | ||
132 | |||
133 | // The creation of a mesh or hull can fail if an underlying asset is not available. | ||
134 | // There are two cases: 1) the asset is not in the cache and it needs to be fetched; | ||
135 | // and 2) the asset cannot be converted (like failed decompression of JPEG2000s). | ||
136 | // The first case causes the asset to be fetched. The second case requires | ||
137 | // us to not loop forever. | ||
138 | // Called after creating a physical mesh or hull. If the physical shape was created, | ||
139 | // just return. | ||
140 | public static BulletShape VerifyMeshCreated(BSScene physicsScene, BulletShape newShape, BSPhysObject prim) | ||
141 | { | ||
142 | // If the shape was successfully created, nothing more to do | ||
143 | if (newShape.HasPhysicalShape) | ||
144 | return newShape; | ||
145 | |||
146 | // VerifyMeshCreated is called after trying to create the mesh. If we think the asset had been | ||
147 | // fetched but we end up here again, the meshing of the asset must have failed. | ||
148 | // Prevent trying to keep fetching the mesh by declaring failure. | ||
149 | if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched) | ||
150 | { | ||
151 | prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; | ||
152 | physicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}", | ||
153 | LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture); | ||
154 | } | ||
155 | else | ||
156 | { | ||
157 | // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset | ||
158 | if (prim.BaseShape.SculptEntry | ||
159 | && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Failed | ||
160 | && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Waiting | ||
161 | && prim.BaseShape.SculptTexture != OMV.UUID.Zero | ||
162 | ) | ||
163 | { | ||
164 | physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID); | ||
165 | // Multiple requestors will know we're waiting for this asset | ||
166 | prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting; | ||
167 | |||
168 | BSPhysObject xprim = prim; | ||
169 | Util.FireAndForget(delegate | ||
170 | { | ||
171 | RequestAssetDelegate assetProvider = physicsScene.RequestAssetMethod; | ||
172 | if (assetProvider != null) | ||
173 | { | ||
174 | BSPhysObject yprim = xprim; // probably not necessary, but, just in case. | ||
175 | assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset) | ||
176 | { | ||
177 | bool assetFound = false; | ||
178 | string mismatchIDs = String.Empty; // DEBUG DEBUG | ||
179 | if (asset != null && yprim.BaseShape.SculptEntry) | ||
180 | { | ||
181 | if (yprim.BaseShape.SculptTexture.ToString() == asset.ID) | ||
182 | { | ||
183 | yprim.BaseShape.SculptData = asset.Data; | ||
184 | // This will cause the prim to see that the filler shape is not the right | ||
185 | // one and try again to build the object. | ||
186 | // No race condition with the normal shape setting since the rebuild is at taint time. | ||
187 | yprim.ForceBodyShapeRebuild(false /* inTaintTime */); | ||
188 | assetFound = true; | ||
189 | } | ||
190 | else | ||
191 | { | ||
192 | mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID; | ||
193 | } | ||
194 | } | ||
195 | if (assetFound) | ||
196 | yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched; | ||
197 | else | ||
198 | yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; | ||
199 | physicsScene.DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}", | ||
200 | yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs ); | ||
201 | }); | ||
202 | } | ||
203 | else | ||
204 | { | ||
205 | xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; | ||
206 | physicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}", | ||
207 | LogHeader, physicsScene.Name); | ||
208 | } | ||
209 | }); | ||
210 | } | ||
211 | else | ||
212 | { | ||
213 | if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed) | ||
214 | { | ||
215 | physicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}", | ||
216 | LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture); | ||
217 | } | ||
218 | } | ||
219 | } | ||
220 | |||
221 | // While we wait for the mesh defining asset to be loaded, stick in a simple box for the object. | ||
222 | BSShape fillShape = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); | ||
223 | physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,boxTempShape", prim.LocalID); | ||
224 | |||
225 | return fillShape.physShapeInfo; | ||
226 | } | ||
227 | |||
135 | } | 228 | } |
136 | 229 | ||
137 | // ============================================================================================================ | 230 | // ============================================================================================================ |
@@ -199,7 +292,7 @@ public class BSShapeNative : BSShape | |||
199 | physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", | 292 | physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", |
200 | LogHeader, prim.LocalID, shapeType); | 293 | LogHeader, prim.LocalID, shapeType); |
201 | } | 294 | } |
202 | newShape.type = shapeType; | 295 | newShape.shapeType = shapeType; |
203 | newShape.isNativeShape = true; | 296 | newShape.isNativeShape = true; |
204 | newShape.shapeKey = (UInt64)shapeKey; | 297 | newShape.shapeKey = (UInt64)shapeKey; |
205 | return newShape; | 298 | return newShape; |
@@ -219,10 +312,11 @@ public class BSShapeMesh : BSShape | |||
219 | public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) | 312 | public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) |
220 | { | 313 | { |
221 | float lod; | 314 | float lod; |
222 | System.UInt64 newMeshKey = BSShapeCollection.ComputeShapeKey(prim.Size, prim.BaseShape, out lod); | 315 | System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod); |
223 | 316 | ||
224 | physicsScene.DetailLog("{0},BSShapeMesh,getReference,oldKey={1},newKey={2},size={3},lod={4}", | 317 | physicsScene.DetailLog("{0},BSShapeMesh,getReference,oldKey={1},newKey={2},size={3},lod={4}", |
225 | prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"), prim.Size, lod); | 318 | prim.LocalID, prim.PhysShape.physShapeInfo.shapeKey.ToString("X"), |
319 | newMeshKey.ToString("X"), prim.Size, lod); | ||
226 | 320 | ||
227 | BSShapeMesh retMesh = new BSShapeMesh(new BulletShape()); | 321 | BSShapeMesh retMesh = new BSShapeMesh(new BulletShape()); |
228 | lock (Meshes) | 322 | lock (Meshes) |
@@ -238,8 +332,8 @@ public class BSShapeMesh : BSShape | |||
238 | BulletShape newShape = retMesh.CreatePhysicalMesh(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod); | 332 | BulletShape newShape = retMesh.CreatePhysicalMesh(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod); |
239 | 333 | ||
240 | // Check to see if mesh was created (might require an asset). | 334 | // Check to see if mesh was created (might require an asset). |
241 | newShape = BSShapeCollection.VerifyMeshCreated(physicsScene, newShape, prim); | 335 | newShape = VerifyMeshCreated(physicsScene, newShape, prim); |
242 | if (newShape.type == BSPhysicsShapeType.SHAPE_MESH) | 336 | if (newShape.shapeType == BSPhysicsShapeType.SHAPE_MESH) |
243 | { | 337 | { |
244 | // If a mesh was what was created, remember the built shape for later sharing. | 338 | // If a mesh was what was created, remember the built shape for later sharing. |
245 | Meshes.Add(newMeshKey, retMesh); | 339 | Meshes.Add(newMeshKey, retMesh); |
@@ -360,10 +454,10 @@ public class BSShapeHull : BSShape | |||
360 | public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) | 454 | public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) |
361 | { | 455 | { |
362 | float lod; | 456 | float lod; |
363 | System.UInt64 newHullKey = BSShapeCollection.ComputeShapeKey(prim.Size, prim.BaseShape, out lod); | 457 | System.UInt64 newHullKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod); |
364 | 458 | ||
365 | physicsScene.DetailLog("{0},BSShapeHull,getReference,oldKey={1},newKey={2},size={3},lod={4}", | 459 | physicsScene.DetailLog("{0},BSShapeHull,getReference,oldKey={1},newKey={2},size={3},lod={4}", |
366 | prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"), prim.Size, lod); | 460 | prim.LocalID, prim.PhysShape.physShapeInfo.shapeKey.ToString("X"), newHullKey.ToString("X"), prim.Size, lod); |
367 | 461 | ||
368 | BSShapeHull retHull = new BSShapeHull(new BulletShape()); | 462 | BSShapeHull retHull = new BSShapeHull(new BulletShape()); |
369 | lock (Hulls) | 463 | lock (Hulls) |
@@ -379,8 +473,8 @@ public class BSShapeHull : BSShape | |||
379 | BulletShape newShape = retHull.CreatePhysicalHull(physicsScene, prim, newHullKey, prim.BaseShape, prim.Size, lod); | 473 | BulletShape newShape = retHull.CreatePhysicalHull(physicsScene, prim, newHullKey, prim.BaseShape, prim.Size, lod); |
380 | 474 | ||
381 | // Check to see if mesh was created (might require an asset). | 475 | // Check to see if mesh was created (might require an asset). |
382 | newShape = BSShapeCollection.VerifyMeshCreated(physicsScene, newShape, prim); | 476 | newShape = VerifyMeshCreated(physicsScene, newShape, prim); |
383 | if (newShape.type == BSPhysicsShapeType.SHAPE_MESH) | 477 | if (newShape.shapeType == BSPhysicsShapeType.SHAPE_MESH) |
384 | { | 478 | { |
385 | // If a mesh was what was created, remember the built shape for later sharing. | 479 | // If a mesh was what was created, remember the built shape for later sharing. |
386 | Hulls.Add(newHullKey, retHull); | 480 | Hulls.Add(newHullKey, retHull); |
@@ -569,7 +663,6 @@ public class BSShapeHull : BSShape | |||
569 | } | 663 | } |
570 | } | 664 | } |
571 | 665 | ||
572 | |||
573 | // ============================================================================================================ | 666 | // ============================================================================================================ |
574 | public class BSShapeCompound : BSShape | 667 | public class BSShapeCompound : BSShape |
575 | { | 668 | { |
@@ -589,9 +682,9 @@ public class BSShapeCompound : BSShape | |||
589 | { | 682 | { |
590 | // Failed the sanity check!! | 683 | // Failed the sanity check!! |
591 | physicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}", | 684 | physicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}", |
592 | LogHeader, physShapeInfo.type, physShapeInfo.AddrString); | 685 | LogHeader, physShapeInfo.shapeType, physShapeInfo.AddrString); |
593 | physicsScene.DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}", | 686 | physicsScene.DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}", |
594 | BSScene.DetailLogZero, physShapeInfo.type, physShapeInfo.AddrString); | 687 | BSScene.DetailLogZero, physShapeInfo.shapeType, physShapeInfo.AddrString); |
595 | return; | 688 | return; |
596 | } | 689 | } |
597 | 690 | ||