aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/PhysicsModules/BulletS/BSLinksetConstraints.cs
diff options
context:
space:
mode:
authorRobert Adams2015-09-08 04:54:16 -0700
committerRobert Adams2015-09-08 04:54:16 -0700
commite5367d822be9b05e74c859afe2d2956a3e95aa33 (patch)
treee904050a30715df587aa527d7f313755177726a7 /OpenSim/Region/PhysicsModules/BulletS/BSLinksetConstraints.cs
parentadd lost admin_reset_land method (diff)
parentDeleted access control spec from [LoginService] section of standalone config.... (diff)
downloadopensim-SC_OLD-e5367d822be9b05e74c859afe2d2956a3e95aa33.zip
opensim-SC_OLD-e5367d822be9b05e74c859afe2d2956a3e95aa33.tar.gz
opensim-SC_OLD-e5367d822be9b05e74c859afe2d2956a3e95aa33.tar.bz2
opensim-SC_OLD-e5367d822be9b05e74c859afe2d2956a3e95aa33.tar.xz
Merge of ubitworkvarnew with opensim/master as of 20150905.
This integrates the OpenSim refactoring to make physics, etc into modules. AVN physics hasn't been moved to new location. Does not compile yet. Merge branch 'osmaster' into mbworknew1
Diffstat (limited to 'OpenSim/Region/PhysicsModules/BulletS/BSLinksetConstraints.cs')
-rwxr-xr-xOpenSim/Region/PhysicsModules/BulletS/BSLinksetConstraints.cs852
1 files changed, 852 insertions, 0 deletions
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSLinksetConstraints.cs b/OpenSim/Region/PhysicsModules/BulletS/BSLinksetConstraints.cs
new file mode 100755
index 0000000..c4b4c86
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSLinksetConstraints.cs
@@ -0,0 +1,852 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OMV = OpenMetaverse;
32
33namespace OpenSim.Region.PhysicsModule.BulletS
34{
35public sealed class BSLinksetConstraints : BSLinkset
36{
37 // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]";
38
39 public class BSLinkInfoConstraint : BSLinkInfo
40 {
41 public ConstraintType constraintType;
42 public BSConstraint constraint;
43 public OMV.Vector3 linearLimitLow;
44 public OMV.Vector3 linearLimitHigh;
45 public OMV.Vector3 angularLimitLow;
46 public OMV.Vector3 angularLimitHigh;
47 public bool useFrameOffset;
48 public bool enableTransMotor;
49 public float transMotorMaxVel;
50 public float transMotorMaxForce;
51 public float cfm;
52 public float erp;
53 public float solverIterations;
54 //
55 public OMV.Vector3 frameInAloc;
56 public OMV.Quaternion frameInArot;
57 public OMV.Vector3 frameInBloc;
58 public OMV.Quaternion frameInBrot;
59 public bool useLinearReferenceFrameA;
60 // Spring
61 public bool[] springAxisEnable;
62 public float[] springDamping;
63 public float[] springStiffness;
64 public OMV.Vector3 springLinearEquilibriumPoint;
65 public OMV.Vector3 springAngularEquilibriumPoint;
66
67 public BSLinkInfoConstraint(BSPrimLinkable pMember)
68 : base(pMember)
69 {
70 constraint = null;
71 ResetLink();
72 member.PhysScene.DetailLog("{0},BSLinkInfoConstraint.creation", member.LocalID);
73 }
74
75 // Set all the parameters for this constraint to a fixed, non-movable constraint.
76 public override void ResetLink()
77 {
78 // constraintType = ConstraintType.D6_CONSTRAINT_TYPE;
79 constraintType = ConstraintType.BS_FIXED_CONSTRAINT_TYPE;
80 linearLimitLow = OMV.Vector3.Zero;
81 linearLimitHigh = OMV.Vector3.Zero;
82 angularLimitLow = OMV.Vector3.Zero;
83 angularLimitHigh = OMV.Vector3.Zero;
84 useFrameOffset = BSParam.LinkConstraintUseFrameOffset;
85 enableTransMotor = BSParam.LinkConstraintEnableTransMotor;
86 transMotorMaxVel = BSParam.LinkConstraintTransMotorMaxVel;
87 transMotorMaxForce = BSParam.LinkConstraintTransMotorMaxForce;
88 cfm = BSParam.LinkConstraintCFM;
89 erp = BSParam.LinkConstraintERP;
90 solverIterations = BSParam.LinkConstraintSolverIterations;
91 frameInAloc = OMV.Vector3.Zero;
92 frameInArot = OMV.Quaternion.Identity;
93 frameInBloc = OMV.Vector3.Zero;
94 frameInBrot = OMV.Quaternion.Identity;
95 useLinearReferenceFrameA = true;
96 springAxisEnable = new bool[6];
97 springDamping = new float[6];
98 springStiffness = new float[6];
99 for (int ii = 0; ii < springAxisEnable.Length; ii++)
100 {
101 springAxisEnable[ii] = false;
102 springDamping[ii] = BSAPITemplate.SPRING_NOT_SPECIFIED;
103 springStiffness[ii] = BSAPITemplate.SPRING_NOT_SPECIFIED;
104 }
105 springLinearEquilibriumPoint = OMV.Vector3.Zero;
106 springAngularEquilibriumPoint = OMV.Vector3.Zero;
107 member.PhysScene.DetailLog("{0},BSLinkInfoConstraint.ResetLink", member.LocalID);
108 }
109
110 // Given a constraint, apply the current constraint parameters to same.
111 public override void SetLinkParameters(BSConstraint constrain)
112 {
113 member.PhysScene.DetailLog("{0},BSLinkInfoConstraint.SetLinkParameters,type={1}", member.LocalID, constraintType);
114 switch (constraintType)
115 {
116 case ConstraintType.BS_FIXED_CONSTRAINT_TYPE:
117 case ConstraintType.D6_CONSTRAINT_TYPE:
118 BSConstraint6Dof constrain6dof = constrain as BSConstraint6Dof;
119 if (constrain6dof != null)
120 {
121 // NOTE: D6_SPRING_CONSTRAINT_TYPE should be updated if you change any of this code.
122 // zero linear and angular limits makes the objects unable to move in relation to each other
123 constrain6dof.SetLinearLimits(linearLimitLow, linearLimitHigh);
124 constrain6dof.SetAngularLimits(angularLimitLow, angularLimitHigh);
125
126 // tweek the constraint to increase stability
127 constrain6dof.UseFrameOffset(useFrameOffset);
128 constrain6dof.TranslationalLimitMotor(enableTransMotor, transMotorMaxVel, transMotorMaxForce);
129 constrain6dof.SetCFMAndERP(cfm, erp);
130 if (solverIterations != 0f)
131 {
132 constrain6dof.SetSolverIterations(solverIterations);
133 }
134 }
135 break;
136 case ConstraintType.D6_SPRING_CONSTRAINT_TYPE:
137 BSConstraintSpring constrainSpring = constrain as BSConstraintSpring;
138 if (constrainSpring != null)
139 {
140 // zero linear and angular limits makes the objects unable to move in relation to each other
141 constrainSpring.SetLinearLimits(linearLimitLow, linearLimitHigh);
142 constrainSpring.SetAngularLimits(angularLimitLow, angularLimitHigh);
143
144 // tweek the constraint to increase stability
145 constrainSpring.UseFrameOffset(useFrameOffset);
146 constrainSpring.TranslationalLimitMotor(enableTransMotor, transMotorMaxVel, transMotorMaxForce);
147 constrainSpring.SetCFMAndERP(cfm, erp);
148 if (solverIterations != 0f)
149 {
150 constrainSpring.SetSolverIterations(solverIterations);
151 }
152 for (int ii = 0; ii < springAxisEnable.Length; ii++)
153 {
154 constrainSpring.SetAxisEnable(ii, springAxisEnable[ii]);
155 if (springDamping[ii] != BSAPITemplate.SPRING_NOT_SPECIFIED)
156 constrainSpring.SetDamping(ii, springDamping[ii]);
157 if (springStiffness[ii] != BSAPITemplate.SPRING_NOT_SPECIFIED)
158 constrainSpring.SetStiffness(ii, springStiffness[ii]);
159 }
160 constrainSpring.CalculateTransforms();
161
162 if (springLinearEquilibriumPoint != OMV.Vector3.Zero)
163 constrainSpring.SetEquilibriumPoint(springLinearEquilibriumPoint, springAngularEquilibriumPoint);
164 else
165 constrainSpring.SetEquilibriumPoint(BSAPITemplate.SPRING_NOT_SPECIFIED, BSAPITemplate.SPRING_NOT_SPECIFIED);
166 }
167 break;
168 default:
169 break;
170 }
171 }
172
173 // Return 'true' if the property updates from the physics engine should be reported
174 // to the simulator.
175 // If the constraint is fixed, we don't need to report as the simulator and viewer will
176 // report the right things.
177 public override bool ShouldUpdateChildProperties()
178 {
179 bool ret = true;
180 if (constraintType == ConstraintType.BS_FIXED_CONSTRAINT_TYPE)
181 ret = false;
182
183 return ret;
184 }
185 }
186
187 public BSLinksetConstraints(BSScene scene, BSPrimLinkable parent) : base(scene, parent)
188 {
189 LinksetImpl = LinksetImplementation.Constraint;
190 }
191
192 private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINT]";
193
194 // When physical properties are changed the linkset needs to recalculate
195 // its internal properties.
196 // This is queued in the 'post taint' queue so the
197 // refresh will happen once after all the other taints are applied.
198 public override void Refresh(BSPrimLinkable requestor)
199 {
200 ScheduleRebuild(requestor);
201 base.Refresh(requestor);
202
203 }
204
205 private void ScheduleRebuild(BSPrimLinkable requestor)
206 {
207 DetailLog("{0},BSLinksetConstraint.ScheduleRebuild,,rebuilding={1},hasChildren={2},actuallyScheduling={3}",
208 requestor.LocalID, Rebuilding, HasAnyChildren, (!Rebuilding && HasAnyChildren));
209
210 // When rebuilding, it is possible to set properties that would normally require a rebuild.
211 // If already rebuilding, don't request another rebuild.
212 // If a linkset with just a root prim (simple non-linked prim) don't bother rebuilding.
213 lock (this)
214 {
215 if (!RebuildScheduled)
216 {
217 if (!Rebuilding && HasAnyChildren)
218 {
219 RebuildScheduled = true;
220 // Queue to happen after all the other taint processing
221 m_physicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate()
222 {
223 if (HasAnyChildren)
224 {
225 // Constraints that have not been changed are not rebuild but make sure
226 // the constraint of the requestor is rebuilt.
227 PhysicallyUnlinkAChildFromRoot(LinksetRoot, requestor);
228 // Rebuild the linkset and all its constraints.
229 RecomputeLinksetConstraints();
230 }
231 RebuildScheduled = false;
232 });
233 }
234 }
235 }
236 }
237
238 // The object is going dynamic (physical). Do any setup necessary
239 // for a dynamic linkset.
240 // Only the state of the passed object can be modified. The rest of the linkset
241 // has not yet been fully constructed.
242 // Return 'true' if any properties updated on the passed object.
243 // Called at taint-time!
244 public override bool MakeDynamic(BSPrimLinkable child)
245 {
246 bool ret = false;
247 DetailLog("{0},BSLinksetConstraints.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child));
248 if (IsRoot(child))
249 {
250 // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly.
251 Refresh(LinksetRoot);
252 }
253 return ret;
254 }
255
256 // The object is going static (non-physical). Do any setup necessary for a static linkset.
257 // Return 'true' if any properties updated on the passed object.
258 // This doesn't normally happen -- OpenSim removes the objects from the physical
259 // world if it is a static linkset.
260 // Called at taint-time!
261 public override bool MakeStatic(BSPrimLinkable child)
262 {
263 bool ret = false;
264
265 DetailLog("{0},BSLinksetConstraint.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child));
266 child.ClearDisplacement();
267 if (IsRoot(child))
268 {
269 // Schedule a rebuild to verify that the root shape is set to the real shape.
270 Refresh(LinksetRoot);
271 }
272 return ret;
273 }
274
275 // Called at taint-time!!
276 public override void UpdateProperties(UpdatedProperties whichUpdated, BSPrimLinkable pObj)
277 {
278 // Nothing to do for constraints on property updates
279 }
280
281 // Routine called when rebuilding the body of some member of the linkset.
282 // Destroy all the constraints have have been made to root and set
283 // up to rebuild the constraints before the next simulation step.
284 // Returns 'true' of something was actually removed and would need restoring
285 // Called at taint-time!!
286 public override bool RemoveDependencies(BSPrimLinkable child)
287 {
288 bool ret = false;
289
290 DetailLog("{0},BSLinksetConstraint.RemoveDependencies,removeChildrenForRoot,rID={1},rBody={2}",
291 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString);
292
293 lock (m_linksetActivityLock)
294 {
295 // Just undo all the constraints for this linkset. Rebuild at the end of the step.
296 ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot);
297 // Cause the constraints, et al to be rebuilt before the next simulation step.
298 Refresh(LinksetRoot);
299 }
300 return ret;
301 }
302
303 // ================================================================
304
305 // Add a new child to the linkset.
306 // Called while LinkActivity is locked.
307 protected override void AddChildToLinkset(BSPrimLinkable child)
308 {
309 if (!HasChild(child))
310 {
311 m_children.Add(child, new BSLinkInfoConstraint(child));
312
313 DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
314
315 // Cause constraints and assorted properties to be recomputed before the next simulation step.
316 Refresh(LinksetRoot);
317 }
318 return;
319 }
320
321 // Remove the specified child from the linkset.
322 // Safe to call even if the child is not really in my linkset.
323 protected override void RemoveChildFromLinkset(BSPrimLinkable child, bool inTaintTime)
324 {
325 if (m_children.Remove(child))
326 {
327 BSPrimLinkable rootx = LinksetRoot; // capture the root and body as of now
328 BSPrimLinkable childx = child;
329
330 DetailLog("{0},BSLinksetConstraints.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
331 childx.LocalID,
332 rootx.LocalID, rootx.PhysBody.AddrString,
333 childx.LocalID, childx.PhysBody.AddrString);
334
335 m_physicsScene.TaintedObject(inTaintTime, childx.LocalID, "BSLinksetConstraints.RemoveChildFromLinkset", delegate()
336 {
337 PhysicallyUnlinkAChildFromRoot(rootx, childx);
338 });
339 // See that the linkset parameters are recomputed at the end of the taint time.
340 Refresh(LinksetRoot);
341 }
342 else
343 {
344 // Non-fatal occurance.
345 // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader);
346 }
347 return;
348 }
349
350 // Create a constraint between me (root of linkset) and the passed prim (the child).
351 // Called at taint time!
352 private void PhysicallyLinkAChildToRoot(BSPrimLinkable rootPrim, BSPrimLinkable childPrim)
353 {
354 // Don't build the constraint when asked. Put it off until just before the simulation step.
355 Refresh(rootPrim);
356 }
357
358 // Create a static constraint between the two passed objects
359 private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSLinkInfo li)
360 {
361 BSLinkInfoConstraint linkInfo = li as BSLinkInfoConstraint;
362 if (linkInfo == null)
363 return null;
364
365 // Zero motion for children so they don't interpolate
366 li.member.ZeroMotion(true);
367
368 BSConstraint constrain = null;
369
370 switch (linkInfo.constraintType)
371 {
372 case ConstraintType.BS_FIXED_CONSTRAINT_TYPE:
373 case ConstraintType.D6_CONSTRAINT_TYPE:
374 // Relative position normalized to the root prim
375 // Essentually a vector pointing from center of rootPrim to center of li.member
376 OMV.Vector3 childRelativePosition = linkInfo.member.Position - rootPrim.Position;
377
378 // real world coordinate of midpoint between the two objects
379 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
380
381 DetailLog("{0},BSLinksetConstraint.BuildConstraint,6Dof,rBody={1},cBody={2},rLoc={3},cLoc={4},midLoc={5}",
382 rootPrim.LocalID, rootPrim.PhysBody, linkInfo.member.PhysBody,
383 rootPrim.Position, linkInfo.member.Position, midPoint);
384
385 // create a constraint that allows no freedom of movement between the two objects
386 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
387
388 constrain = new BSConstraint6Dof(
389 m_physicsScene.World, rootPrim.PhysBody, linkInfo.member.PhysBody, midPoint, true, true );
390
391 /* NOTE: below is an attempt to build constraint with full frame computation, etc.
392 * Using the midpoint is easier since it lets the Bullet code manipulate the transforms
393 * of the objects.
394 * Code left for future programmers.
395 // ==================================================================================
396 // relative position normalized to the root prim
397 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
398 OMV.Vector3 childRelativePosition = (liConstraint.member.Position - rootPrim.Position) * invThisOrientation;
399
400 // relative rotation of the child to the parent
401 OMV.Quaternion childRelativeRotation = invThisOrientation * liConstraint.member.Orientation;
402 OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
403
404 DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, liConstraint.member.LocalID);
405 constrain = new BS6DofConstraint(
406 PhysicsScene.World, rootPrim.Body, liConstraint.member.Body,
407 OMV.Vector3.Zero,
408 OMV.Quaternion.Inverse(rootPrim.Orientation),
409 OMV.Vector3.Zero,
410 OMV.Quaternion.Inverse(liConstraint.member.Orientation),
411 true,
412 true
413 );
414 // ==================================================================================
415 */
416
417 break;
418 case ConstraintType.D6_SPRING_CONSTRAINT_TYPE:
419 constrain = new BSConstraintSpring(m_physicsScene.World, rootPrim.PhysBody, linkInfo.member.PhysBody,
420 linkInfo.frameInAloc, linkInfo.frameInArot, linkInfo.frameInBloc, linkInfo.frameInBrot,
421 linkInfo.useLinearReferenceFrameA,
422 true /*disableCollisionsBetweenLinkedBodies*/);
423 DetailLog("{0},BSLinksetConstraint.BuildConstraint,spring,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6}",
424 rootPrim.LocalID,
425 rootPrim.LocalID, rootPrim.PhysBody.AddrString,
426 linkInfo.member.LocalID, linkInfo.member.PhysBody.AddrString,
427 rootPrim.Position, linkInfo.member.Position);
428
429 break;
430 default:
431 break;
432 }
433
434 linkInfo.SetLinkParameters(constrain);
435
436 m_physicsScene.Constraints.AddConstraint(constrain);
437
438 return constrain;
439 }
440
441 // Remove linkage between the linkset root and a particular child
442 // The root and child bodies are passed in because we need to remove the constraint between
443 // the bodies that were present at unlink time.
444 // Called at taint time!
445 private bool PhysicallyUnlinkAChildFromRoot(BSPrimLinkable rootPrim, BSPrimLinkable childPrim)
446 {
447 bool ret = false;
448 DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}",
449 rootPrim.LocalID,
450 rootPrim.LocalID, rootPrim.PhysBody.AddrString,
451 childPrim.LocalID, childPrim.PhysBody.AddrString);
452
453 // If asked to unlink root from root, just remove all the constraints
454 if (rootPrim == childPrim || childPrim == LinksetRoot)
455 {
456 PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot);
457 ret = true;
458 }
459 else
460 {
461 // Find the constraint for this link and get rid of it from the overall collection and from my list
462 if (m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody))
463 {
464 // Make the child refresh its location
465 m_physicsScene.PE.PushUpdate(childPrim.PhysBody);
466 ret = true;
467 }
468 }
469
470 return ret;
471 }
472
473 // Remove linkage between myself and any possible children I might have.
474 // Returns 'true' of any constraints were destroyed.
475 // Called at taint time!
476 private bool PhysicallyUnlinkAllChildrenFromRoot(BSPrimLinkable rootPrim)
477 {
478 DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
479
480 return m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody);
481 }
482
483 // Call each of the constraints that make up this linkset and recompute the
484 // various transforms and variables. Create constraints of not created yet.
485 // Called before the simulation step to make sure the constraint based linkset
486 // is all initialized.
487 // Called at taint time!!
488 private void RecomputeLinksetConstraints()
489 {
490 float linksetMass = LinksetMass;
491 LinksetRoot.UpdatePhysicalMassProperties(linksetMass, true);
492
493 DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}",
494 LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString, linksetMass);
495
496 try
497 {
498 Rebuilding = true;
499
500 // There is no reason to build all this physical stuff for a non-physical linkset.
501 if (!LinksetRoot.IsPhysicallyActive || !HasAnyChildren)
502 {
503 DetailLog("{0},BSLinksetConstraint.RecomputeLinksetCompound,notPhysicalOrNoChildren", LinksetRoot.LocalID);
504 return; // Note the 'finally' clause at the botton which will get executed.
505 }
506
507 ForEachLinkInfo((li) =>
508 {
509 // A child in the linkset physically shows the mass of the whole linkset.
510 // This allows Bullet to apply enough force on the child to move the whole linkset.
511 // (Also do the mass stuff before recomputing the constraint so mass is not zero.)
512 li.member.UpdatePhysicalMassProperties(linksetMass, true);
513
514 BSConstraint constrain;
515 if (!m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, li.member.PhysBody, out constrain))
516 {
517 // If constraint doesn't exist yet, create it.
518 constrain = BuildConstraint(LinksetRoot, li);
519 }
520 li.SetLinkParameters(constrain);
521 constrain.RecomputeConstraintVariables(linksetMass);
522
523 // PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG
524 return false; // 'false' says to keep processing other members
525 });
526 }
527 finally
528 {
529 Rebuilding = false;
530 }
531 }
532
533 #region Extension
534 public override object Extension(string pFunct, params object[] pParams)
535 {
536 object ret = null;
537 switch (pFunct)
538 {
539 // pParams = [ BSPhysObject root, BSPhysObject child, integer linkType ]
540 case ExtendedPhysics.PhysFunctChangeLinkType:
541 if (pParams.Length > 2)
542 {
543 int requestedType = (int)pParams[2];
544 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,requestedType={1}", LinksetRoot.LocalID, requestedType);
545 if (requestedType == (int)ConstraintType.BS_FIXED_CONSTRAINT_TYPE
546 || requestedType == (int)ConstraintType.D6_CONSTRAINT_TYPE
547 || requestedType == (int)ConstraintType.D6_SPRING_CONSTRAINT_TYPE
548 || requestedType == (int)ConstraintType.HINGE_CONSTRAINT_TYPE
549 || requestedType == (int)ConstraintType.CONETWIST_CONSTRAINT_TYPE
550 || requestedType == (int)ConstraintType.SLIDER_CONSTRAINT_TYPE)
551 {
552 BSPrimLinkable child = pParams[1] as BSPrimLinkable;
553 if (child != null)
554 {
555 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,rootID={1},childID={2},type={3}",
556 LinksetRoot.LocalID, LinksetRoot.LocalID, child.LocalID, requestedType);
557 m_physicsScene.TaintedObject(child.LocalID, "BSLinksetConstraint.PhysFunctChangeLinkType", delegate()
558 {
559 // Pick up all the constraints currently created.
560 RemoveDependencies(child);
561
562 BSLinkInfo linkInfo = null;
563 if (TryGetLinkInfo(child, out linkInfo))
564 {
565 BSLinkInfoConstraint linkInfoC = linkInfo as BSLinkInfoConstraint;
566 if (linkInfoC != null)
567 {
568 linkInfoC.constraintType = (ConstraintType)requestedType;
569 ret = (object)true;
570 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,link={1},type={2}",
571 linkInfo.member.LocalID, linkInfo.member.LocalID, linkInfoC.constraintType);
572 }
573 else
574 {
575 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,linkInfoNotConstraint,childID={1}", LinksetRoot.LocalID, child.LocalID);
576 }
577 }
578 else
579 {
580 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,noLinkInfoForChild,childID={1}", LinksetRoot.LocalID, child.LocalID);
581 }
582 // Cause the whole linkset to be rebuilt in post-taint time.
583 Refresh(child);
584 });
585 }
586 else
587 {
588 DetailLog("{0},BSLinksetConstraint.SetLinkType,childNotBSPrimLinkable", LinksetRoot.LocalID);
589 }
590 }
591 else
592 {
593 DetailLog("{0},BSLinksetConstraint.SetLinkType,illegalRequestedType,reqested={1},spring={2}",
594 LinksetRoot.LocalID, requestedType, ((int)ConstraintType.D6_SPRING_CONSTRAINT_TYPE));
595 }
596 }
597 break;
598 // pParams = [ BSPhysObject root, BSPhysObject child ]
599 case ExtendedPhysics.PhysFunctGetLinkType:
600 if (pParams.Length > 0)
601 {
602 BSPrimLinkable child = pParams[1] as BSPrimLinkable;
603 if (child != null)
604 {
605 BSLinkInfo linkInfo = null;
606 if (TryGetLinkInfo(child, out linkInfo))
607 {
608 BSLinkInfoConstraint linkInfoC = linkInfo as BSLinkInfoConstraint;
609 if (linkInfoC != null)
610 {
611 ret = (object)(int)linkInfoC.constraintType;
612 DetailLog("{0},BSLinksetConstraint.GetLinkType,link={1},type={2}",
613 linkInfo.member.LocalID, linkInfo.member.LocalID, linkInfoC.constraintType);
614
615 }
616 }
617 }
618 }
619 break;
620 // pParams = [ BSPhysObject root, BSPhysObject child, int op, object opParams, int op, object opParams, ... ]
621 case ExtendedPhysics.PhysFunctChangeLinkParams:
622 // There should be two parameters: the childActor and a list of parameters to set
623 if (pParams.Length > 2)
624 {
625 BSPrimLinkable child = pParams[1] as BSPrimLinkable;
626 BSLinkInfo baseLinkInfo = null;
627 if (TryGetLinkInfo(child, out baseLinkInfo))
628 {
629 BSLinkInfoConstraint linkInfo = baseLinkInfo as BSLinkInfoConstraint;
630 if (linkInfo != null)
631 {
632 int valueInt;
633 float valueFloat;
634 bool valueBool;
635 OMV.Vector3 valueVector;
636 OMV.Vector3 valueVector2;
637 OMV.Quaternion valueQuaternion;
638 int axisLow, axisHigh;
639
640 int opIndex = 2;
641 while (opIndex < pParams.Length)
642 {
643 int thisOp = 0;
644 string errMsg = "";
645 try
646 {
647 thisOp = (int)pParams[opIndex];
648 DetailLog("{0},BSLinksetConstraint.ChangeLinkParams2,op={1},val={2}",
649 linkInfo.member.LocalID, thisOp, pParams[opIndex + 1]);
650 switch (thisOp)
651 {
652 case ExtendedPhysics.PHYS_PARAM_LINK_TYPE:
653 valueInt = (int)pParams[opIndex + 1];
654 ConstraintType valueType = (ConstraintType)valueInt;
655 if (valueType == ConstraintType.BS_FIXED_CONSTRAINT_TYPE
656 || valueType == ConstraintType.D6_CONSTRAINT_TYPE
657 || valueType == ConstraintType.D6_SPRING_CONSTRAINT_TYPE
658 || valueType == ConstraintType.HINGE_CONSTRAINT_TYPE
659 || valueType == ConstraintType.CONETWIST_CONSTRAINT_TYPE
660 || valueType == ConstraintType.SLIDER_CONSTRAINT_TYPE)
661 {
662 linkInfo.constraintType = valueType;
663 }
664 opIndex += 2;
665 break;
666 case ExtendedPhysics.PHYS_PARAM_FRAMEINA_LOC:
667 errMsg = "PHYS_PARAM_FRAMEINA_LOC takes one parameter of type vector";
668 valueVector = (OMV.Vector3)pParams[opIndex + 1];
669 linkInfo.frameInAloc = valueVector;
670 opIndex += 2;
671 break;
672 case ExtendedPhysics.PHYS_PARAM_FRAMEINA_ROT:
673 errMsg = "PHYS_PARAM_FRAMEINA_ROT takes one parameter of type rotation";
674 valueQuaternion = (OMV.Quaternion)pParams[opIndex + 1];
675 linkInfo.frameInArot = valueQuaternion;
676 opIndex += 2;
677 break;
678 case ExtendedPhysics.PHYS_PARAM_FRAMEINB_LOC:
679 errMsg = "PHYS_PARAM_FRAMEINB_LOC takes one parameter of type vector";
680 valueVector = (OMV.Vector3)pParams[opIndex + 1];
681 linkInfo.frameInBloc = valueVector;
682 opIndex += 2;
683 break;
684 case ExtendedPhysics.PHYS_PARAM_FRAMEINB_ROT:
685 errMsg = "PHYS_PARAM_FRAMEINB_ROT takes one parameter of type rotation";
686 valueQuaternion = (OMV.Quaternion)pParams[opIndex + 1];
687 linkInfo.frameInBrot = valueQuaternion;
688 opIndex += 2;
689 break;
690 case ExtendedPhysics.PHYS_PARAM_LINEAR_LIMIT_LOW:
691 errMsg = "PHYS_PARAM_LINEAR_LIMIT_LOW takes one parameter of type vector";
692 valueVector = (OMV.Vector3)pParams[opIndex + 1];
693 linkInfo.linearLimitLow = valueVector;
694 opIndex += 2;
695 break;
696 case ExtendedPhysics.PHYS_PARAM_LINEAR_LIMIT_HIGH:
697 errMsg = "PHYS_PARAM_LINEAR_LIMIT_HIGH takes one parameter of type vector";
698 valueVector = (OMV.Vector3)pParams[opIndex + 1];
699 linkInfo.linearLimitHigh = valueVector;
700 opIndex += 2;
701 break;
702 case ExtendedPhysics.PHYS_PARAM_ANGULAR_LIMIT_LOW:
703 errMsg = "PHYS_PARAM_ANGULAR_LIMIT_LOW takes one parameter of type vector";
704 valueVector = (OMV.Vector3)pParams[opIndex + 1];
705 linkInfo.angularLimitLow = valueVector;
706 opIndex += 2;
707 break;
708 case ExtendedPhysics.PHYS_PARAM_ANGULAR_LIMIT_HIGH:
709 errMsg = "PHYS_PARAM_ANGULAR_LIMIT_HIGH takes one parameter of type vector";
710 valueVector = (OMV.Vector3)pParams[opIndex + 1];
711 linkInfo.angularLimitHigh = valueVector;
712 opIndex += 2;
713 break;
714 case ExtendedPhysics.PHYS_PARAM_USE_FRAME_OFFSET:
715 errMsg = "PHYS_PARAM_USE_FRAME_OFFSET takes one parameter of type integer (bool)";
716 valueBool = ((int)pParams[opIndex + 1]) != 0;
717 linkInfo.useFrameOffset = valueBool;
718 opIndex += 2;
719 break;
720 case ExtendedPhysics.PHYS_PARAM_ENABLE_TRANSMOTOR:
721 errMsg = "PHYS_PARAM_ENABLE_TRANSMOTOR takes one parameter of type integer (bool)";
722 valueBool = ((int)pParams[opIndex + 1]) != 0;
723 linkInfo.enableTransMotor = valueBool;
724 opIndex += 2;
725 break;
726 case ExtendedPhysics.PHYS_PARAM_TRANSMOTOR_MAXVEL:
727 errMsg = "PHYS_PARAM_TRANSMOTOR_MAXVEL takes one parameter of type float";
728 valueFloat = (float)pParams[opIndex + 1];
729 linkInfo.transMotorMaxVel = valueFloat;
730 opIndex += 2;
731 break;
732 case ExtendedPhysics.PHYS_PARAM_TRANSMOTOR_MAXFORCE:
733 errMsg = "PHYS_PARAM_TRANSMOTOR_MAXFORCE takes one parameter of type float";
734 valueFloat = (float)pParams[opIndex + 1];
735 linkInfo.transMotorMaxForce = valueFloat;
736 opIndex += 2;
737 break;
738 case ExtendedPhysics.PHYS_PARAM_CFM:
739 errMsg = "PHYS_PARAM_CFM takes one parameter of type float";
740 valueFloat = (float)pParams[opIndex + 1];
741 linkInfo.cfm = valueFloat;
742 opIndex += 2;
743 break;
744 case ExtendedPhysics.PHYS_PARAM_ERP:
745 errMsg = "PHYS_PARAM_ERP takes one parameter of type float";
746 valueFloat = (float)pParams[opIndex + 1];
747 linkInfo.erp = valueFloat;
748 opIndex += 2;
749 break;
750 case ExtendedPhysics.PHYS_PARAM_SOLVER_ITERATIONS:
751 errMsg = "PHYS_PARAM_SOLVER_ITERATIONS takes one parameter of type float";
752 valueFloat = (float)pParams[opIndex + 1];
753 linkInfo.solverIterations = valueFloat;
754 opIndex += 2;
755 break;
756 case ExtendedPhysics.PHYS_PARAM_SPRING_AXIS_ENABLE:
757 errMsg = "PHYS_PARAM_SPRING_AXIS_ENABLE takes two parameters of types integer and integer (bool)";
758 valueInt = (int)pParams[opIndex + 1];
759 valueBool = ((int)pParams[opIndex + 2]) != 0;
760 GetAxisRange(valueInt, out axisLow, out axisHigh);
761 for (int ii = axisLow; ii <= axisHigh; ii++)
762 linkInfo.springAxisEnable[ii] = valueBool;
763 opIndex += 3;
764 break;
765 case ExtendedPhysics.PHYS_PARAM_SPRING_DAMPING:
766 errMsg = "PHYS_PARAM_SPRING_DAMPING takes two parameters of types integer and float";
767 valueInt = (int)pParams[opIndex + 1];
768 valueFloat = (float)pParams[opIndex + 2];
769 GetAxisRange(valueInt, out axisLow, out axisHigh);
770 for (int ii = axisLow; ii <= axisHigh; ii++)
771 linkInfo.springDamping[ii] = valueFloat;
772 opIndex += 3;
773 break;
774 case ExtendedPhysics.PHYS_PARAM_SPRING_STIFFNESS:
775 errMsg = "PHYS_PARAM_SPRING_STIFFNESS takes two parameters of types integer and float";
776 valueInt = (int)pParams[opIndex + 1];
777 valueFloat = (float)pParams[opIndex + 2];
778 GetAxisRange(valueInt, out axisLow, out axisHigh);
779 for (int ii = axisLow; ii <= axisHigh; ii++)
780 linkInfo.springStiffness[ii] = valueFloat;
781 opIndex += 3;
782 break;
783 case ExtendedPhysics.PHYS_PARAM_SPRING_EQUILIBRIUM_POINT:
784 errMsg = "PHYS_PARAM_SPRING_EQUILIBRIUM_POINT takes two parameters of type vector";
785 valueVector = (OMV.Vector3)pParams[opIndex + 1];
786 valueVector2 = (OMV.Vector3)pParams[opIndex + 2];
787 linkInfo.springLinearEquilibriumPoint = valueVector;
788 linkInfo.springAngularEquilibriumPoint = valueVector2;
789 opIndex += 3;
790 break;
791 case ExtendedPhysics.PHYS_PARAM_USE_LINEAR_FRAMEA:
792 errMsg = "PHYS_PARAM_USE_LINEAR_FRAMEA takes one parameter of type integer (bool)";
793 valueBool = ((int)pParams[opIndex + 1]) != 0;
794 linkInfo.useLinearReferenceFrameA = valueBool;
795 opIndex += 2;
796 break;
797 default:
798 break;
799 }
800 }
801 catch (InvalidCastException e)
802 {
803 m_physicsScene.Logger.WarnFormat("{0} value of wrong type in physSetLinksetParams: {1}, err={2}",
804 LogHeader, errMsg, e);
805 }
806 catch (Exception e)
807 {
808 m_physicsScene.Logger.WarnFormat("{0} bad parameters in physSetLinksetParams: {1}", LogHeader, e);
809 }
810 }
811 }
812 // Something changed so a rebuild is in order
813 Refresh(child);
814 }
815 }
816 break;
817 default:
818 ret = base.Extension(pFunct, pParams);
819 break;
820 }
821 return ret;
822 }
823
824 // Bullet constraints keep some limit parameters for each linear and angular axis.
825 // Setting same is easier if there is an easy way to see all or types.
826 // This routine returns the array limits for the set of axis.
827 private void GetAxisRange(int rangeSpec, out int low, out int high)
828 {
829 switch (rangeSpec)
830 {
831 case ExtendedPhysics.PHYS_AXIS_LINEAR_ALL:
832 low = 0;
833 high = 2;
834 break;
835 case ExtendedPhysics.PHYS_AXIS_ANGULAR_ALL:
836 low = 3;
837 high = 5;
838 break;
839 case ExtendedPhysics.PHYS_AXIS_ALL:
840 low = 0;
841 high = 5;
842 break;
843 default:
844 low = high = rangeSpec;
845 break;
846 }
847 return;
848 }
849 #endregion // Extension
850
851}
852}