diff options
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. |