diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs')
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 240 |
1 files changed, 193 insertions, 47 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 4ece1eb..77f69a5 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,37 @@ 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 | public virtual void ResetLink() { } | ||
81 | public virtual void SetLinkParameters(BSConstraint constrain) { } | ||
82 | // Returns 'true' if physical property updates from the child should be reported to the simulator | ||
83 | public virtual bool ShouldUpdateChildProperties() { return false; } | ||
84 | } | ||
85 | |||
86 | public LinksetImplementation LinksetImpl { get; protected set; } | ||
87 | |||
81 | public BSPrimLinkable LinksetRoot { get; protected set; } | 88 | public BSPrimLinkable LinksetRoot { get; protected set; } |
82 | 89 | ||
83 | public BSScene PhysicsScene { get; private set; } | 90 | protected BSScene m_physicsScene { get; private set; } |
84 | 91 | ||
85 | static int m_nextLinksetID = 1; | 92 | static int m_nextLinksetID = 1; |
86 | public int LinksetID { get; private set; } | 93 | public int LinksetID { get; private set; } |
87 | 94 | ||
88 | // The children under the root in this linkset. | 95 | // The children under the root in this linkset. |
89 | protected HashSet<BSPrimLinkable> m_children; | 96 | // protected HashSet<BSPrimLinkable> m_children; |
97 | protected Dictionary<BSPrimLinkable, BSLinkInfo> m_children; | ||
90 | 98 | ||
91 | // We lock the diddling of linkset classes to prevent any badness. | 99 | // We lock the diddling of linkset classes to prevent any badness. |
92 | // This locks the modification of the instances of this class. Changes | 100 | // This locks the modification of the instances of this class. Changes |
93 | // to the physical representation is done via the tainting mechenism. | 101 | // to the physical representation is done via the tainting mechenism. |
94 | protected object m_linksetActivityLock = new Object(); | 102 | protected object m_linksetActivityLock = new Object(); |
95 | 103 | ||
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 | 104 | // 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; } | 105 | public float LinksetMass { get; protected set; } |
105 | 106 | ||
@@ -122,9 +123,9 @@ public abstract class BSLinkset | |||
122 | // We create LOTS of linksets. | 123 | // We create LOTS of linksets. |
123 | if (m_nextLinksetID <= 0) | 124 | if (m_nextLinksetID <= 0) |
124 | m_nextLinksetID = 1; | 125 | m_nextLinksetID = 1; |
125 | PhysicsScene = scene; | 126 | m_physicsScene = scene; |
126 | LinksetRoot = parent; | 127 | LinksetRoot = parent; |
127 | m_children = new HashSet<BSPrimLinkable>(); | 128 | m_children = new Dictionary<BSPrimLinkable, BSLinkInfo>(); |
128 | LinksetMass = parent.RawMass; | 129 | LinksetMass = parent.RawMass; |
129 | Rebuilding = false; | 130 | Rebuilding = false; |
130 | 131 | ||
@@ -151,7 +152,7 @@ public abstract class BSLinkset | |||
151 | // Returns a new linkset for the child which is a linkset of one (just the | 152 | // Returns a new linkset for the child which is a linkset of one (just the |
152 | // orphened child). | 153 | // orphened child). |
153 | // Called at runtime. | 154 | // Called at runtime. |
154 | public BSLinkset RemoveMeFromLinkset(BSPrimLinkable child) | 155 | public BSLinkset RemoveMeFromLinkset(BSPrimLinkable child, bool inTaintTime) |
155 | { | 156 | { |
156 | lock (m_linksetActivityLock) | 157 | lock (m_linksetActivityLock) |
157 | { | 158 | { |
@@ -160,12 +161,12 @@ public abstract class BSLinkset | |||
160 | // Cannot remove the root from a linkset. | 161 | // Cannot remove the root from a linkset. |
161 | return this; | 162 | return this; |
162 | } | 163 | } |
163 | RemoveChildFromLinkset(child); | 164 | RemoveChildFromLinkset(child, inTaintTime); |
164 | LinksetMass = ComputeLinksetMass(); | 165 | LinksetMass = ComputeLinksetMass(); |
165 | } | 166 | } |
166 | 167 | ||
167 | // The child is down to a linkset of just itself | 168 | // The child is down to a linkset of just itself |
168 | return BSLinkset.Factory(PhysicsScene, child); | 169 | return BSLinkset.Factory(m_physicsScene, child); |
169 | } | 170 | } |
170 | 171 | ||
171 | // Return 'true' if the passed object is the root object of this linkset | 172 | // Return 'true' if the passed object is the root object of this linkset |
@@ -185,17 +186,7 @@ public abstract class BSLinkset | |||
185 | bool ret = false; | 186 | bool ret = false; |
186 | lock (m_linksetActivityLock) | 187 | lock (m_linksetActivityLock) |
187 | { | 188 | { |
188 | ret = m_children.Contains(child); | 189 | 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 | } | 190 | } |
200 | return ret; | 191 | return ret; |
201 | } | 192 | } |
@@ -209,7 +200,35 @@ public abstract class BSLinkset | |||
209 | lock (m_linksetActivityLock) | 200 | lock (m_linksetActivityLock) |
210 | { | 201 | { |
211 | action(LinksetRoot); | 202 | action(LinksetRoot); |
212 | foreach (BSPrimLinkable po in m_children) | 203 | foreach (BSPrimLinkable po in m_children.Keys) |
204 | { | ||
205 | if (action(po)) | ||
206 | break; | ||
207 | } | ||
208 | } | ||
209 | return ret; | ||
210 | } | ||
211 | |||
212 | public bool TryGetLinkInfo(BSPrimLinkable child, out BSLinkInfo foundInfo) | ||
213 | { | ||
214 | bool ret = false; | ||
215 | BSLinkInfo found = null; | ||
216 | lock (m_linksetActivityLock) | ||
217 | { | ||
218 | ret = m_children.TryGetValue(child, out found); | ||
219 | } | ||
220 | foundInfo = found; | ||
221 | return ret; | ||
222 | } | ||
223 | // Perform an action on each member of the linkset including root prim. | ||
224 | // Depends on the action on whether this should be done at taint time. | ||
225 | public delegate bool ForEachLinkInfoAction(BSLinkInfo obj); | ||
226 | public virtual bool ForEachLinkInfo(ForEachLinkInfoAction action) | ||
227 | { | ||
228 | bool ret = false; | ||
229 | lock (m_linksetActivityLock) | ||
230 | { | ||
231 | foreach (BSLinkInfo po in m_children.Values) | ||
213 | { | 232 | { |
214 | if (action(po)) | 233 | if (action(po)) |
215 | break; | 234 | break; |
@@ -218,13 +237,55 @@ public abstract class BSLinkset | |||
218 | return ret; | 237 | return ret; |
219 | } | 238 | } |
220 | 239 | ||
240 | // Check the type of the link and return 'true' if the link is flexible and the | ||
241 | // updates from the child should be sent to the simulator so things change. | ||
242 | public virtual bool ShouldReportPropertyUpdates(BSPrimLinkable child) | ||
243 | { | ||
244 | bool ret = false; | ||
245 | |||
246 | BSLinkInfo linkInfo; | ||
247 | if (m_children.TryGetValue(child, out linkInfo)) | ||
248 | { | ||
249 | ret = linkInfo.ShouldUpdateChildProperties(); | ||
250 | } | ||
251 | |||
252 | return ret; | ||
253 | } | ||
254 | |||
255 | // Called after a simulation step to post a collision with this object. | ||
256 | // Return 'true' if linkset processed the collision. 'false' says the linkset didn't have | ||
257 | // anything to add for the collision and it should be passed through normal processing. | ||
258 | // Default processing for a linkset. | ||
259 | public virtual bool HandleCollide(uint collidingWith, BSPhysObject collidee, | ||
260 | OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) | ||
261 | { | ||
262 | bool ret = false; | ||
263 | |||
264 | // prims in the same linkset cannot collide with each other | ||
265 | BSPrimLinkable convCollidee = collidee as BSPrimLinkable; | ||
266 | if (convCollidee != null && (LinksetID == convCollidee.Linkset.LinksetID)) | ||
267 | { | ||
268 | // By returning 'true', we tell the caller the collision has been 'handled' so it won't | ||
269 | // do anything about this collision and thus, effectivily, ignoring the collision. | ||
270 | ret = true; | ||
271 | } | ||
272 | else | ||
273 | { | ||
274 | // Not a collision between members of the linkset. Must be a real collision. | ||
275 | // So the linkset root can know if there is a collision anywhere in the linkset. | ||
276 | LinksetRoot.SomeCollisionSimulationStep = m_physicsScene.SimulationStep; | ||
277 | } | ||
278 | |||
279 | return ret; | ||
280 | } | ||
281 | |||
221 | // I am the root of a linkset and a new child is being added | 282 | // I am the root of a linkset and a new child is being added |
222 | // Called while LinkActivity is locked. | 283 | // Called while LinkActivity is locked. |
223 | protected abstract void AddChildToLinkset(BSPrimLinkable child); | 284 | protected abstract void AddChildToLinkset(BSPrimLinkable child); |
224 | 285 | ||
225 | // I am the root of a linkset and one of my children is being removed. | 286 | // 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. | 287 | // Safe to call even if the child is not really in my linkset. |
227 | protected abstract void RemoveChildFromLinkset(BSPrimLinkable child); | 288 | protected abstract void RemoveChildFromLinkset(BSPrimLinkable child, bool inTaintTime); |
228 | 289 | ||
229 | // When physical properties are changed the linkset needs to recalculate | 290 | // When physical properties are changed the linkset needs to recalculate |
230 | // its internal properties. | 291 | // its internal properties. |
@@ -263,9 +324,88 @@ public abstract class BSLinkset | |||
263 | // This is called when the root body is changing. | 324 | // This is called when the root body is changing. |
264 | // Returns 'true' of something was actually removed and would need restoring | 325 | // Returns 'true' of something was actually removed and would need restoring |
265 | // Called at taint-time!! | 326 | // Called at taint-time!! |
266 | public abstract bool RemoveBodyDependencies(BSPrimLinkable child); | 327 | public abstract bool RemoveDependencies(BSPrimLinkable child); |
267 | 328 | ||
268 | // ================================================================ | 329 | // ================================================================ |
330 | // Some physical setting happen to all members of the linkset | ||
331 | public virtual void SetPhysicalFriction(float friction) | ||
332 | { | ||
333 | ForEachMember((member) => | ||
334 | { | ||
335 | if (member.PhysBody.HasPhysicalBody) | ||
336 | m_physicsScene.PE.SetFriction(member.PhysBody, friction); | ||
337 | return false; // 'false' says to continue looping | ||
338 | } | ||
339 | ); | ||
340 | } | ||
341 | public virtual void SetPhysicalRestitution(float restitution) | ||
342 | { | ||
343 | ForEachMember((member) => | ||
344 | { | ||
345 | if (member.PhysBody.HasPhysicalBody) | ||
346 | m_physicsScene.PE.SetRestitution(member.PhysBody, restitution); | ||
347 | return false; // 'false' says to continue looping | ||
348 | } | ||
349 | ); | ||
350 | } | ||
351 | public virtual void SetPhysicalGravity(OMV.Vector3 gravity) | ||
352 | { | ||
353 | ForEachMember((member) => | ||
354 | { | ||
355 | if (member.PhysBody.HasPhysicalBody) | ||
356 | m_physicsScene.PE.SetGravity(member.PhysBody, gravity); | ||
357 | return false; // 'false' says to continue looping | ||
358 | } | ||
359 | ); | ||
360 | } | ||
361 | public virtual void ComputeAndSetLocalInertia(OMV.Vector3 inertiaFactor, float linksetMass) | ||
362 | { | ||
363 | ForEachMember((member) => | ||
364 | { | ||
365 | if (member.PhysBody.HasPhysicalBody) | ||
366 | { | ||
367 | OMV.Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(member.PhysShape.physShapeInfo, linksetMass); | ||
368 | member.Inertia = inertia * inertiaFactor; | ||
369 | m_physicsScene.PE.SetMassProps(member.PhysBody, linksetMass, member.Inertia); | ||
370 | m_physicsScene.PE.UpdateInertiaTensor(member.PhysBody); | ||
371 | DetailLog("{0},BSLinkset.ComputeAndSetLocalInertia,m.mass={1}, inertia={2}", member.LocalID, linksetMass, member.Inertia); | ||
372 | |||
373 | } | ||
374 | return false; // 'false' says to continue looping | ||
375 | } | ||
376 | ); | ||
377 | } | ||
378 | public virtual void SetPhysicalCollisionFlags(CollisionFlags collFlags) | ||
379 | { | ||
380 | ForEachMember((member) => | ||
381 | { | ||
382 | if (member.PhysBody.HasPhysicalBody) | ||
383 | m_physicsScene.PE.SetCollisionFlags(member.PhysBody, collFlags); | ||
384 | return false; // 'false' says to continue looping | ||
385 | } | ||
386 | ); | ||
387 | } | ||
388 | public virtual void AddToPhysicalCollisionFlags(CollisionFlags collFlags) | ||
389 | { | ||
390 | ForEachMember((member) => | ||
391 | { | ||
392 | if (member.PhysBody.HasPhysicalBody) | ||
393 | m_physicsScene.PE.AddToCollisionFlags(member.PhysBody, collFlags); | ||
394 | return false; // 'false' says to continue looping | ||
395 | } | ||
396 | ); | ||
397 | } | ||
398 | public virtual void RemoveFromPhysicalCollisionFlags(CollisionFlags collFlags) | ||
399 | { | ||
400 | ForEachMember((member) => | ||
401 | { | ||
402 | if (member.PhysBody.HasPhysicalBody) | ||
403 | m_physicsScene.PE.RemoveFromCollisionFlags(member.PhysBody, collFlags); | ||
404 | return false; // 'false' says to continue looping | ||
405 | } | ||
406 | ); | ||
407 | } | ||
408 | // ================================================================ | ||
269 | protected virtual float ComputeLinksetMass() | 409 | protected virtual float ComputeLinksetMass() |
270 | { | 410 | { |
271 | float mass = LinksetRoot.RawMass; | 411 | float mass = LinksetRoot.RawMass; |
@@ -273,7 +413,7 @@ public abstract class BSLinkset | |||
273 | { | 413 | { |
274 | lock (m_linksetActivityLock) | 414 | lock (m_linksetActivityLock) |
275 | { | 415 | { |
276 | foreach (BSPrimLinkable bp in m_children) | 416 | foreach (BSPrimLinkable bp in m_children.Keys) |
277 | { | 417 | { |
278 | mass += bp.RawMass; | 418 | mass += bp.RawMass; |
279 | } | 419 | } |
@@ -291,7 +431,7 @@ public abstract class BSLinkset | |||
291 | com = LinksetRoot.Position * LinksetRoot.RawMass; | 431 | com = LinksetRoot.Position * LinksetRoot.RawMass; |
292 | float totalMass = LinksetRoot.RawMass; | 432 | float totalMass = LinksetRoot.RawMass; |
293 | 433 | ||
294 | foreach (BSPrimLinkable bp in m_children) | 434 | foreach (BSPrimLinkable bp in m_children.Keys) |
295 | { | 435 | { |
296 | com += bp.Position * bp.RawMass; | 436 | com += bp.Position * bp.RawMass; |
297 | totalMass += bp.RawMass; | 437 | totalMass += bp.RawMass; |
@@ -310,7 +450,7 @@ public abstract class BSLinkset | |||
310 | { | 450 | { |
311 | com = LinksetRoot.Position; | 451 | com = LinksetRoot.Position; |
312 | 452 | ||
313 | foreach (BSPrimLinkable bp in m_children) | 453 | foreach (BSPrimLinkable bp in m_children.Keys) |
314 | { | 454 | { |
315 | com += bp.Position; | 455 | com += bp.Position; |
316 | } | 456 | } |
@@ -320,12 +460,18 @@ public abstract class BSLinkset | |||
320 | return com; | 460 | return com; |
321 | } | 461 | } |
322 | 462 | ||
463 | #region Extension | ||
464 | public virtual object Extension(string pFunct, params object[] pParams) | ||
465 | { | ||
466 | return null; | ||
467 | } | ||
468 | #endregion // Extension | ||
469 | |||
323 | // Invoke the detailed logger and output something if it's enabled. | 470 | // Invoke the detailed logger and output something if it's enabled. |
324 | protected void DetailLog(string msg, params Object[] args) | 471 | protected void DetailLog(string msg, params Object[] args) |
325 | { | 472 | { |
326 | if (PhysicsScene.PhysicsLogging.Enabled) | 473 | if (m_physicsScene.PhysicsLogging.Enabled) |
327 | PhysicsScene.DetailLog(msg, args); | 474 | m_physicsScene.DetailLog(msg, args); |
328 | } | 475 | } |
329 | |||
330 | } | 476 | } |
331 | } | 477 | } |