aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs494
1 files changed, 462 insertions, 32 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
index 4bac222..aaf92c8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -28,6 +28,8 @@ using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Text; 29using System.Text;
30 30
31using OpenSim.Region.OptionalModules.Scripting;
32
31using OMV = OpenMetaverse; 33using OMV = OpenMetaverse;
32 34
33namespace OpenSim.Region.Physics.BulletSPlugin 35namespace OpenSim.Region.Physics.BulletSPlugin
@@ -51,18 +53,32 @@ public sealed class BSLinksetConstraints : BSLinkset
51 public float cfm; 53 public float cfm;
52 public float erp; 54 public float erp;
53 public float solverIterations; 55 public float solverIterations;
56 //
57 public OMV.Vector3 frameInAloc;
58 public OMV.Quaternion frameInArot;
59 public OMV.Vector3 frameInBloc;
60 public OMV.Quaternion frameInBrot;
61 public bool useLinearReferenceFrameA;
62 // Spring
63 public bool[] springAxisEnable;
64 public float[] springDamping;
65 public float[] springStiffness;
66 public OMV.Vector3 springLinearEquilibriumPoint;
67 public OMV.Vector3 springAngularEquilibriumPoint;
54 68
55 public BSLinkInfoConstraint(BSPrimLinkable pMember) 69 public BSLinkInfoConstraint(BSPrimLinkable pMember)
56 : base(pMember) 70 : base(pMember)
57 { 71 {
58 constraint = null; 72 constraint = null;
59 ResetToFixedConstraint(); 73 ResetLink();
74 member.PhysScene.DetailLog("{0},BSLinkInfoConstraint.creation", member.LocalID);
60 } 75 }
61 76
62 // Set all the parameters for this constraint to a fixed, non-movable constraint. 77 // Set all the parameters for this constraint to a fixed, non-movable constraint.
63 public void ResetToFixedConstraint() 78 public override void ResetLink()
64 { 79 {
65 constraintType = ConstraintType.D6_CONSTRAINT_TYPE; 80 // constraintType = ConstraintType.D6_CONSTRAINT_TYPE;
81 constraintType = ConstraintType.FIXED_CONSTRAINT_TYPE;
66 linearLimitLow = OMV.Vector3.Zero; 82 linearLimitLow = OMV.Vector3.Zero;
67 linearLimitHigh = OMV.Vector3.Zero; 83 linearLimitHigh = OMV.Vector3.Zero;
68 angularLimitLow = OMV.Vector3.Zero; 84 angularLimitLow = OMV.Vector3.Zero;
@@ -74,17 +90,37 @@ public sealed class BSLinksetConstraints : BSLinkset
74 cfm = BSParam.LinkConstraintCFM; 90 cfm = BSParam.LinkConstraintCFM;
75 erp = BSParam.LinkConstraintERP; 91 erp = BSParam.LinkConstraintERP;
76 solverIterations = BSParam.LinkConstraintSolverIterations; 92 solverIterations = BSParam.LinkConstraintSolverIterations;
93 frameInAloc = OMV.Vector3.Zero;
94 frameInArot = OMV.Quaternion.Identity;
95 frameInBloc = OMV.Vector3.Zero;
96 frameInBrot = OMV.Quaternion.Identity;
97 useLinearReferenceFrameA = true;
98 springAxisEnable = new bool[6];
99 springDamping = new float[6];
100 springStiffness = new float[6];
101 for (int ii = 0; ii < springAxisEnable.Length; ii++)
102 {
103 springAxisEnable[ii] = false;
104 springDamping[ii] = BSAPITemplate.SPRING_NOT_SPECIFIED;
105 springStiffness[ii] = BSAPITemplate.SPRING_NOT_SPECIFIED;
106 }
107 springLinearEquilibriumPoint = OMV.Vector3.Zero;
108 springAngularEquilibriumPoint = OMV.Vector3.Zero;
109 member.PhysScene.DetailLog("{0},BSLinkInfoConstraint.ResetLink", member.LocalID);
77 } 110 }
78 111
79 // Given a constraint, apply the current constraint parameters to same. 112 // Given a constraint, apply the current constraint parameters to same.
80 public void SetConstraintParameters(BSConstraint constrain) 113 public override void SetLinkParameters(BSConstraint constrain)
81 { 114 {
115 member.PhysScene.DetailLog("{0},BSLinkInfoConstraint.SetLinkParameters,type={1}", member.LocalID, constraintType);
82 switch (constraintType) 116 switch (constraintType)
83 { 117 {
118 case ConstraintType.FIXED_CONSTRAINT_TYPE:
84 case ConstraintType.D6_CONSTRAINT_TYPE: 119 case ConstraintType.D6_CONSTRAINT_TYPE:
85 BSConstraint6Dof constrain6dof = constrain as BSConstraint6Dof; 120 BSConstraint6Dof constrain6dof = constrain as BSConstraint6Dof;
86 if (constrain6dof != null) 121 if (constrain6dof != null)
87 { 122 {
123 // NOTE: D6_SPRING_CONSTRAINT_TYPE should be updated if you change any of this code.
88 // zero linear and angular limits makes the objects unable to move in relation to each other 124 // zero linear and angular limits makes the objects unable to move in relation to each other
89 constrain6dof.SetLinearLimits(linearLimitLow, linearLimitHigh); 125 constrain6dof.SetLinearLimits(linearLimitLow, linearLimitHigh);
90 constrain6dof.SetAngularLimits(angularLimitLow, angularLimitHigh); 126 constrain6dof.SetAngularLimits(angularLimitLow, angularLimitHigh);
@@ -99,10 +135,55 @@ public sealed class BSLinksetConstraints : BSLinkset
99 } 135 }
100 } 136 }
101 break; 137 break;
138 case ConstraintType.D6_SPRING_CONSTRAINT_TYPE:
139 BSConstraintSpring constrainSpring = constrain as BSConstraintSpring;
140 if (constrainSpring != null)
141 {
142 // zero linear and angular limits makes the objects unable to move in relation to each other
143 constrainSpring.SetLinearLimits(linearLimitLow, linearLimitHigh);
144 constrainSpring.SetAngularLimits(angularLimitLow, angularLimitHigh);
145
146 // tweek the constraint to increase stability
147 constrainSpring.UseFrameOffset(useFrameOffset);
148 constrainSpring.TranslationalLimitMotor(enableTransMotor, transMotorMaxVel, transMotorMaxForce);
149 constrainSpring.SetCFMAndERP(cfm, erp);
150 if (solverIterations != 0f)
151 {
152 constrainSpring.SetSolverIterations(solverIterations);
153 }
154 for (int ii = 0; ii < springAxisEnable.Length; ii++)
155 {
156 constrainSpring.SetAxisEnable(ii, springAxisEnable[ii]);
157 if (springDamping[ii] != BSAPITemplate.SPRING_NOT_SPECIFIED)
158 constrainSpring.SetDamping(ii, springDamping[ii]);
159 if (springStiffness[ii] != BSAPITemplate.SPRING_NOT_SPECIFIED)
160 constrainSpring.SetStiffness(ii, springStiffness[ii]);
161 }
162 constrainSpring.CalculateTransforms();
163
164 if (springLinearEquilibriumPoint != OMV.Vector3.Zero)
165 constrainSpring.SetEquilibriumPoint(springLinearEquilibriumPoint, springAngularEquilibriumPoint);
166 else
167 constrainSpring.SetEquilibriumPoint(BSAPITemplate.SPRING_NOT_SPECIFIED, BSAPITemplate.SPRING_NOT_SPECIFIED);
168 }
169 break;
102 default: 170 default:
103 break; 171 break;
104 } 172 }
105 } 173 }
174
175 // Return 'true' if the property updates from the physics engine should be reported
176 // to the simulator.
177 // If the constraint is fixed, we don't need to report as the simulator and viewer will
178 // report the right things.
179 public override bool ShouldUpdateChildProperties()
180 {
181 bool ret = true;
182 if (constraintType == ConstraintType.FIXED_CONSTRAINT_TYPE)
183 ret = false;
184
185 return ret;
186 }
106 } 187 }
107 188
108 public BSLinksetConstraints(BSScene scene, BSPrimLinkable parent) : base(scene, parent) 189 public BSLinksetConstraints(BSScene scene, BSPrimLinkable parent) : base(scene, parent)
@@ -110,12 +191,15 @@ public sealed class BSLinksetConstraints : BSLinkset
110 LinksetImpl = LinksetImplementation.Constraint; 191 LinksetImpl = LinksetImplementation.Constraint;
111 } 192 }
112 193
194 private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINT]";
195
113 // When physical properties are changed the linkset needs to recalculate 196 // When physical properties are changed the linkset needs to recalculate
114 // its internal properties. 197 // its internal properties.
115 // This is queued in the 'post taint' queue so the 198 // This is queued in the 'post taint' queue so the
116 // refresh will happen once after all the other taints are applied. 199 // refresh will happen once after all the other taints are applied.
117 public override void Refresh(BSPrimLinkable requestor) 200 public override void Refresh(BSPrimLinkable requestor)
118 { 201 {
202 ScheduleRebuild(requestor);
119 base.Refresh(requestor); 203 base.Refresh(requestor);
120 204
121 } 205 }
@@ -132,10 +216,16 @@ public sealed class BSLinksetConstraints : BSLinkset
132 { 216 {
133 // Queue to happen after all the other taint processing 217 // Queue to happen after all the other taint processing
134 m_physicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() 218 m_physicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate()
219 {
220 if (HasAnyChildren)
135 { 221 {
136 if (HasAnyChildren) 222 // Constraints that have not been changed are not rebuild but make sure
137 RecomputeLinksetConstraints(); 223 // the constraint of the requestor is rebuilt.
138 }); 224 PhysicallyUnlinkAChildFromRoot(LinksetRoot, requestor);
225 // Rebuild the linkset and all its constraints.
226 RecomputeLinksetConstraints();
227 }
228 });
139 } 229 }
140 } 230 }
141 231
@@ -152,7 +242,7 @@ public sealed class BSLinksetConstraints : BSLinkset
152 if (IsRoot(child)) 242 if (IsRoot(child))
153 { 243 {
154 // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly. 244 // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly.
155 ScheduleRebuild(LinksetRoot); 245 Refresh(LinksetRoot);
156 } 246 }
157 return ret; 247 return ret;
158 } 248 }
@@ -171,7 +261,7 @@ public sealed class BSLinksetConstraints : BSLinkset
171 if (IsRoot(child)) 261 if (IsRoot(child))
172 { 262 {
173 // Schedule a rebuild to verify that the root shape is set to the real shape. 263 // Schedule a rebuild to verify that the root shape is set to the real shape.
174 ScheduleRebuild(LinksetRoot); 264 Refresh(LinksetRoot);
175 } 265 }
176 return ret; 266 return ret;
177 } 267 }
@@ -199,7 +289,7 @@ public sealed class BSLinksetConstraints : BSLinkset
199 // Just undo all the constraints for this linkset. Rebuild at the end of the step. 289 // Just undo all the constraints for this linkset. Rebuild at the end of the step.
200 ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); 290 ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot);
201 // Cause the constraints, et al to be rebuilt before the next simulation step. 291 // Cause the constraints, et al to be rebuilt before the next simulation step.
202 ScheduleRebuild(LinksetRoot); 292 Refresh(LinksetRoot);
203 } 293 }
204 return ret; 294 return ret;
205 } 295 }
@@ -217,14 +307,14 @@ public sealed class BSLinksetConstraints : BSLinkset
217 DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); 307 DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
218 308
219 // Cause constraints and assorted properties to be recomputed before the next simulation step. 309 // Cause constraints and assorted properties to be recomputed before the next simulation step.
220 ScheduleRebuild(LinksetRoot); 310 Refresh(LinksetRoot);
221 } 311 }
222 return; 312 return;
223 } 313 }
224 314
225 // Remove the specified child from the linkset. 315 // Remove the specified child from the linkset.
226 // Safe to call even if the child is not really in my linkset. 316 // Safe to call even if the child is not really in my linkset.
227 protected override void RemoveChildFromLinkset(BSPrimLinkable child) 317 protected override void RemoveChildFromLinkset(BSPrimLinkable child, bool inTaintTime)
228 { 318 {
229 if (m_children.Remove(child)) 319 if (m_children.Remove(child))
230 { 320 {
@@ -236,12 +326,12 @@ public sealed class BSLinksetConstraints : BSLinkset
236 rootx.LocalID, rootx.PhysBody.AddrString, 326 rootx.LocalID, rootx.PhysBody.AddrString,
237 childx.LocalID, childx.PhysBody.AddrString); 327 childx.LocalID, childx.PhysBody.AddrString);
238 328
239 m_physicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate() 329 m_physicsScene.TaintedObject(inTaintTime, childx.LocalID, "BSLinksetConstraints.RemoveChildFromLinkset", delegate()
240 { 330 {
241 PhysicallyUnlinkAChildFromRoot(rootx, childx); 331 PhysicallyUnlinkAChildFromRoot(rootx, childx);
242 }); 332 });
243 // See that the linkset parameters are recomputed at the end of the taint time. 333 // See that the linkset parameters are recomputed at the end of the taint time.
244 ScheduleRebuild(LinksetRoot); 334 Refresh(LinksetRoot);
245 } 335 }
246 else 336 else
247 { 337 {
@@ -262,8 +352,8 @@ public sealed class BSLinksetConstraints : BSLinkset
262 // Create a static constraint between the two passed objects 352 // Create a static constraint between the two passed objects
263 private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSLinkInfo li) 353 private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSLinkInfo li)
264 { 354 {
265 BSLinkInfoConstraint liConstraint = li as BSLinkInfoConstraint; 355 BSLinkInfoConstraint linkInfo = li as BSLinkInfoConstraint;
266 if (liConstraint == null) 356 if (linkInfo == null)
267 return null; 357 return null;
268 358
269 // Zero motion for children so they don't interpolate 359 // Zero motion for children so they don't interpolate
@@ -271,27 +361,26 @@ public sealed class BSLinksetConstraints : BSLinkset
271 361
272 BSConstraint constrain = null; 362 BSConstraint constrain = null;
273 363
274 switch (liConstraint.constraintType) 364 switch (linkInfo.constraintType)
275 { 365 {
366 case ConstraintType.FIXED_CONSTRAINT_TYPE:
276 case ConstraintType.D6_CONSTRAINT_TYPE: 367 case ConstraintType.D6_CONSTRAINT_TYPE:
277 // Relative position normalized to the root prim 368 // Relative position normalized to the root prim
278 // Essentually a vector pointing from center of rootPrim to center of li.member 369 // Essentually a vector pointing from center of rootPrim to center of li.member
279 OMV.Vector3 childRelativePosition = liConstraint.member.Position - rootPrim.Position; 370 OMV.Vector3 childRelativePosition = linkInfo.member.Position - rootPrim.Position;
280 371
281 // real world coordinate of midpoint between the two objects 372 // real world coordinate of midpoint between the two objects
282 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); 373 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
283 374
284 DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", 375 DetailLog("{0},BSLinksetConstraint.BuildConstraint,6Dof,rBody={1},cBody={2},rLoc={3},cLoc={4},midLoc={5}",
285 rootPrim.LocalID, 376 rootPrim.LocalID, rootPrim.PhysBody, linkInfo.member.PhysBody,
286 rootPrim.LocalID, rootPrim.PhysBody.AddrString, 377 rootPrim.Position, linkInfo.member.Position, midPoint);
287 liConstraint.member.LocalID, liConstraint.member.PhysBody.AddrString,
288 rootPrim.Position, liConstraint.member.Position, midPoint);
289 378
290 // create a constraint that allows no freedom of movement between the two objects 379 // create a constraint that allows no freedom of movement between the two objects
291 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 380 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
292 381
293 constrain = new BSConstraint6Dof( 382 constrain = new BSConstraint6Dof(
294 m_physicsScene.World, rootPrim.PhysBody, liConstraint.member.PhysBody, midPoint, true, true ); 383 m_physicsScene.World, rootPrim.PhysBody, linkInfo.member.PhysBody, midPoint, true, true );
295 384
296 /* NOTE: below is an attempt to build constraint with full frame computation, etc. 385 /* NOTE: below is an attempt to build constraint with full frame computation, etc.
297 * Using the midpoint is easier since it lets the Bullet code manipulate the transforms 386 * Using the midpoint is easier since it lets the Bullet code manipulate the transforms
@@ -320,11 +409,23 @@ public sealed class BSLinksetConstraints : BSLinkset
320 */ 409 */
321 410
322 break; 411 break;
412 case ConstraintType.D6_SPRING_CONSTRAINT_TYPE:
413 constrain = new BSConstraintSpring(m_physicsScene.World, rootPrim.PhysBody, linkInfo.member.PhysBody,
414 linkInfo.frameInAloc, linkInfo.frameInArot, linkInfo.frameInBloc, linkInfo.frameInBrot,
415 linkInfo.useLinearReferenceFrameA,
416 true /*disableCollisionsBetweenLinkedBodies*/);
417 DetailLog("{0},BSLinksetConstraint.BuildConstraint,spring,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6}",
418 rootPrim.LocalID,
419 rootPrim.LocalID, rootPrim.PhysBody.AddrString,
420 linkInfo.member.LocalID, linkInfo.member.PhysBody.AddrString,
421 rootPrim.Position, linkInfo.member.Position);
422
423 break;
323 default: 424 default:
324 break; 425 break;
325 } 426 }
326 427
327 liConstraint.SetConstraintParameters(constrain); 428 linkInfo.SetLinkParameters(constrain);
328 429
329 m_physicsScene.Constraints.AddConstraint(constrain); 430 m_physicsScene.Constraints.AddConstraint(constrain);
330 431
@@ -343,13 +444,22 @@ public sealed class BSLinksetConstraints : BSLinkset
343 rootPrim.LocalID, rootPrim.PhysBody.AddrString, 444 rootPrim.LocalID, rootPrim.PhysBody.AddrString,
344 childPrim.LocalID, childPrim.PhysBody.AddrString); 445 childPrim.LocalID, childPrim.PhysBody.AddrString);
345 446
346 // Find the constraint for this link and get rid of it from the overall collection and from my list 447 // If asked to unlink root from root, just remove all the constraints
347 if (m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody)) 448 if (rootPrim == childPrim || childPrim == LinksetRoot)
348 { 449 {
349 // Make the child refresh its location 450 PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot);
350 m_physicsScene.PE.PushUpdate(childPrim.PhysBody);
351 ret = true; 451 ret = true;
352 } 452 }
453 else
454 {
455 // Find the constraint for this link and get rid of it from the overall collection and from my list
456 if (m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody))
457 {
458 // Make the child refresh its location
459 m_physicsScene.PE.PushUpdate(childPrim.PhysBody);
460 ret = true;
461 }
462 }
353 463
354 return ret; 464 return ret;
355 } 465 }
@@ -382,9 +492,9 @@ public sealed class BSLinksetConstraints : BSLinkset
382 Rebuilding = true; 492 Rebuilding = true;
383 493
384 // There is no reason to build all this physical stuff for a non-physical linkset. 494 // There is no reason to build all this physical stuff for a non-physical linkset.
385 if (!LinksetRoot.IsPhysicallyActive) 495 if (!LinksetRoot.IsPhysicallyActive || !HasAnyChildren)
386 { 496 {
387 DetailLog("{0},BSLinksetConstraint.RecomputeLinksetCompound,notPhysical", LinksetRoot.LocalID); 497 DetailLog("{0},BSLinksetConstraint.RecomputeLinksetCompound,notPhysicalOrNoChildren", LinksetRoot.LocalID);
388 return; // Note the 'finally' clause at the botton which will get executed. 498 return; // Note the 'finally' clause at the botton which will get executed.
389 } 499 }
390 500
@@ -401,6 +511,7 @@ public sealed class BSLinksetConstraints : BSLinkset
401 // If constraint doesn't exist yet, create it. 511 // If constraint doesn't exist yet, create it.
402 constrain = BuildConstraint(LinksetRoot, li); 512 constrain = BuildConstraint(LinksetRoot, li);
403 } 513 }
514 li.SetLinkParameters(constrain);
404 constrain.RecomputeConstraintVariables(linksetMass); 515 constrain.RecomputeConstraintVariables(linksetMass);
405 516
406 // PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG 517 // PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG
@@ -412,5 +523,324 @@ public sealed class BSLinksetConstraints : BSLinkset
412 Rebuilding = false; 523 Rebuilding = false;
413 } 524 }
414 } 525 }
526
527 #region Extension
528 public override object Extension(string pFunct, params object[] pParams)
529 {
530 object ret = null;
531 switch (pFunct)
532 {
533 // pParams = [ BSPhysObject root, BSPhysObject child, integer linkType ]
534 case ExtendedPhysics.PhysFunctChangeLinkType:
535 if (pParams.Length > 2)
536 {
537 int requestedType = (int)pParams[2];
538 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,requestedType={1}", LinksetRoot.LocalID, requestedType);
539 if (requestedType == (int)ConstraintType.FIXED_CONSTRAINT_TYPE
540 || requestedType == (int)ConstraintType.D6_CONSTRAINT_TYPE
541 || requestedType == (int)ConstraintType.D6_SPRING_CONSTRAINT_TYPE
542 || requestedType == (int)ConstraintType.HINGE_CONSTRAINT_TYPE
543 || requestedType == (int)ConstraintType.CONETWIST_CONSTRAINT_TYPE
544 || requestedType == (int)ConstraintType.SLIDER_CONSTRAINT_TYPE)
545 {
546 BSPrimLinkable child = pParams[1] as BSPrimLinkable;
547 if (child != null)
548 {
549 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,rootID={1},childID={2},type={3}",
550 LinksetRoot.LocalID, LinksetRoot.LocalID, child.LocalID, requestedType);
551 m_physicsScene.TaintedObject(child.LocalID, "BSLinksetConstraint.PhysFunctChangeLinkType", delegate()
552 {
553 // Pick up all the constraints currently created.
554 RemoveDependencies(child);
555
556 BSLinkInfo linkInfo = null;
557 if (TryGetLinkInfo(child, out linkInfo))
558 {
559 BSLinkInfoConstraint linkInfoC = linkInfo as BSLinkInfoConstraint;
560 if (linkInfoC != null)
561 {
562 linkInfoC.constraintType = (ConstraintType)requestedType;
563 ret = (object)true;
564 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,link={1},type={2}",
565 linkInfo.member.LocalID, linkInfo.member.LocalID, linkInfoC.constraintType);
566 }
567 else
568 {
569 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,linkInfoNotConstraint,childID={1}", LinksetRoot.LocalID, child.LocalID);
570 }
571 }
572 else
573 {
574 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,noLinkInfoForChild,childID={1}", LinksetRoot.LocalID, child.LocalID);
575 }
576 // Cause the whole linkset to be rebuilt in post-taint time.
577 Refresh(child);
578 });
579 }
580 else
581 {
582 DetailLog("{0},BSLinksetConstraint.SetLinkType,childNotBSPrimLinkable", LinksetRoot.LocalID);
583 }
584 }
585 else
586 {
587 DetailLog("{0},BSLinksetConstraint.SetLinkType,illegalRequestedType,reqested={1},spring={2}",
588 LinksetRoot.LocalID, requestedType, ((int)ConstraintType.D6_SPRING_CONSTRAINT_TYPE));
589 }
590 }
591 break;
592 // pParams = [ BSPhysObject root, BSPhysObject child ]
593 case ExtendedPhysics.PhysFunctGetLinkType:
594 if (pParams.Length > 0)
595 {
596 BSPrimLinkable child = pParams[1] as BSPrimLinkable;
597 if (child != null)
598 {
599 BSLinkInfo linkInfo = null;
600 if (TryGetLinkInfo(child, out linkInfo))
601 {
602 BSLinkInfoConstraint linkInfoC = linkInfo as BSLinkInfoConstraint;
603 if (linkInfoC != null)
604 {
605 ret = (object)(int)linkInfoC.constraintType;
606 DetailLog("{0},BSLinksetConstraint.GetLinkType,link={1},type={2}",
607 linkInfo.member.LocalID, linkInfo.member.LocalID, linkInfoC.constraintType);
608
609 }
610 }
611 }
612 }
613 break;
614 // pParams = [ BSPhysObject root, BSPhysObject child, int op, object opParams, int op, object opParams, ... ]
615 case ExtendedPhysics.PhysFunctChangeLinkParams:
616 // There should be two parameters: the childActor and a list of parameters to set
617 if (pParams.Length > 2)
618 {
619 BSPrimLinkable child = pParams[1] as BSPrimLinkable;
620 BSLinkInfo baseLinkInfo = null;
621 if (TryGetLinkInfo(child, out baseLinkInfo))
622 {
623 BSLinkInfoConstraint linkInfo = baseLinkInfo as BSLinkInfoConstraint;
624 if (linkInfo != null)
625 {
626 int valueInt;
627 float valueFloat;
628 bool valueBool;
629 OMV.Vector3 valueVector;
630 OMV.Vector3 valueVector2;
631 OMV.Quaternion valueQuaternion;
632 int axisLow, axisHigh;
633
634 int opIndex = 2;
635 while (opIndex < pParams.Length)
636 {
637 int thisOp = 0;
638 string errMsg = "";
639 try
640 {
641 thisOp = (int)pParams[opIndex];
642 DetailLog("{0},BSLinksetConstraint.ChangeLinkParams2,op={1},val={2}",
643 linkInfo.member.LocalID, thisOp, pParams[opIndex + 1]);
644 switch (thisOp)
645 {
646 case ExtendedPhysics.PHYS_PARAM_LINK_TYPE:
647 valueInt = (int)pParams[opIndex + 1];
648 ConstraintType valueType = (ConstraintType)valueInt;
649 if (valueType == ConstraintType.FIXED_CONSTRAINT_TYPE
650 || valueType == ConstraintType.D6_CONSTRAINT_TYPE
651 || valueType == ConstraintType.D6_SPRING_CONSTRAINT_TYPE
652 || valueType == ConstraintType.HINGE_CONSTRAINT_TYPE
653 || valueType == ConstraintType.CONETWIST_CONSTRAINT_TYPE
654 || valueType == ConstraintType.SLIDER_CONSTRAINT_TYPE)
655 {
656 linkInfo.constraintType = valueType;
657 }
658 opIndex += 2;
659 break;
660 case ExtendedPhysics.PHYS_PARAM_FRAMEINA_LOC:
661 errMsg = "PHYS_PARAM_FRAMEINA_LOC takes one parameter of type vector";
662 valueVector = (OMV.Vector3)pParams[opIndex + 1];
663 linkInfo.frameInAloc = valueVector;
664 opIndex += 2;
665 break;
666 case ExtendedPhysics.PHYS_PARAM_FRAMEINA_ROT:
667 errMsg = "PHYS_PARAM_FRAMEINA_ROT takes one parameter of type rotation";
668 valueQuaternion = (OMV.Quaternion)pParams[opIndex + 1];
669 linkInfo.frameInArot = valueQuaternion;
670 opIndex += 2;
671 break;
672 case ExtendedPhysics.PHYS_PARAM_FRAMEINB_LOC:
673 errMsg = "PHYS_PARAM_FRAMEINB_LOC takes one parameter of type vector";
674 valueVector = (OMV.Vector3)pParams[opIndex + 1];
675 linkInfo.frameInBloc = valueVector;
676 opIndex += 2;
677 break;
678 case ExtendedPhysics.PHYS_PARAM_FRAMEINB_ROT:
679 errMsg = "PHYS_PARAM_FRAMEINB_ROT takes one parameter of type rotation";
680 valueQuaternion = (OMV.Quaternion)pParams[opIndex + 1];
681 linkInfo.frameInBrot = valueQuaternion;
682 opIndex += 2;
683 break;
684 case ExtendedPhysics.PHYS_PARAM_LINEAR_LIMIT_LOW:
685 errMsg = "PHYS_PARAM_LINEAR_LIMIT_LOW takes one parameter of type vector";
686 valueVector = (OMV.Vector3)pParams[opIndex + 1];
687 linkInfo.linearLimitLow = valueVector;
688 opIndex += 2;
689 break;
690 case ExtendedPhysics.PHYS_PARAM_LINEAR_LIMIT_HIGH:
691 errMsg = "PHYS_PARAM_LINEAR_LIMIT_HIGH takes one parameter of type vector";
692 valueVector = (OMV.Vector3)pParams[opIndex + 1];
693 linkInfo.linearLimitHigh = valueVector;
694 opIndex += 2;
695 break;
696 case ExtendedPhysics.PHYS_PARAM_ANGULAR_LIMIT_LOW:
697 errMsg = "PHYS_PARAM_ANGULAR_LIMIT_LOW takes one parameter of type vector";
698 valueVector = (OMV.Vector3)pParams[opIndex + 1];
699 linkInfo.angularLimitLow = valueVector;
700 opIndex += 2;
701 break;
702 case ExtendedPhysics.PHYS_PARAM_ANGULAR_LIMIT_HIGH:
703 errMsg = "PHYS_PARAM_ANGULAR_LIMIT_HIGH takes one parameter of type vector";
704 valueVector = (OMV.Vector3)pParams[opIndex + 1];
705 linkInfo.angularLimitHigh = valueVector;
706 opIndex += 2;
707 break;
708 case ExtendedPhysics.PHYS_PARAM_USE_FRAME_OFFSET:
709 errMsg = "PHYS_PARAM_USE_FRAME_OFFSET takes one parameter of type integer (bool)";
710 valueBool = ((int)pParams[opIndex + 1]) != 0;
711 linkInfo.useFrameOffset = valueBool;
712 opIndex += 2;
713 break;
714 case ExtendedPhysics.PHYS_PARAM_ENABLE_TRANSMOTOR:
715 errMsg = "PHYS_PARAM_ENABLE_TRANSMOTOR takes one parameter of type integer (bool)";
716 valueBool = ((int)pParams[opIndex + 1]) != 0;
717 linkInfo.enableTransMotor = valueBool;
718 opIndex += 2;
719 break;
720 case ExtendedPhysics.PHYS_PARAM_TRANSMOTOR_MAXVEL:
721 errMsg = "PHYS_PARAM_TRANSMOTOR_MAXVEL takes one parameter of type float";
722 valueFloat = (float)pParams[opIndex + 1];
723 linkInfo.transMotorMaxVel = valueFloat;
724 opIndex += 2;
725 break;
726 case ExtendedPhysics.PHYS_PARAM_TRANSMOTOR_MAXFORCE:
727 errMsg = "PHYS_PARAM_TRANSMOTOR_MAXFORCE takes one parameter of type float";
728 valueFloat = (float)pParams[opIndex + 1];
729 linkInfo.transMotorMaxForce = valueFloat;
730 opIndex += 2;
731 break;
732 case ExtendedPhysics.PHYS_PARAM_CFM:
733 errMsg = "PHYS_PARAM_CFM takes one parameter of type float";
734 valueFloat = (float)pParams[opIndex + 1];
735 linkInfo.cfm = valueFloat;
736 opIndex += 2;
737 break;
738 case ExtendedPhysics.PHYS_PARAM_ERP:
739 errMsg = "PHYS_PARAM_ERP takes one parameter of type float";
740 valueFloat = (float)pParams[opIndex + 1];
741 linkInfo.erp = valueFloat;
742 opIndex += 2;
743 break;
744 case ExtendedPhysics.PHYS_PARAM_SOLVER_ITERATIONS:
745 errMsg = "PHYS_PARAM_SOLVER_ITERATIONS takes one parameter of type float";
746 valueFloat = (float)pParams[opIndex + 1];
747 linkInfo.solverIterations = valueFloat;
748 opIndex += 2;
749 break;
750 case ExtendedPhysics.PHYS_PARAM_SPRING_AXIS_ENABLE:
751 errMsg = "PHYS_PARAM_SPRING_AXIS_ENABLE takes two parameters of types integer and integer (bool)";
752 valueInt = (int)pParams[opIndex + 1];
753 valueBool = ((int)pParams[opIndex + 2]) != 0;
754 GetAxisRange(valueInt, out axisLow, out axisHigh);
755 for (int ii = axisLow; ii <= axisHigh; ii++)
756 linkInfo.springAxisEnable[ii] = valueBool;
757 opIndex += 3;
758 break;
759 case ExtendedPhysics.PHYS_PARAM_SPRING_DAMPING:
760 errMsg = "PHYS_PARAM_SPRING_DAMPING takes two parameters of types integer and float";
761 valueInt = (int)pParams[opIndex + 1];
762 valueFloat = (float)pParams[opIndex + 2];
763 GetAxisRange(valueInt, out axisLow, out axisHigh);
764 for (int ii = axisLow; ii <= axisHigh; ii++)
765 linkInfo.springDamping[ii] = valueFloat;
766 opIndex += 3;
767 break;
768 case ExtendedPhysics.PHYS_PARAM_SPRING_STIFFNESS:
769 errMsg = "PHYS_PARAM_SPRING_STIFFNESS takes two parameters of types integer and float";
770 valueInt = (int)pParams[opIndex + 1];
771 valueFloat = (float)pParams[opIndex + 2];
772 GetAxisRange(valueInt, out axisLow, out axisHigh);
773 for (int ii = axisLow; ii <= axisHigh; ii++)
774 linkInfo.springStiffness[ii] = valueFloat;
775 opIndex += 3;
776 break;
777 case ExtendedPhysics.PHYS_PARAM_SPRING_EQUILIBRIUM_POINT:
778 errMsg = "PHYS_PARAM_SPRING_EQUILIBRIUM_POINT takes two parameters of type vector";
779 valueVector = (OMV.Vector3)pParams[opIndex + 1];
780 valueVector2 = (OMV.Vector3)pParams[opIndex + 2];
781 linkInfo.springLinearEquilibriumPoint = valueVector;
782 linkInfo.springAngularEquilibriumPoint = valueVector2;
783 opIndex += 3;
784 break;
785 case ExtendedPhysics.PHYS_PARAM_USE_LINEAR_FRAMEA:
786 errMsg = "PHYS_PARAM_USE_LINEAR_FRAMEA takes one parameter of type integer (bool)";
787 valueBool = ((int)pParams[opIndex + 1]) != 0;
788 linkInfo.useLinearReferenceFrameA = valueBool;
789 opIndex += 2;
790 break;
791 default:
792 break;
793 }
794 }
795 catch (InvalidCastException e)
796 {
797 m_physicsScene.Logger.WarnFormat("{0} value of wrong type in physSetLinksetParams: {1}, err={2}",
798 LogHeader, errMsg, e);
799 }
800 catch (Exception e)
801 {
802 m_physicsScene.Logger.WarnFormat("{0} bad parameters in physSetLinksetParams: {1}", LogHeader, e);
803 }
804 }
805 }
806 // Something changed so a rebuild is in order
807 Refresh(child);
808 }
809 }
810 break;
811 default:
812 ret = base.Extension(pFunct, pParams);
813 break;
814 }
815 return ret;
816 }
817
818 // Bullet constraints keep some limit parameters for each linear and angular axis.
819 // Setting same is easier if there is an easy way to see all or types.
820 // This routine returns the array limits for the set of axis.
821 private void GetAxisRange(int rangeSpec, out int low, out int high)
822 {
823 switch (rangeSpec)
824 {
825 case ExtendedPhysics.PHYS_AXIS_LINEAR_ALL:
826 low = 0;
827 high = 2;
828 break;
829 case ExtendedPhysics.PHYS_AXIS_ANGULAR_ALL:
830 low = 3;
831 high = 5;
832 break;
833 case ExtendedPhysics.PHYS_AXIS_ALL:
834 low = 0;
835 high = 5;
836 break;
837 default:
838 low = high = rangeSpec;
839 break;
840 }
841 return;
842 }
843 #endregion // Extension
844
415} 845}
416} 846}