public void ComposeShape() { ColliderShapeChanged = false; if (ColliderShape != null) { if (!ColliderShape.IsPartOfAsset) { ColliderShape.Dispose(); ColliderShape = null; } else { ColliderShape = null; } } CanScaleShape = true; if (ColliderShapes.Count == 1) //single shape case { if (ColliderShapes[0] == null) { return; } if (ColliderShapes[0].GetType() == typeof(ColliderShapeAssetDesc)) { CanScaleShape = false; } ColliderShape = PhysicsColliderShape.CreateShape(ColliderShapes[0]); ColliderShape?.UpdateLocalTransformations(); } else if (ColliderShapes.Count > 1) //need a compound shape in this case { var compound = new CompoundColliderShape(); foreach (var desc in ColliderShapes) { if (desc == null) { continue; } if (desc.GetType() == typeof(ColliderShapeAssetDesc)) { CanScaleShape = false; } var subShape = PhysicsColliderShape.CreateShape(desc); if (subShape != null) { compound.AddChildShape(subShape); } } ColliderShape = compound; ColliderShape.UpdateLocalTransformations(); } }
internal static ColliderShape Compose(IReadOnlyList <IAssetColliderShapeDesc> descs) { ColliderShape res = null; if (descs.Count == 1) //single shape case { res = CreateShape(descs[0]); if (res == null) { return(null); } res.IsPartOfAsset = true; } else if (descs.Count > 1) //need a compound shape in this case { var compound = new CompoundColliderShape(); foreach (var desc in descs) { var subShape = CreateShape(desc); if (subShape == null) { continue; } compound.AddChildShape(subShape); } res = compound; res.IsPartOfAsset = true; } return(res); }
/// <summary> /// Creates the character. /// </summary> /// <param name="collider">The collider.</param> /// <param name="stepHeight">Height of the step.</param> /// <returns></returns> public Character CreateCharacter(ColliderShape collider, float stepHeight) { var ch = new Character(collider) { InternalCollider = new BulletSharp.PairCachingGhostObject { CollisionShape = collider.InternalShape } }; ch.InternalCollider.UserObject = ch; ch.InternalCollider.CollisionFlags |= BulletSharp.CollisionFlags.CharacterObject; if (collider.NeedsCustomCollisionCallback) { ch.InternalCollider.CollisionFlags |= BulletSharp.CollisionFlags.CustomMaterialCallback; } ch.InternalCollider.ContactProcessingThreshold = !canCcd ? 1e18f : 1e30f; ch.KinematicCharacter = new BulletSharp.KinematicCharacterController((BulletSharp.PairCachingGhostObject)ch.InternalCollider, (BulletSharp.ConvexShape)collider.InternalShape, stepHeight); return(ch); }
internal void DeriveBonePhysicsTransformation(out Matrix derivedTransformation) { Quaternion rotation; Vector3 translation; //derive rotation and translation, scale is ignored for now Vector3 scale; BoneWorldMatrix.Decompose(out scale, out rotation, out translation); derivedTransformation = Matrix.RotationQuaternion(rotation) * Matrix.Translation(translation); //handle dynamic scaling if allowed (aka not using assets) if (CanScaleShape) { if (scale != ColliderShape.Scaling) { ColliderShape.Scaling = scale; ColliderShape.UpdateLocalTransformations(); if (DebugEntity != null) { DebugEntity.Transform.Scale = scale; } } } //Handle collider shape offset if (ColliderShape.LocalOffset != Vector3.Zero || ColliderShape.LocalRotation != Quaternion.Identity) { derivedTransformation = Matrix.Multiply(ColliderShape.PositiveCenterMatrix, derivedTransformation); } }
/// <summary> /// Creates the rigid body. /// </summary> /// <param name="collider">The collider.</param> /// <returns></returns> public RigidBody CreateRigidBody(ColliderShape collider) { var rb = new RigidBody(collider); rb.InternalRigidBody = new BulletSharp.RigidBody(0.0f, rb.MotionState, collider.InternalShape, Vector3.Zero) { UserObject = rb }; rb.InternalCollider = rb.InternalRigidBody; rb.InternalCollider.ContactProcessingThreshold = !canCcd ? 1e18f : 1e30f; if (collider.NeedsCustomCollisionCallback) { rb.InternalCollider.CollisionFlags |= BulletSharp.CollisionFlags.CustomMaterialCallback; } if (collider.Is2D) //set different defaults for 2D shapes { rb.InternalRigidBody.LinearFactor = new Vector3(1.0f, 1.0f, 0.0f); rb.InternalRigidBody.AngularFactor = new Vector3(0.0f, 0.0f, 1.0f); } return(rb); }
/// <summary> /// Pefrorms a sweep test using a collider shape and stops at the first hit /// </summary> /// <param name="shape">The shape.</param> /// <param name="from">From.</param> /// <param name="to">To.</param> /// <returns></returns> /// <exception cref="System.Exception">This kind of shape cannot be used for a ShapeSweep.</exception> public HitResult ShapeSweep(ColliderShape shape, Matrix from, Matrix to) { var sh = shape.InternalShape as BulletSharp.ConvexShape; if (sh == null) { throw new Exception("This kind of shape cannot be used for a ShapeSweep."); } var result = new HitResult(); //result.Succeded is false by default using (var rcb = new BulletSharp.ClosestConvexResultCallback(from.TranslationVector, to.TranslationVector)) { collisionWorld.ConvexSweepTest(sh, from, to, rcb); if (rcb.HitCollisionObject == null) { return(result); } result.Succeeded = true; result.Collider = (PhysicsComponent)rcb.HitCollisionObject.UserObject; result.Normal = rcb.HitNormalWorld; result.Point = rcb.HitPointWorld; } return(result); }
/// <summary> /// Pefrorms a sweep test using a collider shape and never stops until "to" /// </summary> /// <param name="shape">The shape.</param> /// <param name="from">From.</param> /// <param name="to">To.</param> /// <returns></returns> /// <exception cref="System.Exception">This kind of shape cannot be used for a ShapeSweep.</exception> public List <HitResult> ShapeSweepPenetrating(ColliderShape shape, Matrix from, Matrix to) { var sh = shape.InternalShape as BulletSharp.ConvexShape; if (sh == null) { throw new Exception("This kind of shape cannot be used for a ShapeSweep."); } var result = new List <HitResult>(); using (var rcb = new BulletSharp.AllHitsConvexResultCallback()) { collisionWorld.ConvexSweepTest(sh, from, to, rcb); var count = rcb.CollisionObjects.Count; for (var i = 0; i < count; i++) { var singleResult = new HitResult { Succeeded = true, Collider = (PhysicsComponent)rcb.CollisionObjects[i].UserObject, Normal = rcb.HitNormalWorld[i], Point = rcb.HitPointWorld[i] }; result.Add(singleResult); } } return(result); }
/// <summary> /// Removes a child shape. /// </summary> /// <param name="shape">The shape.</param> public void RemoveChildShape(ColliderShape shape) { colliderShapes.Remove(shape); InternalCompoundShape.RemoveChildShape(shape.InternalShape); shape.Parent = null; }
/// <summary> /// Adds a child shape. /// </summary> /// <param name="shape">The shape.</param> public void AddChildShape(ColliderShape shape) { colliderShapes.Add(shape); InternalCompoundShape.AddChildShape(shape.PositiveCenterMatrix, shape.InternalShape); shape.Parent = this; }
/// <summary> /// Adds a child shape. /// </summary> /// <param name="shape">The shape.</param> public void AddChildShape(ColliderShape shape) { colliderShapes.Add(shape); InternalCompoundShape.AddChildShape(shape.PositiveCenterMatrix, shape.InternalShape); shape.Parent = this; }
/// <summary> /// Removes a child shape. /// </summary> /// <param name="shape">The shape.</param> public void RemoveChildShape(ColliderShape shape) { colliderShapes.Remove(shape); InternalCompoundShape.RemoveChildShape(shape.InternalShape); shape.Parent = null; }
/// <summary> /// Initializes a new instance of the <see cref="Collider"/> class. /// </summary> /// <param name="collider">The collider.</param> public Collider(ColliderShape collider) { ProtectedColliderShape = collider; FirstCollisionChannel = new Channel<Collision> { Preference = ChannelPreference.PreferSender }; NewPairChannel = new Channel<Collision> { Preference = ChannelPreference.PreferSender }; PairEndedChannel = new Channel<Collision> { Preference = ChannelPreference.PreferSender }; AllPairsEndedChannel = new Channel<Collision> { Preference = ChannelPreference.PreferSender }; }
/// <summary> /// Adds a child shape. /// </summary> /// <param name="shape">The shape.</param> public void AddChildShape(ColliderShape shape) { colliderShapes.Add(shape); var compoundMatrix = Matrix.RotationQuaternion(shape.LocalRotation) * Matrix.Translation(shape.LocalOffset); InternalCompoundShape.AddChildShape(compoundMatrix, shape.InternalShape); shape.Parent = this; }
/// <summary> /// Adds a child shape. /// </summary> /// <param name="shape">The shape.</param> public void AddChildShape(ColliderShape shape) { colliderShapes.Add(shape); var compoundMatrix = Matrix.RotationQuaternion(shape.LocalRotation) * Matrix.Translation(shape.LocalOffset); InternalCompoundShape.AddChildShape(compoundMatrix, shape.InternalShape); shape.Parent = this; }
public void Dispose() { if (Shape == null) { return; } var compound = Shape.Parent; compound?.RemoveChildShape(Shape); Shape.Dispose(); Shape = null; }
/// <summary> /// Initializes a new instance of the <see cref="Collider"/> class. /// </summary> /// <param name="collider">The collider.</param> public Collider(ColliderShape collider) { ProtectedColliderShape = collider; FirstCollisionChannel = new Channel <Collision> { Preference = ChannelPreference.PreferSender }; NewPairChannel = new Channel <Collision> { Preference = ChannelPreference.PreferSender }; PairEndedChannel = new Channel <Collision> { Preference = ChannelPreference.PreferSender }; AllPairsEndedChannel = new Channel <Collision> { Preference = ChannelPreference.PreferSender }; }
/// <summary> /// Pefrorms a sweep test using a collider shape and never stops until "to" /// </summary> /// <param name="shape">The shape.</param> /// <param name="from">From.</param> /// <param name="to">To.</param> /// <param name="groupFilters">The PhysicsCompoenet CollisionGroup(s) that we intend to filter in.</param> /// <returns></returns> /// <exception cref="System.Exception">This kind of shape cannot be used for a ShapeSweep.</exception> public FastList <HitResult> ShapeSweepPenetrating(ColliderShape shape, Matrix from, Matrix to, IReadOnlyCollection <CollisionFilterGroups> groupFilters) { var sh = shape.InternalShape as BulletSharp.ConvexShape; if (sh == null) { throw new Exception("This kind of shape cannot be used for a ShapeSweep."); } var fullDistance = (to.TranslationVector - from.TranslationVector).LengthSquared(); using (var rcb = new BulletSharp.AllHitsConvexResultCallback()) { collisionWorld.ConvexSweepTest(sh, from, to, rcb); var count = rcb.CollisionObjects.Count; var result = new FastList <HitResult>(count); for (var i = 0; i < count; i++) { var component = (PhysicsComponent)rcb.CollisionObjects[i].UserObject; if (!groupFilters.Contains(component.CollisionGroup)) { continue; } var singleResult = new HitResult { Succeeded = true, Collider = (PhysicsComponent)rcb.CollisionObjects[i].UserObject, Normal = rcb.HitNormalWorld[i], Point = rcb.HitPointWorld[i], FullLength = fullDistance, StartPoint = from.TranslationVector, NormalizedDistance = -1.0f //lazily computed }; result.Add(singleResult); } return(result); } }
/// <summary> /// Creates the collider. /// </summary> /// <param name="shape">The shape.</param> /// <returns></returns> public Collider CreateCollider(ColliderShape shape) { var collider = new Collider(shape) { InternalCollider = new BulletSharp.CollisionObject { CollisionShape = shape.InternalShape, ContactProcessingThreshold = !canCcd ? 1e18f : 1e30f } }; collider.InternalCollider.UserObject = collider; collider.InternalCollider.CollisionFlags |= BulletSharp.CollisionFlags.NoContactResponse; if (shape.NeedsCustomCollisionCallback) { collider.InternalCollider.CollisionFlags |= BulletSharp.CollisionFlags.CustomMaterialCallback; } return(collider); }
/// <summary> /// Performs a sweep test using a collider shape and never stops until "to" /// </summary> /// <param name="shape">The shape.</param> /// <param name="from">From.</param> /// <param name="to">To.</param> /// <returns>The list with hit results.</returns> /// <exception cref="System.Exception">This kind of shape cannot be used for a ShapeSweep.</exception> public FastList<HitResult> ShapeSweepPenetrating(ColliderShape shape, Matrix from, Matrix to) { var results = new FastList<HitResult>(); ShapeSweepPenetrating(shape, from, to, results); return results; }
/// <summary> /// Performs a sweep test using a collider shape and never stops until "to" /// </summary> /// <param name="shape">The shape.</param> /// <param name="from">From.</param> /// <param name="to">To.</param> /// <param name="resultsOutput">The list to fill with results.</param> /// <param name="collisionFilterGroups">The collision group of this shape sweep</param> /// <param name="collisionFilterGroupFlags">The collision group that this shape sweep can collide with</param> /// <exception cref="System.Exception">This kind of shape cannot be used for a ShapeSweep.</exception> public void ShapeSweepPenetrating(ColliderShape shape, Matrix from, Matrix to, IList<HitResult> resultsOutput, CollisionFilterGroups collisionFilterGroups, CollisionFilterGroupFlags collisionFilterGroupFlags) { var sh = shape.InternalShape as BulletSharp.ConvexShape; if (sh == null) throw new Exception("This kind of shape cannot be used for a ShapeSweep."); using (var rcb = new XenkoAllHitsConvexResultCallback(resultsOutput) { CollisionFilterGroup = (BulletSharp.CollisionFilterGroups)collisionFilterGroups, CollisionFilterMask = (BulletSharp.CollisionFilterGroups)collisionFilterGroupFlags }) { collisionWorld.ConvexSweepTest(sh, from, to, rcb); } }
/// <summary> /// Initializes a new instance of the <see cref="Character"/> class. /// </summary> /// <param name="collider">The collider.</param> internal Character(ColliderShape collider) : base(collider) { }
private Entity CreateChildEntity(ColliderShape shape, PhysicsElementBase.Types type, bool addOffset = false) { if (shape == null) { return(null); } switch (shape.Type) { case ColliderShapeTypes.StaticPlane: { //Hmm TODO maybe can draw an infinite plane?? return(null); } case ColliderShapeTypes.Compound: { var entity = new Entity(); //We got to recurse var compound = (CompoundColliderShape)shape; for (var i = 0; i < compound.Count; i++) { var subShape = compound[i]; var subEntity = CreateChildEntity(subShape, type, true); subEntity.Transform.UseTRS = false; entity.AddChild(subEntity); } entity.Transform.LocalMatrix = Matrix.Identity; entity.Transform.UseTRS = false; return(entity); } default: { Material mat; switch (type) { case PhysicsElementBase.Types.PhantomCollider: mat = triggerMaterial; break; case PhysicsElementBase.Types.StaticCollider: case PhysicsElementBase.Types.StaticRigidBody: mat = staticMaterial; break; case PhysicsElementBase.Types.DynamicRigidBody: mat = dynamicMaterial; break; case PhysicsElementBase.Types.KinematicRigidBody: mat = kinematicMaterial; break; case PhysicsElementBase.Types.CharacterController: mat = characterMaterial; break; default: throw new ArgumentOutOfRangeException("type", type, null); } var entity = new Entity { new ModelComponent { Model = new Model { mat, new Mesh { Draw = shape.CreateDebugPrimitive(graphicsDevice) } } } }; var offset = addOffset ? Matrix.RotationQuaternion(shape.LocalRotation) * Matrix.Translation(shape.LocalOffset) : Matrix.Identity; if (shape.Type == ColliderShapeTypes.ConvexHull) { var hullDesc = (ConvexHullColliderShape)shape; entity.Transform.LocalMatrix = shape.DebugPrimitiveMatrix * Matrix.Scaling(hullDesc.Scaling) * offset; } else { entity.Transform.LocalMatrix = shape.DebugPrimitiveMatrix * offset; } entity.Transform.UseTRS = false; return(entity); } } }
internal static ColliderShape CreateShape(IColliderShapeDesc desc) { ColliderShape shape = null; var type = desc.GetType(); if (type == typeof(BoxColliderShapeDesc)) { var boxDesc = (BoxColliderShapeDesc)desc; shape = new BoxColliderShape(boxDesc.Is2D, boxDesc.Size) { LocalOffset = boxDesc.LocalOffset, LocalRotation = boxDesc.LocalRotation }; } else if (type == typeof(CapsuleColliderShapeDesc)) { var capsuleDesc = (CapsuleColliderShapeDesc)desc; shape = new CapsuleColliderShape(capsuleDesc.Is2D, capsuleDesc.Radius, capsuleDesc.Length, capsuleDesc.Orientation) { LocalOffset = capsuleDesc.LocalOffset, LocalRotation = capsuleDesc.LocalRotation }; } else if (type == typeof(CylinderColliderShapeDesc)) { var cylinderDesc = (CylinderColliderShapeDesc)desc; shape = new CylinderColliderShape(cylinderDesc.Height, cylinderDesc.Radius, cylinderDesc.Orientation) { LocalOffset = cylinderDesc.LocalOffset, LocalRotation = cylinderDesc.LocalRotation }; } else if (type == typeof(ConeColliderShapeDesc)) { var coneDesc = (ConeColliderShapeDesc)desc; shape = new ConeColliderShape(coneDesc.Height, coneDesc.Radius, coneDesc.Orientation) { LocalOffset = coneDesc.LocalOffset, LocalRotation = coneDesc.LocalRotation }; } else if (type == typeof(SphereColliderShapeDesc)) { var sphereDesc = (SphereColliderShapeDesc)desc; shape = new SphereColliderShape(sphereDesc.Is2D, sphereDesc.Radius) { LocalOffset = sphereDesc.LocalOffset }; } else if (type == typeof(StaticPlaneColliderShapeDesc)) { var planeDesc = (StaticPlaneColliderShapeDesc)desc; shape = new StaticPlaneColliderShape(planeDesc.Normal, planeDesc.Offset); } else if (type == typeof(ConvexHullColliderShapeDesc)) { var convexDesc = (ConvexHullColliderShapeDesc)desc; if (convexDesc.ConvexHulls == null) { return(null); } //Optimize performance and focus on less shapes creation since this shape could be nested if (convexDesc.ConvexHulls.Count == 1) { if (convexDesc.ConvexHulls[0].Count == 1 && convexDesc.ConvexHullsIndices[0][0].Count > 0) { shape = new ConvexHullColliderShape(convexDesc.ConvexHulls[0][0], convexDesc.ConvexHullsIndices[0][0], convexDesc.Scaling) { NeedsCustomCollisionCallback = true }; //shape.UpdateLocalTransformations(); shape.Description = desc; return(shape); } if (convexDesc.ConvexHulls[0].Count <= 1) { return(null); } var subCompound = new CompoundColliderShape { NeedsCustomCollisionCallback = true }; for (var i = 0; i < convexDesc.ConvexHulls[0].Count; i++) { var verts = convexDesc.ConvexHulls[0][i]; var indices = convexDesc.ConvexHullsIndices[0][i]; if (indices.Count == 0) { continue; } var subHull = new ConvexHullColliderShape(verts, indices, convexDesc.Scaling); //subHull.UpdateLocalTransformations(); subCompound.AddChildShape(subHull); } //subCompound.UpdateLocalTransformations(); subCompound.Description = desc; return(subCompound); } if (convexDesc.ConvexHulls.Count <= 1) { return(null); } var compound = new CompoundColliderShape { NeedsCustomCollisionCallback = true }; for (var i = 0; i < convexDesc.ConvexHulls.Count; i++) { var verts = convexDesc.ConvexHulls[i]; var indices = convexDesc.ConvexHullsIndices[i]; if (verts.Count == 1) { if (indices[0].Count == 0) { continue; } var subHull = new ConvexHullColliderShape(verts[0], indices[0], convexDesc.Scaling); //subHull.UpdateLocalTransformations(); compound.AddChildShape(subHull); } else if (verts.Count > 1) { var subCompound = new CompoundColliderShape(); for (var b = 0; b < verts.Count; b++) { var subVerts = verts[b]; var subIndex = indices[b]; if (subIndex.Count == 0) { continue; } var subHull = new ConvexHullColliderShape(subVerts, subIndex, convexDesc.Scaling); //subHull.UpdateLocalTransformations(); subCompound.AddChildShape(subHull); } //subCompound.UpdateLocalTransformations(); compound.AddChildShape(subCompound); } } //compound.UpdateLocalTransformations(); compound.Description = desc; return(compound); } else if (type == typeof(ColliderShapeAssetDesc)) { var assetDesc = (ColliderShapeAssetDesc)desc; if (assetDesc.Shape == null) { return(null); } if (assetDesc.Shape.Shape == null) { assetDesc.Shape.Shape = Compose(assetDesc.Shape.Descriptions); } shape = assetDesc.Shape.Shape; } if (shape == null) { return(shape); } //shape.UpdateLocalTransformations(); shape.Description = desc; return(shape); }
/// <summary> /// Performs a sweep test using a collider shape and never stops until "to" /// </summary> /// <param name="shape">The shape.</param> /// <param name="from">From.</param> /// <param name="to">To.</param> /// <param name="collisionFilterGroups">The collision group of this shape sweep</param> /// <param name="collisionFilterGroupFlags">The collision group that this shape sweep can collide with</param> /// <returns>The list with hit results.</returns> /// <exception cref="System.Exception">This kind of shape cannot be used for a ShapeSweep.</exception> public FastList<HitResult> ShapeSweepPenetrating(ColliderShape shape, Matrix from, Matrix to, CollisionFilterGroups collisionFilterGroups, CollisionFilterGroupFlags collisionFilterGroupFlags) { var results = new FastList<HitResult>(); ShapeSweepPenetrating(shape, from, to, results, collisionFilterGroups, collisionFilterGroupFlags); return results; }
internal RigidBody(ColliderShape collider) : base(collider) { LinkedConstraints = new List<Constraint>(); MotionState = new XenkoMotionState(this); }
private Entity CreateChildEntity(PhysicsComponent component, ColliderShape shape, bool addOffset = false) { if (shape == null) { return(null); } switch (shape.Type) { case ColliderShapeTypes.StaticPlane: { //Hmm TODO maybe can draw an infinite plane?? return(null); } case ColliderShapeTypes.Compound: { var entity = new Entity(); //We got to recurse var compound = (CompoundColliderShape)shape; for (var i = 0; i < compound.Count; i++) { var subShape = compound[i]; var subEntity = CreateChildEntity(component, subShape, true); subEntity.Transform.UseTRS = false; entity.AddChild(subEntity); } entity.Transform.LocalMatrix = Matrix.Identity; entity.Transform.UseTRS = false; return(entity); } default: { var mat = triggerMaterial; if (component is RigidbodyComponent) { mat = ((RigidbodyComponent)component).IsKinematic ? kinematicMaterial : dynamicMaterial; } else if (component is CharacterComponent) { mat = characterMaterial; } else if (component is StaticColliderComponent) { mat = staticMaterial; } var entity = new Entity { new ModelComponent { Model = new Model { mat, new Mesh { Draw = shape.CreateDebugPrimitive(graphicsDevice) } } } }; var offset = addOffset ? Matrix.RotationQuaternion(shape.LocalRotation) * Matrix.Translation(shape.LocalOffset) : Matrix.Identity; if (shape.Type == ColliderShapeTypes.ConvexHull) { var hullDesc = (ConvexHullColliderShape)shape; entity.Transform.LocalMatrix = shape.DebugPrimitiveMatrix * Matrix.Scaling(hullDesc.Scaling) * offset; } else { entity.Transform.LocalMatrix = shape.DebugPrimitiveMatrix * offset; } entity.Transform.UseTRS = false; return(entity); } } }
private Entity CreateChildEntity(ColliderShape shape, PhysicsElementBase.Types type, bool addOffset = false) { if (shape == null) return null; switch (shape.Type) { case ColliderShapeTypes.StaticPlane: { //Hmm TODO maybe can draw an infinite plane?? return null; } case ColliderShapeTypes.Compound: { var entity = new Entity(); //We got to recurse var compound = (CompoundColliderShape)shape; for (var i = 0; i < compound.Count; i++) { var subShape = compound[i]; var subEntity = CreateChildEntity(subShape, type, true); subEntity.Transform.UseTRS = false; entity.AddChild(subEntity); } entity.Transform.LocalMatrix = Matrix.Identity; entity.Transform.UseTRS = false; return entity; } default: { Material mat; switch (type) { case PhysicsElementBase.Types.PhantomCollider: mat = triggerMaterial; break; case PhysicsElementBase.Types.StaticCollider: case PhysicsElementBase.Types.StaticRigidBody: mat = staticMaterial; break; case PhysicsElementBase.Types.DynamicRigidBody: mat = dynamicMaterial; break; case PhysicsElementBase.Types.KinematicRigidBody: mat = kinematicMaterial; break; case PhysicsElementBase.Types.CharacterController: mat = characterMaterial; break; default: throw new ArgumentOutOfRangeException("type", type, null); } var entity = new Entity { new ModelComponent { Model = new Model { mat, new Mesh { Draw = shape.CreateDebugPrimitive(graphicsDevice) } } } }; var offset = addOffset ? Matrix.RotationQuaternion(shape.LocalRotation)*Matrix.Translation(shape.LocalOffset) : Matrix.Identity; if (shape.Type == ColliderShapeTypes.ConvexHull) { var hullDesc = (ConvexHullColliderShape)shape; entity.Transform.LocalMatrix = shape.DebugPrimitiveMatrix * Matrix.Scaling(hullDesc.Scaling) * offset; } else { entity.Transform.LocalMatrix = shape.DebugPrimitiveMatrix * offset; } entity.Transform.UseTRS = false; return entity; } } }
/// <summary> /// Pefrorms a sweep test using a collider shape and never stops until "to" /// </summary> /// <param name="shape">The shape.</param> /// <param name="from">From.</param> /// <param name="to">To.</param> /// <returns></returns> /// <exception cref="System.Exception">This kind of shape cannot be used for a ShapeSweep.</exception> public List<HitResult> ShapeSweepPenetrating(ColliderShape shape, Matrix from, Matrix to) { var sh = shape.InternalShape as BulletSharp.ConvexShape; if (sh == null) throw new Exception("This kind of shape cannot be used for a ShapeSweep."); var result = new List<HitResult>(); using (var rcb = new BulletSharp.AllHitsConvexResultCallback()) { collisionWorld.ConvexSweepTest(sh, from, to, rcb); var count = rcb.CollisionObjects.Count; for (var i = 0; i < count; i++) { var singleResult = new HitResult { Succeeded = true, Collider = (PhysicsComponent)rcb.CollisionObjects[i].UserObject, Normal = rcb.HitNormalWorld[i], Point = rcb.HitPointWorld[i] }; result.Add(singleResult); } } return result; }
/// <summary> /// Creates the character. /// </summary> /// <param name="collider">The collider.</param> /// <param name="stepHeight">Height of the step.</param> /// <returns></returns> public Character CreateCharacter(ColliderShape collider, float stepHeight) { var ch = new Character(collider) { InternalCollider = new BulletSharp.PairCachingGhostObject { CollisionShape = collider.InternalShape } }; ch.InternalCollider.UserObject = ch; ch.InternalCollider.CollisionFlags |= BulletSharp.CollisionFlags.CharacterObject; if (collider.NeedsCustomCollisionCallback) { ch.InternalCollider.CollisionFlags |= BulletSharp.CollisionFlags.CustomMaterialCallback; } ch.InternalCollider.ContactProcessingThreshold = !canCcd ? 1e18f : 1e30f; ch.KinematicCharacter = new BulletSharp.KinematicCharacterController((BulletSharp.PairCachingGhostObject)ch.InternalCollider, (BulletSharp.ConvexShape)collider.InternalShape, stepHeight); return ch; }
/// <summary> /// Creates the collider. /// </summary> /// <param name="shape">The shape.</param> /// <returns></returns> public Collider CreateCollider(ColliderShape shape) { var collider = new Collider(shape) { InternalCollider = new BulletSharp.CollisionObject { CollisionShape = shape.InternalShape, ContactProcessingThreshold = !canCcd ? 1e18f : 1e30f } }; collider.InternalCollider.UserObject = collider; collider.InternalCollider.CollisionFlags |= BulletSharp.CollisionFlags.NoContactResponse; if (shape.NeedsCustomCollisionCallback) { collider.InternalCollider.CollisionFlags |= BulletSharp.CollisionFlags.CustomMaterialCallback; } return collider; }
/// <summary> /// Creates the rigid body. /// </summary> /// <param name="collider">The collider.</param> /// <returns></returns> public RigidBody CreateRigidBody(ColliderShape collider) { var rb = new RigidBody(collider); rb.InternalRigidBody = new BulletSharp.RigidBody(0.0f, rb.MotionState, collider.InternalShape, Vector3.Zero) { UserObject = rb }; rb.InternalCollider = rb.InternalRigidBody; rb.InternalCollider.ContactProcessingThreshold = !canCcd ? 1e18f : 1e30f; if (collider.NeedsCustomCollisionCallback) { rb.InternalCollider.CollisionFlags |= BulletSharp.CollisionFlags.CustomMaterialCallback; } if (collider.Is2D) //set different defaults for 2D shapes { rb.InternalRigidBody.LinearFactor = new Vector3(1.0f, 1.0f, 0.0f); rb.InternalRigidBody.AngularFactor = new Vector3(0.0f, 0.0f, 1.0f); } return rb; }
private Entity CreateChildEntity(PhysicsComponent component, ColliderShape shape, bool addOffset = false) { if (shape == null) return null; switch (shape.Type) { case ColliderShapeTypes.StaticPlane: { //Hmm TODO maybe can draw an infinite plane?? return null; } case ColliderShapeTypes.Compound: { var entity = new Entity(); //We got to recurse var compound = (CompoundColliderShape)shape; for (var i = 0; i < compound.Count; i++) { var subShape = compound[i]; var subEntity = CreateChildEntity(component, subShape, true); subEntity.Transform.UseTRS = false; entity.AddChild(subEntity); } entity.Transform.LocalMatrix = Matrix.Identity; entity.Transform.UseTRS = false; return entity; } default: { var mat = triggerMaterial; if (component is RigidbodyComponent) { mat = ((RigidbodyComponent)component).IsKinematic ? kinematicMaterial : dynamicMaterial; } else if (component is CharacterComponent) { mat = characterMaterial; } else if (component is StaticColliderComponent) { mat = staticMaterial; } var entity = new Entity { new ModelComponent { Model = new Model { mat, new Mesh { Draw = shape.CreateDebugPrimitive(graphicsDevice) } } } }; var offset = addOffset ? Matrix.RotationQuaternion(shape.LocalRotation)*Matrix.Translation(shape.LocalOffset) : Matrix.Identity; if (shape.Type == ColliderShapeTypes.ConvexHull) { var hullDesc = (ConvexHullColliderShape)shape; entity.Transform.LocalMatrix = shape.DebugPrimitiveMatrix * Matrix.Scaling(hullDesc.Scaling) * offset; } else { entity.Transform.LocalMatrix = shape.DebugPrimitiveMatrix * offset; } entity.Transform.UseTRS = false; return entity; } } }
/// <summary> /// Pefrorms a sweep test using a collider shape and stops at the first hit /// </summary> /// <param name="shape">The shape.</param> /// <param name="from">From.</param> /// <param name="to">To.</param> /// <returns></returns> /// <exception cref="System.Exception">This kind of shape cannot be used for a ShapeSweep.</exception> public HitResult ShapeSweep(ColliderShape shape, Matrix from, Matrix to) { var sh = shape.InternalShape as BulletSharp.ConvexShape; if (sh == null) throw new Exception("This kind of shape cannot be used for a ShapeSweep."); var result = new HitResult(); //result.Succeded is false by default using (var rcb = new BulletSharp.ClosestConvexResultCallback(from.TranslationVector, to.TranslationVector)) { collisionWorld.ConvexSweepTest(sh, from, to, rcb); if (rcb.HitCollisionObject == null) return result; result.Succeeded = true; result.Collider = (PhysicsComponent)rcb.HitCollisionObject.UserObject; result.Normal = rcb.HitNormalWorld; result.Point = rcb.HitPointWorld; } return result; }
/// <summary> /// Initializes a new instance of the <see cref="Character"/> class. /// </summary> /// <param name="collider">The collider.</param> internal Character(ColliderShape collider) : base(collider) { }
public void Dispose() { if (Shape == null) return; var compound = Shape.Parent; compound?.RemoveChildShape(Shape); Shape.Dispose(); Shape = null; }
internal RigidBody(ColliderShape collider) : base(collider) { LinkedConstraints = new List <Constraint>(); MotionState = new XenkoMotionState(this); }