diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs')
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 197 |
1 files changed, 153 insertions, 44 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 4ece1eb..3afd52e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | |||
@@ -33,14 +33,6 @@ using OMV = OpenMetaverse; | |||
33 | namespace OpenSim.Region.Physics.BulletSPlugin | 33 | namespace OpenSim.Region.Physics.BulletSPlugin |
34 | { | 34 | { |
35 | 35 | ||
36 | // A BSPrim can get individual information about its linkedness attached | ||
37 | // to it through an instance of a subclass of LinksetInfo. | ||
38 | // Each type of linkset will define the information needed for its type. | ||
39 | public abstract class BSLinksetInfo | ||
40 | { | ||
41 | public virtual void Clear() { } | ||
42 | } | ||
43 | |||
44 | public abstract class BSLinkset | 36 | public abstract class BSLinkset |
45 | { | 37 | { |
46 | // private static string LogHeader = "[BULLETSIM LINKSET]"; | 38 | // private static string LogHeader = "[BULLETSIM LINKSET]"; |
@@ -56,15 +48,15 @@ public abstract class BSLinkset | |||
56 | { | 48 | { |
57 | BSLinkset ret = null; | 49 | BSLinkset ret = null; |
58 | 50 | ||
59 | switch ((int)BSParam.LinksetImplementation) | 51 | switch (parent.LinksetType) |
60 | { | 52 | { |
61 | case (int)LinksetImplementation.Constraint: | 53 | case LinksetImplementation.Constraint: |
62 | ret = new BSLinksetConstraints(physScene, parent); | 54 | ret = new BSLinksetConstraints(physScene, parent); |
63 | break; | 55 | break; |
64 | case (int)LinksetImplementation.Compound: | 56 | case LinksetImplementation.Compound: |
65 | ret = new BSLinksetCompound(physScene, parent); | 57 | ret = new BSLinksetCompound(physScene, parent); |
66 | break; | 58 | break; |
67 | case (int)LinksetImplementation.Manual: | 59 | case LinksetImplementation.Manual: |
68 | // ret = new BSLinksetManual(physScene, parent); | 60 | // ret = new BSLinksetManual(physScene, parent); |
69 | break; | 61 | break; |
70 | default: | 62 | default: |
@@ -78,28 +70,33 @@ public abstract class BSLinkset | |||
78 | return ret; | 70 | return ret; |
79 | } | 71 | } |
80 | 72 | ||
73 | public class BSLinkInfo | ||
74 | { | ||
75 | public BSPrimLinkable member; | ||
76 | public BSLinkInfo(BSPrimLinkable pMember) | ||
77 | { | ||
78 | member = pMember; | ||
79 | } | ||
80 | } | ||
81 | |||
82 | public LinksetImplementation LinksetImpl { get; protected set; } | ||
83 | |||
81 | public BSPrimLinkable LinksetRoot { get; protected set; } | 84 | public BSPrimLinkable LinksetRoot { get; protected set; } |
82 | 85 | ||
83 | public BSScene PhysicsScene { get; private set; } | 86 | protected BSScene m_physicsScene { get; private set; } |
84 | 87 | ||
85 | static int m_nextLinksetID = 1; | 88 | static int m_nextLinksetID = 1; |
86 | public int LinksetID { get; private set; } | 89 | public int LinksetID { get; private set; } |
87 | 90 | ||
88 | // The children under the root in this linkset. | 91 | // The children under the root in this linkset. |
89 | protected HashSet<BSPrimLinkable> m_children; | 92 | // protected HashSet<BSPrimLinkable> m_children; |
93 | protected Dictionary<BSPrimLinkable, BSLinkInfo> m_children; | ||
90 | 94 | ||
91 | // We lock the diddling of linkset classes to prevent any badness. | 95 | // We lock the diddling of linkset classes to prevent any badness. |
92 | // This locks the modification of the instances of this class. Changes | 96 | // This locks the modification of the instances of this class. Changes |
93 | // to the physical representation is done via the tainting mechenism. | 97 | // to the physical representation is done via the tainting mechenism. |
94 | protected object m_linksetActivityLock = new Object(); | 98 | protected object m_linksetActivityLock = new Object(); |
95 | 99 | ||
96 | // Some linksets have a preferred physical shape. | ||
97 | // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected. | ||
98 | public virtual BSPhysicsShapeType PreferredPhysicalShape(BSPrimLinkable requestor) | ||
99 | { | ||
100 | return BSPhysicsShapeType.SHAPE_UNKNOWN; | ||
101 | } | ||
102 | |||
103 | // We keep the prim's mass in the linkset structure since it could be dependent on other prims | 100 | // We keep the prim's mass in the linkset structure since it could be dependent on other prims |
104 | public float LinksetMass { get; protected set; } | 101 | public float LinksetMass { get; protected set; } |
105 | 102 | ||
@@ -122,9 +119,9 @@ public abstract class BSLinkset | |||
122 | // We create LOTS of linksets. | 119 | // We create LOTS of linksets. |
123 | if (m_nextLinksetID <= 0) | 120 | if (m_nextLinksetID <= 0) |
124 | m_nextLinksetID = 1; | 121 | m_nextLinksetID = 1; |
125 | PhysicsScene = scene; | 122 | m_physicsScene = scene; |
126 | LinksetRoot = parent; | 123 | LinksetRoot = parent; |
127 | m_children = new HashSet<BSPrimLinkable>(); | 124 | m_children = new Dictionary<BSPrimLinkable, BSLinkInfo>(); |
128 | LinksetMass = parent.RawMass; | 125 | LinksetMass = parent.RawMass; |
129 | Rebuilding = false; | 126 | Rebuilding = false; |
130 | 127 | ||
@@ -165,7 +162,7 @@ public abstract class BSLinkset | |||
165 | } | 162 | } |
166 | 163 | ||
167 | // The child is down to a linkset of just itself | 164 | // The child is down to a linkset of just itself |
168 | return BSLinkset.Factory(PhysicsScene, child); | 165 | return BSLinkset.Factory(m_physicsScene, child); |
169 | } | 166 | } |
170 | 167 | ||
171 | // Return 'true' if the passed object is the root object of this linkset | 168 | // Return 'true' if the passed object is the root object of this linkset |
@@ -185,17 +182,7 @@ public abstract class BSLinkset | |||
185 | bool ret = false; | 182 | bool ret = false; |
186 | lock (m_linksetActivityLock) | 183 | lock (m_linksetActivityLock) |
187 | { | 184 | { |
188 | ret = m_children.Contains(child); | 185 | ret = m_children.ContainsKey(child); |
189 | /* Safer version but the above should work | ||
190 | foreach (BSPrimLinkable bp in m_children) | ||
191 | { | ||
192 | if (child.LocalID == bp.LocalID) | ||
193 | { | ||
194 | ret = true; | ||
195 | break; | ||
196 | } | ||
197 | } | ||
198 | */ | ||
199 | } | 186 | } |
200 | return ret; | 187 | return ret; |
201 | } | 188 | } |
@@ -209,7 +196,24 @@ public abstract class BSLinkset | |||
209 | lock (m_linksetActivityLock) | 196 | lock (m_linksetActivityLock) |
210 | { | 197 | { |
211 | action(LinksetRoot); | 198 | action(LinksetRoot); |
212 | foreach (BSPrimLinkable po in m_children) | 199 | foreach (BSPrimLinkable po in m_children.Keys) |
200 | { | ||
201 | if (action(po)) | ||
202 | break; | ||
203 | } | ||
204 | } | ||
205 | return ret; | ||
206 | } | ||
207 | |||
208 | // Perform an action on each member of the linkset including root prim. | ||
209 | // Depends on the action on whether this should be done at taint time. | ||
210 | public delegate bool ForEachLinkInfoAction(BSLinkInfo obj); | ||
211 | public virtual bool ForEachLinkInfo(ForEachLinkInfoAction action) | ||
212 | { | ||
213 | bool ret = false; | ||
214 | lock (m_linksetActivityLock) | ||
215 | { | ||
216 | foreach (BSLinkInfo po in m_children.Values) | ||
213 | { | 217 | { |
214 | if (action(po)) | 218 | if (action(po)) |
215 | break; | 219 | break; |
@@ -218,10 +222,37 @@ public abstract class BSLinkset | |||
218 | return ret; | 222 | return ret; |
219 | } | 223 | } |
220 | 224 | ||
225 | // Called after a simulation step to post a collision with this object. | ||
226 | // Return 'true' if linkset processed the collision. 'false' says the linkset didn't have | ||
227 | // anything to add for the collision and it should be passed through normal processing. | ||
228 | // Default processing for a linkset. | ||
229 | public virtual bool HandleCollide(uint collidingWith, BSPhysObject collidee, | ||
230 | OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) | ||
231 | { | ||
232 | bool ret = false; | ||
233 | |||
234 | // prims in the same linkset cannot collide with each other | ||
235 | BSPrimLinkable convCollidee = collidee as BSPrimLinkable; | ||
236 | if (convCollidee != null && (LinksetID == convCollidee.Linkset.LinksetID)) | ||
237 | { | ||
238 | // By returning 'true', we tell the caller the collision has been 'handled' so it won't | ||
239 | // do anything about this collision and thus, effectivily, ignoring the collision. | ||
240 | ret = true; | ||
241 | } | ||
242 | else | ||
243 | { | ||
244 | // Not a collision between members of the linkset. Must be a real collision. | ||
245 | // So the linkset root can know if there is a collision anywhere in the linkset. | ||
246 | LinksetRoot.SomeCollisionSimulationStep = m_physicsScene.SimulationStep; | ||
247 | } | ||
248 | |||
249 | return ret; | ||
250 | } | ||
251 | |||
221 | // I am the root of a linkset and a new child is being added | 252 | // I am the root of a linkset and a new child is being added |
222 | // Called while LinkActivity is locked. | 253 | // Called while LinkActivity is locked. |
223 | protected abstract void AddChildToLinkset(BSPrimLinkable child); | 254 | protected abstract void AddChildToLinkset(BSPrimLinkable child); |
224 | 255 | ||
225 | // I am the root of a linkset and one of my children is being removed. | 256 | // I am the root of a linkset and one of my children is being removed. |
226 | // Safe to call even if the child is not really in my linkset. | 257 | // Safe to call even if the child is not really in my linkset. |
227 | protected abstract void RemoveChildFromLinkset(BSPrimLinkable child); | 258 | protected abstract void RemoveChildFromLinkset(BSPrimLinkable child); |
@@ -263,8 +294,87 @@ public abstract class BSLinkset | |||
263 | // This is called when the root body is changing. | 294 | // This is called when the root body is changing. |
264 | // Returns 'true' of something was actually removed and would need restoring | 295 | // Returns 'true' of something was actually removed and would need restoring |
265 | // Called at taint-time!! | 296 | // Called at taint-time!! |
266 | public abstract bool RemoveBodyDependencies(BSPrimLinkable child); | 297 | public abstract bool RemoveDependencies(BSPrimLinkable child); |
298 | |||
299 | // ================================================================ | ||
300 | // Some physical setting happen to all members of the linkset | ||
301 | public virtual void SetPhysicalFriction(float friction) | ||
302 | { | ||
303 | ForEachMember((member) => | ||
304 | { | ||
305 | if (member.PhysBody.HasPhysicalBody) | ||
306 | m_physicsScene.PE.SetFriction(member.PhysBody, friction); | ||
307 | return false; // 'false' says to continue looping | ||
308 | } | ||
309 | ); | ||
310 | } | ||
311 | public virtual void SetPhysicalRestitution(float restitution) | ||
312 | { | ||
313 | ForEachMember((member) => | ||
314 | { | ||
315 | if (member.PhysBody.HasPhysicalBody) | ||
316 | m_physicsScene.PE.SetRestitution(member.PhysBody, restitution); | ||
317 | return false; // 'false' says to continue looping | ||
318 | } | ||
319 | ); | ||
320 | } | ||
321 | public virtual void SetPhysicalGravity(OMV.Vector3 gravity) | ||
322 | { | ||
323 | ForEachMember((member) => | ||
324 | { | ||
325 | if (member.PhysBody.HasPhysicalBody) | ||
326 | m_physicsScene.PE.SetGravity(member.PhysBody, gravity); | ||
327 | return false; // 'false' says to continue looping | ||
328 | } | ||
329 | ); | ||
330 | } | ||
331 | public virtual void ComputeAndSetLocalInertia(OMV.Vector3 inertiaFactor, float linksetMass) | ||
332 | { | ||
333 | ForEachMember((member) => | ||
334 | { | ||
335 | if (member.PhysBody.HasPhysicalBody) | ||
336 | { | ||
337 | OMV.Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(member.PhysShape.physShapeInfo, linksetMass); | ||
338 | member.Inertia = inertia * inertiaFactor; | ||
339 | m_physicsScene.PE.SetMassProps(member.PhysBody, linksetMass, member.Inertia); | ||
340 | m_physicsScene.PE.UpdateInertiaTensor(member.PhysBody); | ||
341 | DetailLog("{0},BSLinkset.ComputeAndSetLocalInertia,m.mass={1}, inertia={2}", member.LocalID, linksetMass, member.Inertia); | ||
267 | 342 | ||
343 | } | ||
344 | return false; // 'false' says to continue looping | ||
345 | } | ||
346 | ); | ||
347 | } | ||
348 | public virtual void SetPhysicalCollisionFlags(CollisionFlags collFlags) | ||
349 | { | ||
350 | ForEachMember((member) => | ||
351 | { | ||
352 | if (member.PhysBody.HasPhysicalBody) | ||
353 | m_physicsScene.PE.SetCollisionFlags(member.PhysBody, collFlags); | ||
354 | return false; // 'false' says to continue looping | ||
355 | } | ||
356 | ); | ||
357 | } | ||
358 | public virtual void AddToPhysicalCollisionFlags(CollisionFlags collFlags) | ||
359 | { | ||
360 | ForEachMember((member) => | ||
361 | { | ||
362 | if (member.PhysBody.HasPhysicalBody) | ||
363 | m_physicsScene.PE.AddToCollisionFlags(member.PhysBody, collFlags); | ||
364 | return false; // 'false' says to continue looping | ||
365 | } | ||
366 | ); | ||
367 | } | ||
368 | public virtual void RemoveFromPhysicalCollisionFlags(CollisionFlags collFlags) | ||
369 | { | ||
370 | ForEachMember((member) => | ||
371 | { | ||
372 | if (member.PhysBody.HasPhysicalBody) | ||
373 | m_physicsScene.PE.RemoveFromCollisionFlags(member.PhysBody, collFlags); | ||
374 | return false; // 'false' says to continue looping | ||
375 | } | ||
376 | ); | ||
377 | } | ||
268 | // ================================================================ | 378 | // ================================================================ |
269 | protected virtual float ComputeLinksetMass() | 379 | protected virtual float ComputeLinksetMass() |
270 | { | 380 | { |
@@ -273,7 +383,7 @@ public abstract class BSLinkset | |||
273 | { | 383 | { |
274 | lock (m_linksetActivityLock) | 384 | lock (m_linksetActivityLock) |
275 | { | 385 | { |
276 | foreach (BSPrimLinkable bp in m_children) | 386 | foreach (BSPrimLinkable bp in m_children.Keys) |
277 | { | 387 | { |
278 | mass += bp.RawMass; | 388 | mass += bp.RawMass; |
279 | } | 389 | } |
@@ -291,7 +401,7 @@ public abstract class BSLinkset | |||
291 | com = LinksetRoot.Position * LinksetRoot.RawMass; | 401 | com = LinksetRoot.Position * LinksetRoot.RawMass; |
292 | float totalMass = LinksetRoot.RawMass; | 402 | float totalMass = LinksetRoot.RawMass; |
293 | 403 | ||
294 | foreach (BSPrimLinkable bp in m_children) | 404 | foreach (BSPrimLinkable bp in m_children.Keys) |
295 | { | 405 | { |
296 | com += bp.Position * bp.RawMass; | 406 | com += bp.Position * bp.RawMass; |
297 | totalMass += bp.RawMass; | 407 | totalMass += bp.RawMass; |
@@ -310,7 +420,7 @@ public abstract class BSLinkset | |||
310 | { | 420 | { |
311 | com = LinksetRoot.Position; | 421 | com = LinksetRoot.Position; |
312 | 422 | ||
313 | foreach (BSPrimLinkable bp in m_children) | 423 | foreach (BSPrimLinkable bp in m_children.Keys) |
314 | { | 424 | { |
315 | com += bp.Position; | 425 | com += bp.Position; |
316 | } | 426 | } |
@@ -323,9 +433,8 @@ public abstract class BSLinkset | |||
323 | // Invoke the detailed logger and output something if it's enabled. | 433 | // Invoke the detailed logger and output something if it's enabled. |
324 | protected void DetailLog(string msg, params Object[] args) | 434 | protected void DetailLog(string msg, params Object[] args) |
325 | { | 435 | { |
326 | if (PhysicsScene.PhysicsLogging.Enabled) | 436 | if (m_physicsScene.PhysicsLogging.Enabled) |
327 | PhysicsScene.DetailLog(msg, args); | 437 | m_physicsScene.DetailLog(msg, args); |
328 | } | 438 | } |
329 | |||
330 | } | 439 | } |
331 | } | 440 | } |