/// <summary> /// Splits a single compound collidable into two separate compound collidables and computes information needed by the simulation. /// </summary> /// <param name="childContributions">List of distribution information associated with each child shape of the whole compound shape used by the compound being split.</param> /// <param name="splitPredicate">Delegate which determines if a child in the original compound should be moved to the new compound.</param> /// <param name="a">Original compound to be split. Children in this compound will be removed and added to the other compound.</param> /// <param name="b">Compound to receive children removed from the original compound.</param> /// <param name="distributionInfoA">Volume, volume distribution, and center information about the new form of the original compound collidable.</param> /// <param name="distributionInfoB">Volume, volume distribution, and center information about the new compound collidable.</param> /// <returns>Whether or not the predicate returned true for any element in the original compound and split the compound.</returns> public static bool SplitCompound(IList<ShapeDistributionInformation> childContributions, Func<CompoundChild, bool> splitPredicate, Entity<CompoundCollidable> a, out Entity<CompoundCollidable> b, out ShapeDistributionInformation distributionInfoA, out ShapeDistributionInformation distributionInfoB) { var bCollidable = new CompoundCollidable { Shape = a.CollisionInformation.Shape }; b = null; float weightA, weightB; if (SplitCompound(childContributions, splitPredicate, a.CollisionInformation, bCollidable, out distributionInfoA, out distributionInfoB, out weightA, out weightB)) { //Reconfigure the entities using the data computed in the split. float originalMass = a.mass; if (a.CollisionInformation.children.Count > 0) { float newMassA = (weightA / (weightA + weightB)) * originalMass; Matrix3x3.Multiply(ref distributionInfoA.VolumeDistribution, newMassA * InertiaHelper.InertiaTensorScale, out distributionInfoA.VolumeDistribution); a.Initialize(a.CollisionInformation, newMassA, distributionInfoA.VolumeDistribution, distributionInfoA.Volume); } if (bCollidable.children.Count > 0) { float newMassB = (weightB / (weightA + weightB)) * originalMass; Matrix3x3.Multiply(ref distributionInfoB.VolumeDistribution, newMassB * InertiaHelper.InertiaTensorScale, out distributionInfoB.VolumeDistribution); b = new Entity<CompoundCollidable>(); b.Initialize(bCollidable, newMassB, distributionInfoB.VolumeDistribution, distributionInfoB.Volume); } SplitReposition(a, b, ref distributionInfoA, ref distributionInfoB, weightA, weightB); return true; } else return false; }
/// <summary> /// Removes a child from a compound body. /// </summary> /// <param name="childContributions">List of distribution information associated with each child shape of the whole compound shape used by the compound being split.</param> /// <param name="removalPredicate">Delegate which determines if a child in the original compound should be moved to the new compound.</param> /// <param name="distributionInfo">Volume, volume distribution, and center information about the new form of the original compound collidable.</param> /// <param name="compound">Original compound to have a child removed.</param> /// <returns>Whether or not the predicate returned true for any element in the original compound and split the compound.</returns> public static bool RemoveChildFromCompound(Entity<CompoundCollidable> compound, Func<CompoundChild, bool> removalPredicate, IList<ShapeDistributionInformation> childContributions, out ShapeDistributionInformation distributionInfo) { float weight; float removedWeight; Vector3 removedCenter; if (RemoveChildFromCompound(compound.CollisionInformation, removalPredicate, childContributions, out distributionInfo, out weight, out removedWeight, out removedCenter)) { //Reconfigure the entities using the data computed in the split. //Only bother if there are any children left in the compound! if (compound.CollisionInformation.Children.Count > 0) { float originalMass = compound.mass; float newMass = (weight / (weight + removedWeight)) * originalMass; Matrix3x3.Multiply(ref distributionInfo.VolumeDistribution, newMass * InertiaHelper.InertiaTensorScale, out distributionInfo.VolumeDistribution); compound.Initialize(compound.CollisionInformation, newMass, distributionInfo.VolumeDistribution, distributionInfo.Volume); RemoveReposition(compound, ref distributionInfo, weight, removedWeight, ref removedCenter); } return true; } else return false; }