aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs3
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs10
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs96
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs296
4 files changed, 240 insertions, 165 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index fc4526b..623ac8f 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -200,10 +200,9 @@ public class BSCharacter : BSPhysObject
200 } 200 }
201 } 201 }
202 public override OMV.Vector3 Scale { get; set; } 202 public override OMV.Vector3 Scale { get; set; }
203 private PrimitiveBaseShape _pbs;
204 public override PrimitiveBaseShape Shape 203 public override PrimitiveBaseShape Shape
205 { 204 {
206 set { _pbs = value;} 205 set { BaseShape = value; }
207 } 206 }
208 207
209 public override bool Grabbed { 208 public override bool Grabbed {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index 202052d..ead6a08 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -47,6 +47,7 @@ public abstract class BSPhysObject : PhysicsActor
47 TypeName = typeName; 47 TypeName = typeName;
48 48
49 Linkset = new BSLinkset(PhysicsScene, this); 49 Linkset = new BSLinkset(PhysicsScene, this);
50 LastAssetBuildFailed = false;
50 51
51 CollisionCollection = new CollisionEventUpdate(); 52 CollisionCollection = new CollisionEventUpdate();
52 SubscribedEventsMs = 0; 53 SubscribedEventsMs = 0;
@@ -69,6 +70,13 @@ public abstract class BSPhysObject : PhysicsActor
69 // Reference to the physical shape (btCollisionShape) of this object 70 // Reference to the physical shape (btCollisionShape) of this object
70 public BulletShape BSShape; 71 public BulletShape BSShape;
71 72
73 // 'true' if the mesh's underlying asset failed to build.
74 // This will keep us from looping after the first time the build failed.
75 public bool LastAssetBuildFailed { get; set; }
76
77 // The objects base shape information. Null if not a prim type shape.
78 public PrimitiveBaseShape BaseShape { get; protected set; }
79
72 // When the physical properties are updated, an EntityProperty holds the update values. 80 // When the physical properties are updated, an EntityProperty holds the update values.
73 // Keep the current and last EntityProperties to enable computation of differences 81 // Keep the current and last EntityProperties to enable computation of differences
74 // between the current update and the previous values. 82 // between the current update and the previous values.
@@ -101,6 +109,8 @@ public abstract class BSPhysObject : PhysicsActor
101 109
102 public abstract float ForceBuoyancy { get; set; } 110 public abstract float ForceBuoyancy { get; set; }
103 111
112 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
113
104 #region Collisions 114 #region Collisions
105 115
106 // Requested number of milliseconds between collision events. Zero means disabled. 116 // Requested number of milliseconds between collision events. Zero means disabled.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 8013e68..aeeb4dd 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -46,8 +46,6 @@ public sealed class BSPrim : BSPhysObject
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 private static readonly string LogHeader = "[BULLETS PRIM]"; 47 private static readonly string LogHeader = "[BULLETS PRIM]";
48 48
49 private PrimitiveBaseShape _pbs;
50
51 // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. 49 // _size is what the user passed. Scale is what we pass to the physics engine with the mesh.
52 // Often Scale is unity because the meshmerizer will apply _size when creating the mesh. 50 // Often Scale is unity because the meshmerizer will apply _size when creating the mesh.
53 private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user 51 private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user
@@ -103,7 +101,7 @@ public sealed class BSPrim : BSPhysObject
103 _buoyancy = 1f; 101 _buoyancy = 1f;
104 _velocity = OMV.Vector3.Zero; 102 _velocity = OMV.Vector3.Zero;
105 _rotationalVelocity = OMV.Vector3.Zero; 103 _rotationalVelocity = OMV.Vector3.Zero;
106 _pbs = pbs; 104 BaseShape = pbs;
107 _isPhysical = pisPhysical; 105 _isPhysical = pisPhysical;
108 _isVolumeDetect = false; 106 _isVolumeDetect = false;
109 _friction = PhysicsScene.Params.defaultFriction; // TODO: compute based on object material 107 _friction = PhysicsScene.Params.defaultFriction; // TODO: compute based on object material
@@ -160,14 +158,7 @@ public sealed class BSPrim : BSPhysObject
160 get { return _size; } 158 get { return _size; }
161 set { 159 set {
162 _size = value; 160 _size = value;
163 PhysicsScene.TaintedObject("BSPrim.setSize", delegate() 161 ForceBodyShapeRebuild(false);
164 {
165 _mass = CalculateMass(); // changing size changes the mass
166 // Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct
167 // scale and margins are set.
168 CreateGeomAndObject(true);
169 // DetailLog("{0},BSPrim.setSize,size={1},scale={2},mass={3},physical={4}", LocalID, _size, Scale, _mass, IsPhysical);
170 });
171 } 162 }
172 } 163 }
173 // Scale is what we set in the physics engine. It is different than 'size' in that 164 // Scale is what we set in the physics engine. It is different than 'size' in that
@@ -176,14 +167,23 @@ public sealed class BSPrim : BSPhysObject
176 167
177 public override PrimitiveBaseShape Shape { 168 public override PrimitiveBaseShape Shape {
178 set { 169 set {
179 _pbs = value; 170 BaseShape = value;
180 PhysicsScene.TaintedObject("BSPrim.setShape", delegate() 171 ForceBodyShapeRebuild(false);
181 {
182 _mass = CalculateMass(); // changing the shape changes the mass
183 CreateGeomAndObject(true);
184 });
185 } 172 }
186 } 173 }
174 public override bool ForceBodyShapeRebuild(bool inTaintTime)
175 {
176 BSScene.TaintCallback rebuildOperation = delegate()
177 {
178 _mass = CalculateMass(); // changing the shape changes the mass
179 CreateGeomAndObject(true);
180 };
181 if (inTaintTime)
182 rebuildOperation();
183 else
184 PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", rebuildOperation);
185 return true;
186 }
187 public override bool Grabbed { 187 public override bool Grabbed {
188 set { _grabbed = value; 188 set { _grabbed = value;
189 } 189 }
@@ -924,19 +924,19 @@ public sealed class BSPrim : BSPhysObject
924 float tmp; 924 float tmp;
925 925
926 float returnMass = 0; 926 float returnMass = 0;
927 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f; 927 float hollowAmount = (float)BaseShape.ProfileHollow * 2.0e-5f;
928 float hollowVolume = hollowAmount * hollowAmount; 928 float hollowVolume = hollowAmount * hollowAmount;
929 929
930 switch (_pbs.ProfileShape) 930 switch (BaseShape.ProfileShape)
931 { 931 {
932 case ProfileShape.Square: 932 case ProfileShape.Square:
933 // default box 933 // default box
934 934
935 if (_pbs.PathCurve == (byte)Extrusion.Straight) 935 if (BaseShape.PathCurve == (byte)Extrusion.Straight)
936 { 936 {
937 if (hollowAmount > 0.0) 937 if (hollowAmount > 0.0)
938 { 938 {
939 switch (_pbs.HollowShape) 939 switch (BaseShape.HollowShape)
940 { 940 {
941 case HollowShape.Square: 941 case HollowShape.Square:
942 case HollowShape.Same: 942 case HollowShape.Same:
@@ -960,19 +960,19 @@ public sealed class BSPrim : BSPhysObject
960 } 960 }
961 } 961 }
962 962
963 else if (_pbs.PathCurve == (byte)Extrusion.Curve1) 963 else if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
964 { 964 {
965 //a tube 965 //a tube
966 966
967 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX); 967 volume *= 0.78539816339e-2f * (float)(200 - BaseShape.PathScaleX);
968 tmp= 1.0f -2.0e-2f * (float)(200 - _pbs.PathScaleY); 968 tmp= 1.0f -2.0e-2f * (float)(200 - BaseShape.PathScaleY);
969 volume -= volume*tmp*tmp; 969 volume -= volume*tmp*tmp;
970 970
971 if (hollowAmount > 0.0) 971 if (hollowAmount > 0.0)
972 { 972 {
973 hollowVolume *= hollowAmount; 973 hollowVolume *= hollowAmount;
974 974
975 switch (_pbs.HollowShape) 975 switch (BaseShape.HollowShape)
976 { 976 {
977 case HollowShape.Square: 977 case HollowShape.Square:
978 case HollowShape.Same: 978 case HollowShape.Same:
@@ -997,13 +997,13 @@ public sealed class BSPrim : BSPhysObject
997 997
998 case ProfileShape.Circle: 998 case ProfileShape.Circle:
999 999
1000 if (_pbs.PathCurve == (byte)Extrusion.Straight) 1000 if (BaseShape.PathCurve == (byte)Extrusion.Straight)
1001 { 1001 {
1002 volume *= 0.78539816339f; // elipse base 1002 volume *= 0.78539816339f; // elipse base
1003 1003
1004 if (hollowAmount > 0.0) 1004 if (hollowAmount > 0.0)
1005 { 1005 {
1006 switch (_pbs.HollowShape) 1006 switch (BaseShape.HollowShape)
1007 { 1007 {
1008 case HollowShape.Same: 1008 case HollowShape.Same:
1009 case HollowShape.Circle: 1009 case HollowShape.Circle:
@@ -1025,10 +1025,10 @@ public sealed class BSPrim : BSPhysObject
1025 } 1025 }
1026 } 1026 }
1027 1027
1028 else if (_pbs.PathCurve == (byte)Extrusion.Curve1) 1028 else if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
1029 { 1029 {
1030 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX); 1030 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - BaseShape.PathScaleX);
1031 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); 1031 tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY);
1032 volume *= (1.0f - tmp * tmp); 1032 volume *= (1.0f - tmp * tmp);
1033 1033
1034 if (hollowAmount > 0.0) 1034 if (hollowAmount > 0.0)
@@ -1037,7 +1037,7 @@ public sealed class BSPrim : BSPhysObject
1037 // calculate the hollow volume by it's shape compared to the prim shape 1037 // calculate the hollow volume by it's shape compared to the prim shape
1038 hollowVolume *= hollowAmount; 1038 hollowVolume *= hollowAmount;
1039 1039
1040 switch (_pbs.HollowShape) 1040 switch (BaseShape.HollowShape)
1041 { 1041 {
1042 case HollowShape.Same: 1042 case HollowShape.Same:
1043 case HollowShape.Circle: 1043 case HollowShape.Circle:
@@ -1061,7 +1061,7 @@ public sealed class BSPrim : BSPhysObject
1061 break; 1061 break;
1062 1062
1063 case ProfileShape.HalfCircle: 1063 case ProfileShape.HalfCircle:
1064 if (_pbs.PathCurve == (byte)Extrusion.Curve1) 1064 if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
1065 { 1065 {
1066 volume *= 0.52359877559829887307710723054658f; 1066 volume *= 0.52359877559829887307710723054658f;
1067 } 1067 }
@@ -1069,7 +1069,7 @@ public sealed class BSPrim : BSPhysObject
1069 1069
1070 case ProfileShape.EquilateralTriangle: 1070 case ProfileShape.EquilateralTriangle:
1071 1071
1072 if (_pbs.PathCurve == (byte)Extrusion.Straight) 1072 if (BaseShape.PathCurve == (byte)Extrusion.Straight)
1073 { 1073 {
1074 volume *= 0.32475953f; 1074 volume *= 0.32475953f;
1075 1075
@@ -1077,7 +1077,7 @@ public sealed class BSPrim : BSPhysObject
1077 { 1077 {
1078 1078
1079 // calculate the hollow volume by it's shape compared to the prim shape 1079 // calculate the hollow volume by it's shape compared to the prim shape
1080 switch (_pbs.HollowShape) 1080 switch (BaseShape.HollowShape)
1081 { 1081 {
1082 case HollowShape.Same: 1082 case HollowShape.Same:
1083 case HollowShape.Triangle: 1083 case HollowShape.Triangle:
@@ -1102,11 +1102,11 @@ public sealed class BSPrim : BSPhysObject
1102 volume *= (1.0f - hollowVolume); 1102 volume *= (1.0f - hollowVolume);
1103 } 1103 }
1104 } 1104 }
1105 else if (_pbs.PathCurve == (byte)Extrusion.Curve1) 1105 else if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
1106 { 1106 {
1107 volume *= 0.32475953f; 1107 volume *= 0.32475953f;
1108 volume *= 0.01f * (float)(200 - _pbs.PathScaleX); 1108 volume *= 0.01f * (float)(200 - BaseShape.PathScaleX);
1109 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); 1109 tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY);
1110 volume *= (1.0f - tmp * tmp); 1110 volume *= (1.0f - tmp * tmp);
1111 1111
1112 if (hollowAmount > 0.0) 1112 if (hollowAmount > 0.0)
@@ -1114,7 +1114,7 @@ public sealed class BSPrim : BSPhysObject
1114 1114
1115 hollowVolume *= hollowAmount; 1115 hollowVolume *= hollowAmount;
1116 1116
1117 switch (_pbs.HollowShape) 1117 switch (BaseShape.HollowShape)
1118 { 1118 {
1119 case HollowShape.Same: 1119 case HollowShape.Same:
1120 case HollowShape.Triangle: 1120 case HollowShape.Triangle:
@@ -1154,26 +1154,26 @@ public sealed class BSPrim : BSPhysObject
1154 float profileBegin; 1154 float profileBegin;
1155 float profileEnd; 1155 float profileEnd;
1156 1156
1157 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible) 1157 if (BaseShape.PathCurve == (byte)Extrusion.Straight || BaseShape.PathCurve == (byte)Extrusion.Flexible)
1158 { 1158 {
1159 taperX1 = _pbs.PathScaleX * 0.01f; 1159 taperX1 = BaseShape.PathScaleX * 0.01f;
1160 if (taperX1 > 1.0f) 1160 if (taperX1 > 1.0f)
1161 taperX1 = 2.0f - taperX1; 1161 taperX1 = 2.0f - taperX1;
1162 taperX = 1.0f - taperX1; 1162 taperX = 1.0f - taperX1;
1163 1163
1164 taperY1 = _pbs.PathScaleY * 0.01f; 1164 taperY1 = BaseShape.PathScaleY * 0.01f;
1165 if (taperY1 > 1.0f) 1165 if (taperY1 > 1.0f)
1166 taperY1 = 2.0f - taperY1; 1166 taperY1 = 2.0f - taperY1;
1167 taperY = 1.0f - taperY1; 1167 taperY = 1.0f - taperY1;
1168 } 1168 }
1169 else 1169 else
1170 { 1170 {
1171 taperX = _pbs.PathTaperX * 0.01f; 1171 taperX = BaseShape.PathTaperX * 0.01f;
1172 if (taperX < 0.0f) 1172 if (taperX < 0.0f)
1173 taperX = -taperX; 1173 taperX = -taperX;
1174 taperX1 = 1.0f - taperX; 1174 taperX1 = 1.0f - taperX;
1175 1175
1176 taperY = _pbs.PathTaperY * 0.01f; 1176 taperY = BaseShape.PathTaperY * 0.01f;
1177 if (taperY < 0.0f) 1177 if (taperY < 0.0f)
1178 taperY = -taperY; 1178 taperY = -taperY;
1179 taperY1 = 1.0f - taperY; 1179 taperY1 = 1.0f - taperY;
@@ -1183,13 +1183,13 @@ public sealed class BSPrim : BSPhysObject
1183 1183
1184 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); 1184 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
1185 1185
1186 pathBegin = (float)_pbs.PathBegin * 2.0e-5f; 1186 pathBegin = (float)BaseShape.PathBegin * 2.0e-5f;
1187 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f; 1187 pathEnd = 1.0f - (float)BaseShape.PathEnd * 2.0e-5f;
1188 volume *= (pathEnd - pathBegin); 1188 volume *= (pathEnd - pathBegin);
1189 1189
1190 // this is crude aproximation 1190 // this is crude aproximation
1191 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f; 1191 profileBegin = (float)BaseShape.ProfileBegin * 2.0e-5f;
1192 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f; 1192 profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f;
1193 volume *= (profileEnd - profileBegin); 1193 volume *= (profileEnd - profileBegin);
1194 1194
1195 returnMass = _density * volume; 1195 returnMass = _density * volume;
@@ -1251,7 +1251,7 @@ public sealed class BSPrim : BSPhysObject
1251 // Create the correct physical representation for this type of object. 1251 // Create the correct physical representation for this type of object.
1252 // Updates BSBody and BSShape with the new information. 1252 // Updates BSBody and BSShape with the new information.
1253 // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. 1253 // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary.
1254 PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, _pbs, 1254 PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, BaseShape,
1255 null, delegate(BulletBody dBody) 1255 null, delegate(BulletBody dBody)
1256 { 1256 {
1257 // Called if the current prim body is about to be destroyed. 1257 // Called if the current prim body is about to be destroyed.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 861ffe7..d3ba273 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -117,7 +117,7 @@ public class BSShapeCollection : IDisposable
117 117
118 // Track another user of a body 118 // Track another user of a body
119 // We presume the caller has allocated the body. 119 // We presume the caller has allocated the body.
120 // Bodies only have one user so the reference count is either 1 or 0. 120 // Bodies only have one user so the body is just put into the world if not already there.
121 public void ReferenceBody(BulletBody body, bool inTaintTime) 121 public void ReferenceBody(BulletBody body, bool inTaintTime)
122 { 122 {
123 lock (m_collectionActivityLock) 123 lock (m_collectionActivityLock)
@@ -241,26 +241,32 @@ public class BSShapeCollection : IDisposable
241 241
242 BSScene.TaintCallback dereferenceOperation = delegate() 242 BSScene.TaintCallback dereferenceOperation = delegate()
243 { 243 {
244 switch (shape.type) 244 if (shape.ptr != IntPtr.Zero)
245 { 245 {
246 case ShapeData.PhysicsShapeType.SHAPE_HULL: 246 if (shape.isNativeShape)
247 DereferenceHull(shape, shapeCallback); 247 {
248 break;
249 case ShapeData.PhysicsShapeType.SHAPE_MESH:
250 DereferenceMesh(shape, shapeCallback);
251 break;
252 case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN:
253 break;
254 default:
255 // Native shapes are not tracked and are released immediately 248 // Native shapes are not tracked and are released immediately
256 if (shape.ptr != IntPtr.Zero & shape.isNativeShape) 249 DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
250 BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime);
251 if (shapeCallback != null) shapeCallback(shape);
252 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
253 }
254 else
255 {
256 switch (shape.type)
257 { 257 {
258 DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", 258 case ShapeData.PhysicsShapeType.SHAPE_HULL:
259 BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime); 259 DereferenceHull(shape, shapeCallback);
260 if (shapeCallback != null) shapeCallback(shape); 260 break;
261 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); 261 case ShapeData.PhysicsShapeType.SHAPE_MESH:
262 DereferenceMesh(shape, shapeCallback);
263 break;
264 case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN:
265 break;
266 default:
267 break;
262 } 268 }
263 break; 269 }
264 } 270 }
265 }; 271 };
266 if (inTaintTime) 272 if (inTaintTime)
@@ -405,7 +411,6 @@ public class BSShapeCollection : IDisposable
405 ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, 411 ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey,
406 ShapeDestructionCallback shapeCallback) 412 ShapeDestructionCallback shapeCallback)
407 { 413 {
408 BulletShape newShape;
409 414
410 shapeData.Type = shapeType; 415 shapeData.Type = shapeType;
411 // Bullet native objects are scaled by the Bullet engine so pass the size in 416 // Bullet native objects are scaled by the Bullet engine so pass the size in
@@ -415,27 +420,35 @@ public class BSShapeCollection : IDisposable
415 // release any previous shape 420 // release any previous shape
416 DereferenceShape(prim.BSShape, true, shapeCallback); 421 DereferenceShape(prim.BSShape, true, shapeCallback);
417 422
423 BulletShape newShape = BuildPhysicalNativeShape(shapeType, shapeData, shapeKey);
424
425 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
426 DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
427 shapeData.ID, newShape, shapeData.Scale);
428
429 prim.BSShape = newShape;
430 return true;
431 }
432
433 private BulletShape BuildPhysicalNativeShape(ShapeData.PhysicsShapeType shapeType,
434 ShapeData shapeData, ShapeData.FixedShapeKey shapeKey)
435 {
436 BulletShape newShape;
437
418 if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) 438 if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR)
419 { 439 {
420 newShape = new BulletShape( 440 newShape = new BulletShape(
421 BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, shapeData.Scale), 441 BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, shapeData.Scale),
422 shapeType); 442 shapeType);
423 newShape.shapeKey = (System.UInt64)shapeKey;
424 newShape.isNativeShape = true;
425 } 443 }
426 else 444 else
427 { 445 {
428 newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); 446 newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType);
429 newShape.shapeKey = (System.UInt64)shapeKey;
430 newShape.isNativeShape = true;
431 } 447 }
448 newShape.shapeKey = (System.UInt64)shapeKey;
449 newShape.isNativeShape = true;
432 450
433 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. 451 return newShape;
434 DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
435 shapeData.ID, newShape, shapeData.Scale);
436
437 prim.BSShape = newShape;
438 return true;
439 } 452 }
440 453
441 // Builds a mesh shape in the physical world and updates prim.BSShape. 454 // Builds a mesh shape in the physical world and updates prim.BSShape.
@@ -461,6 +474,8 @@ public class BSShapeCollection : IDisposable
461 DereferenceShape(prim.BSShape, true, shapeCallback); 474 DereferenceShape(prim.BSShape, true, shapeCallback);
462 475
463 newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod); 476 newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod);
477 // Take evasive action if the mesh was not constructed.
478 newShape = VerifyMeshCreated(newShape, prim, shapeData, pbs);
464 479
465 ReferenceShape(newShape); 480 ReferenceShape(newShape);
466 481
@@ -474,7 +489,7 @@ public class BSShapeCollection : IDisposable
474 private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) 489 private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
475 { 490 {
476 IMesh meshData = null; 491 IMesh meshData = null;
477 IntPtr meshPtr; 492 IntPtr meshPtr = IntPtr.Zero;
478 MeshDesc meshDesc; 493 MeshDesc meshDesc;
479 if (Meshes.TryGetValue(newMeshKey, out meshDesc)) 494 if (Meshes.TryGetValue(newMeshKey, out meshDesc))
480 { 495 {
@@ -486,23 +501,26 @@ public class BSShapeCollection : IDisposable
486 // Pass false for physicalness as this creates some sort of bounding box which we don't need 501 // Pass false for physicalness as this creates some sort of bounding box which we don't need
487 meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); 502 meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);
488 503
489 int[] indices = meshData.getIndexListAsInt(); 504 if (meshData != null)
490 List<OMV.Vector3> vertices = meshData.getVertexList();
491
492 float[] verticesAsFloats = new float[vertices.Count * 3];
493 int vi = 0;
494 foreach (OMV.Vector3 vv in vertices)
495 { 505 {
496 verticesAsFloats[vi++] = vv.X; 506 int[] indices = meshData.getIndexListAsInt();
497 verticesAsFloats[vi++] = vv.Y; 507 List<OMV.Vector3> vertices = meshData.getVertexList();
498 verticesAsFloats[vi++] = vv.Z;
499 }
500 508
501 // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", 509 float[] verticesAsFloats = new float[vertices.Count * 3];
502 // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); 510 int vi = 0;
511 foreach (OMV.Vector3 vv in vertices)
512 {
513 verticesAsFloats[vi++] = vv.X;
514 verticesAsFloats[vi++] = vv.Y;
515 verticesAsFloats[vi++] = vv.Z;
516 }
517
518 // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}",
519 // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count);
503 520
504 meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, 521 meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr,
505 indices.GetLength(0), indices, vertices.Count, verticesAsFloats); 522 indices.GetLength(0), indices, vertices.Count, verticesAsFloats);
523 }
506 } 524 }
507 BulletShape newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH); 525 BulletShape newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH);
508 newShape.shapeKey = newMeshKey; 526 newShape.shapeKey = newMeshKey;
@@ -531,6 +549,7 @@ public class BSShapeCollection : IDisposable
531 DereferenceShape(prim.BSShape, true, shapeCallback); 549 DereferenceShape(prim.BSShape, true, shapeCallback);
532 550
533 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod); 551 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod);
552 newShape = VerifyMeshCreated(newShape, prim, shapeData, pbs);
534 553
535 ReferenceShape(newShape); 554 ReferenceShape(newShape);
536 555
@@ -544,7 +563,7 @@ public class BSShapeCollection : IDisposable
544 private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) 563 private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
545 { 564 {
546 565
547 IntPtr hullPtr; 566 IntPtr hullPtr = IntPtr.Zero;
548 HullDesc hullDesc; 567 HullDesc hullDesc;
549 if (Hulls.TryGetValue(newHullKey, out hullDesc)) 568 if (Hulls.TryGetValue(newHullKey, out hullDesc))
550 { 569 {
@@ -556,86 +575,89 @@ public class BSShapeCollection : IDisposable
556 // Build a new hull in the physical world 575 // Build a new hull in the physical world
557 // Pass false for physicalness as this creates some sort of bounding box which we don't need 576 // Pass false for physicalness as this creates some sort of bounding box which we don't need
558 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); 577 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);
559 578 if (meshData != null)
560 int[] indices = meshData.getIndexListAsInt();
561 List<OMV.Vector3> vertices = meshData.getVertexList();
562
563 //format conversion from IMesh format to DecompDesc format
564 List<int> convIndices = new List<int>();
565 List<float3> convVertices = new List<float3>();
566 for (int ii = 0; ii < indices.GetLength(0); ii++)
567 {
568 convIndices.Add(indices[ii]);
569 }
570 foreach (OMV.Vector3 vv in vertices)
571 { 579 {
572 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
573 }
574 580
575 // setup and do convex hull conversion 581 int[] indices = meshData.getIndexListAsInt();
576 m_hulls = new List<ConvexResult>(); 582 List<OMV.Vector3> vertices = meshData.getVertexList();
577 DecompDesc dcomp = new DecompDesc();
578 dcomp.mIndices = convIndices;
579 dcomp.mVertices = convVertices;
580 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
581 // create the hull into the _hulls variable
582 convexBuilder.process(dcomp);
583
584 // Convert the vertices and indices for passing to unmanaged.
585 // The hull information is passed as a large floating point array.
586 // The format is:
587 // convHulls[0] = number of hulls
588 // convHulls[1] = number of vertices in first hull
589 // convHulls[2] = hull centroid X coordinate
590 // convHulls[3] = hull centroid Y coordinate
591 // convHulls[4] = hull centroid Z coordinate
592 // convHulls[5] = first hull vertex X
593 // convHulls[6] = first hull vertex Y
594 // convHulls[7] = first hull vertex Z
595 // convHulls[8] = second hull vertex X
596 // ...
597 // convHulls[n] = number of vertices in second hull
598 // convHulls[n+1] = second hull centroid X coordinate
599 // ...
600 //
601 // TODO: is is very inefficient. Someday change the convex hull generator to return
602 // data structures that do not need to be converted in order to pass to Bullet.
603 // And maybe put the values directly into pinned memory rather than marshaling.
604 int hullCount = m_hulls.Count;
605 int totalVertices = 1; // include one for the count of the hulls
606 foreach (ConvexResult cr in m_hulls)
607 {
608 totalVertices += 4; // add four for the vertex count and centroid
609 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
610 }
611 float[] convHulls = new float[totalVertices];
612 583
613 convHulls[0] = (float)hullCount; 584 //format conversion from IMesh format to DecompDesc format
614 int jj = 1; 585 List<int> convIndices = new List<int>();
615 foreach (ConvexResult cr in m_hulls) 586 List<float3> convVertices = new List<float3>();
616 { 587 for (int ii = 0; ii < indices.GetLength(0); ii++)
617 // copy vertices for index access
618 float3[] verts = new float3[cr.HullVertices.Count];
619 int kk = 0;
620 foreach (float3 ff in cr.HullVertices)
621 { 588 {
622 verts[kk++] = ff; 589 convIndices.Add(indices[ii]);
590 }
591 foreach (OMV.Vector3 vv in vertices)
592 {
593 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
623 } 594 }
624 595
625 // add to the array one hull's worth of data 596 // setup and do convex hull conversion
626 convHulls[jj++] = cr.HullIndices.Count; 597 m_hulls = new List<ConvexResult>();
627 convHulls[jj++] = 0f; // centroid x,y,z 598 DecompDesc dcomp = new DecompDesc();
628 convHulls[jj++] = 0f; 599 dcomp.mIndices = convIndices;
629 convHulls[jj++] = 0f; 600 dcomp.mVertices = convVertices;
630 foreach (int ind in cr.HullIndices) 601 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
602 // create the hull into the _hulls variable
603 convexBuilder.process(dcomp);
604
605 // Convert the vertices and indices for passing to unmanaged.
606 // The hull information is passed as a large floating point array.
607 // The format is:
608 // convHulls[0] = number of hulls
609 // convHulls[1] = number of vertices in first hull
610 // convHulls[2] = hull centroid X coordinate
611 // convHulls[3] = hull centroid Y coordinate
612 // convHulls[4] = hull centroid Z coordinate
613 // convHulls[5] = first hull vertex X
614 // convHulls[6] = first hull vertex Y
615 // convHulls[7] = first hull vertex Z
616 // convHulls[8] = second hull vertex X
617 // ...
618 // convHulls[n] = number of vertices in second hull
619 // convHulls[n+1] = second hull centroid X coordinate
620 // ...
621 //
622 // TODO: is is very inefficient. Someday change the convex hull generator to return
623 // data structures that do not need to be converted in order to pass to Bullet.
624 // And maybe put the values directly into pinned memory rather than marshaling.
625 int hullCount = m_hulls.Count;
626 int totalVertices = 1; // include one for the count of the hulls
627 foreach (ConvexResult cr in m_hulls)
631 { 628 {
632 convHulls[jj++] = verts[ind].x; 629 totalVertices += 4; // add four for the vertex count and centroid
633 convHulls[jj++] = verts[ind].y; 630 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
634 convHulls[jj++] = verts[ind].z; 631 }
632 float[] convHulls = new float[totalVertices];
633
634 convHulls[0] = (float)hullCount;
635 int jj = 1;
636 foreach (ConvexResult cr in m_hulls)
637 {
638 // copy vertices for index access
639 float3[] verts = new float3[cr.HullVertices.Count];
640 int kk = 0;
641 foreach (float3 ff in cr.HullVertices)
642 {
643 verts[kk++] = ff;
644 }
645
646 // add to the array one hull's worth of data
647 convHulls[jj++] = cr.HullIndices.Count;
648 convHulls[jj++] = 0f; // centroid x,y,z
649 convHulls[jj++] = 0f;
650 convHulls[jj++] = 0f;
651 foreach (int ind in cr.HullIndices)
652 {
653 convHulls[jj++] = verts[ind].x;
654 convHulls[jj++] = verts[ind].y;
655 convHulls[jj++] = verts[ind].z;
656 }
635 } 657 }
658 // create the hull data structure in Bullet
659 hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls);
636 } 660 }
637 // create the hull data structure in Bullet
638 hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls);
639 } 661 }
640 662
641 BulletShape newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL); 663 BulletShape newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL);
@@ -676,6 +698,50 @@ public class BSShapeCollection : IDisposable
676 return ComputeShapeKey(shapeData, pbs, out lod); 698 return ComputeShapeKey(shapeData, pbs, out lod);
677 } 699 }
678 700
701 private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs)
702 {
703 // If the shape was successfully created, nothing more to do
704 if (newShape.ptr != IntPtr.Zero)
705 return newShape;
706
707 // The most common reason for failure is that an underlying asset is not available
708
709 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
710 if (pbs.SculptEntry && !prim.LastAssetBuildFailed && pbs.SculptTexture != OMV.UUID.Zero)
711 {
712 prim.LastAssetBuildFailed = true;
713 BSPhysObject xprim = prim;
714 Util.FireAndForget(delegate
715 {
716 RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod;
717 if (assetProvider != null)
718 {
719 BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
720 assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
721 {
722 if (!yprim.BaseShape.SculptEntry)
723 return;
724 if (yprim.BaseShape.SculptTexture.ToString() != asset.ID)
725 return;
726
727 yprim.BaseShape.SculptData = new byte[asset.Data.Length];
728 asset.Data.CopyTo(yprim.BaseShape.SculptData, 0);
729 // This will cause the prim to see that the filler shape is not the right
730 // one and try again to build the object.
731 yprim.ForceBodyShapeRebuild(false);
732
733 });
734 }
735 });
736 }
737
738 // While we figure out the real problem, stick a simple native shape on the object.
739 BulletShape fillinShape =
740 BuildPhysicalNativeShape(ShapeData.PhysicsShapeType.SHAPE_SPHERE, shapeData, ShapeData.FixedShapeKey.KEY_SPHERE);
741
742 return fillinShape;
743 }
744
679 // Create a body object in Bullet. 745 // Create a body object in Bullet.
680 // Updates prim.BSBody with the information about the new body if one is created. 746 // Updates prim.BSBody with the information about the new body if one is created.
681 // Returns 'true' if an object was actually created. 747 // Returns 'true' if an object was actually created.