//This is valid for Dynamic rigidbodies (called once at initialization) //and Kinematic rigidbodies, called every simulation tick (if body not sleeping) to let the physics engine know where the kinematic body is. private static void RigidBodyGetWorldTransform(PhysicsElement element, out Matrix physicsTransform) { if (element.BoneIndex == -1) { element.DerivePhysicsTransformation(out physicsTransform); } else { element.DeriveBonePhysicsTransformation(out physicsTransform); } }
//This is called by the physics engine to update the transformation of Dynamic rigidbodies. private static void RigidBodySetWorldTransform(PhysicsElement element, Matrix physicsTransform) { if (element.BoneIndex == -1) { element.UpdateTransformationComponent(physicsTransform); } else { element.UpdateBoneTransformation(physicsTransform); } }
void NewElement(PhysicsElement element, AssociatedData data, Entity entity) { if (element.Shape == null) { return; //no shape no purpose } var shape = element.Shape.Shape; element.Data = data; element.BoneIndex = -1; if (!element.Sprite && element.LinkedBoneName != null && data.ModelComponent != null) { //find the linked bone, if can't be found we just skip this element for (var index = 0; index < data.ModelComponent.ModelViewHierarchy.Nodes.Length; index++) { var node = data.ModelComponent.ModelViewHierarchy.Nodes[index]; if (node.Name != element.LinkedBoneName) { continue; } element.BoneIndex = index; break; } if (element.BoneIndex == -1) { throw new Exception("The specified LinkedBoneName doesn't exist in the model hierarchy."); } } //complex hierarchy models not implemented yet if (element.BoneIndex != -1) { throw new NotImplementedException("Physics on complex hierarchy model's bones is not implemented yet."); } var defaultGroups = element.CanCollideWith == 0 || element.CollisionGroup == 0; switch (element.Type) { case PhysicsElement.Types.PhantomCollider: { var c = physicsSystem.PhysicsEngine.CreateCollider(shape); element.Collider = c; //required by the next call element.Collider.EntityObject = entity; //required by the next call element.UpdatePhysicsTransformation(); //this will set position and rotation of the collider c.IsTrigger = true; if (defaultGroups) { physicsSystem.PhysicsEngine.AddCollider(c); } else { physicsSystem.PhysicsEngine.AddCollider(c, (CollisionFilterGroups)element.CollisionGroup, element.CanCollideWith); } } break; case PhysicsElement.Types.StaticCollider: { var c = physicsSystem.PhysicsEngine.CreateCollider(shape); element.Collider = c; //required by the next call element.Collider.EntityObject = entity; //required by the next call element.UpdatePhysicsTransformation(); //this will set position and rotation of the collider c.IsTrigger = false; if (defaultGroups) { physicsSystem.PhysicsEngine.AddCollider(c); } else { physicsSystem.PhysicsEngine.AddCollider(c, (CollisionFilterGroups)element.CollisionGroup, element.CanCollideWith); } } break; case PhysicsElement.Types.StaticRigidBody: { var rb = physicsSystem.PhysicsEngine.CreateRigidBody(shape); rb.EntityObject = entity; rb.GetWorldTransformCallback = (out Matrix transform) => RigidBodyGetWorldTransform(element, out transform); rb.SetWorldTransformCallback = transform => RigidBodySetWorldTransform(element, transform); element.Collider = rb; element.UpdatePhysicsTransformation(); //this will set position and rotation of the collider rb.Type = RigidBodyTypes.Static; if (defaultGroups) { physicsSystem.PhysicsEngine.AddRigidBody(rb); } else { physicsSystem.PhysicsEngine.AddRigidBody(rb, (CollisionFilterGroups)element.CollisionGroup, element.CanCollideWith); } } break; case PhysicsElement.Types.DynamicRigidBody: { var rb = physicsSystem.PhysicsEngine.CreateRigidBody(shape); rb.EntityObject = entity; rb.GetWorldTransformCallback = (out Matrix transform) => RigidBodyGetWorldTransform(element, out transform); rb.SetWorldTransformCallback = transform => RigidBodySetWorldTransform(element, transform); element.Collider = rb; element.UpdatePhysicsTransformation(); //this will set position and rotation of the collider rb.Type = RigidBodyTypes.Dynamic; rb.Mass = 1.0f; if (defaultGroups) { physicsSystem.PhysicsEngine.AddRigidBody(rb); } else { physicsSystem.PhysicsEngine.AddRigidBody(rb, (CollisionFilterGroups)element.CollisionGroup, element.CanCollideWith); } } break; case PhysicsElement.Types.KinematicRigidBody: { var rb = physicsSystem.PhysicsEngine.CreateRigidBody(shape); rb.EntityObject = entity; rb.GetWorldTransformCallback = (out Matrix transform) => RigidBodyGetWorldTransform(element, out transform); rb.SetWorldTransformCallback = transform => RigidBodySetWorldTransform(element, transform); element.Collider = rb; element.UpdatePhysicsTransformation(); //this will set position and rotation of the collider rb.Type = RigidBodyTypes.Kinematic; rb.Mass = 0.0f; if (defaultGroups) { physicsSystem.PhysicsEngine.AddRigidBody(rb); } else { physicsSystem.PhysicsEngine.AddRigidBody(rb, (CollisionFilterGroups)element.CollisionGroup, element.CanCollideWith); } } break; case PhysicsElement.Types.CharacterController: { var ch = physicsSystem.PhysicsEngine.CreateCharacter(shape, element.StepHeight); element.Collider = ch; element.Collider.EntityObject = entity; element.UpdatePhysicsTransformation(); //this will set position and rotation of the collider if (defaultGroups) { physicsSystem.PhysicsEngine.AddCharacter(ch); } else { physicsSystem.PhysicsEngine.AddCharacter(ch, (CollisionFilterGroups)element.CollisionGroup, element.CanCollideWith); } characters.Add(element); } break; } elements.Add(element); }
//This is valid for Dynamic rigidbodies (called once at initialization) //and Kinematic rigidbodies (called every simulation tick (if body not sleeping) to let the physics engine know where the kinematic body is) static void RigidBodyGetWorldTransform(PhysicsElement element, out Matrix physicsTransform) { physicsTransform = element.DerivePhysicsTransformation(); }
//This is called by the physics engine to update the transformation of Dynamic rigidbodies static void RigidBodySetWorldTransform(PhysicsElement element, Matrix physicsTransform) { element.UpdateTransformationComponent(physicsTransform); }
private void DrawDebugCompound(ref Matrix viewProj, CompoundColliderShape compound, PhysicsElement element) { for (var i = 0; i < compound.Count; i++) { var subShape = compound[i]; switch (subShape.Type) { case ColliderShapeTypes.StaticPlane: continue; case ColliderShapeTypes.Compound: DrawDebugCompound(ref viewProj, (CompoundColliderShape)compound[i], element); break; default: { var physTrans = element.BoneIndex == -1 ? element.Collider.PhysicsWorldTransform : element.BoneWorldMatrix; physTrans = Matrix.Multiply(subShape.PositiveCenterMatrix, physTrans); //must account collider shape scaling Matrix worldTrans; Matrix.Multiply(ref subShape.DebugPrimitiveScaling, ref physTrans, out worldTrans); physicsSystem.PhysicsEngine.DebugEffect.WorldViewProj = worldTrans * viewProj; physicsSystem.PhysicsEngine.DebugEffect.Color = element.Collider.IsActive ? Color.Green : Color.Red; physicsSystem.PhysicsEngine.DebugEffect.UseUv = subShape.Type != ColliderShapeTypes.ConvexHull; physicsSystem.PhysicsEngine.DebugEffect.Apply(); subShape.DebugPrimitive.Draw(); } break; } } }
void DeleteElement(PhysicsElement element, bool now = false) { //might be possible that this element was not valid during creation so it would be already null if (element.Collider == null) { return; } var toDispose = new List <IDisposable>(); elements.Remove(element); switch (element.Type) { case PhysicsElement.Types.PhantomCollider: case PhysicsElement.Types.StaticCollider: { physicsSystem.PhysicsEngine.RemoveCollider(element.Collider); } break; case PhysicsElement.Types.StaticRigidBody: case PhysicsElement.Types.DynamicRigidBody: case PhysicsElement.Types.KinematicRigidBody: { var rb = (RigidBody)element.Collider; var constraints = rb.LinkedConstraints.ToArray(); foreach (var c in constraints) { physicsSystem.PhysicsEngine.RemoveConstraint(c); toDispose.Add(c); } physicsSystem.PhysicsEngine.RemoveRigidBody(rb); } break; case PhysicsElement.Types.CharacterController: { characters.Remove(element); physicsSystem.PhysicsEngine.RemoveCharacter((Character)element.Collider); } break; } toDispose.Add(element.Collider); element.Collider = null; //dispose in another thread for better performance if (!now) { TaskList.Dispatch(toDispose, 4, 128, (i, disposable) => disposable.Dispose()); } else { foreach (var d in toDispose) { d.Dispose(); } } }
private void NewElement(PhysicsElement element, AssociatedData data, Entity entity) { if (element.Shape == null || element.Shape.Descriptions == null || element.Shape.Shape == null) { return; //no shape no purpose } var shape = element.Shape.Shape; element.Data = data; element.BoneIndex = -1; if (!element.LinkedBoneName.IsNullOrEmpty()) { element.BoneIndex = data.ModelComponent.ModelViewHierarchy.Nodes.IndexOf(x => x.Name == element.LinkedBoneName); if (element.BoneIndex == -1) { throw new Exception("The specified LinkedBoneName doesn't exist in the model hierarchy."); } element.BoneWorldMatrixOut = element.BoneWorldMatrix = data.ModelComponent.ModelViewHierarchy.NodeTransformations[element.BoneIndex].WorldMatrix; } var defaultGroups = element.CanCollideWith == 0 || element.CollisionGroup == 0; switch (element.Type) { case PhysicsElement.Types.PhantomCollider: { var c = Simulation.CreateCollider(shape); element.Collider = c; //required by the next call element.Collider.Entity = entity; //required by the next call element.UpdatePhysicsTransformation(); //this will set position and rotation of the collider c.IsTrigger = true; if (defaultGroups) { simulation.AddCollider(c); } else { simulation.AddCollider(c, (CollisionFilterGroupFlags)element.CollisionGroup, element.CanCollideWith); } } break; case PhysicsElement.Types.StaticCollider: { var c = Simulation.CreateCollider(shape); element.Collider = c; //required by the next call element.Collider.Entity = entity; //required by the next call element.UpdatePhysicsTransformation(); //this will set position and rotation of the collider c.IsTrigger = false; if (defaultGroups) { simulation.AddCollider(c); } else { simulation.AddCollider(c, (CollisionFilterGroupFlags)element.CollisionGroup, element.CanCollideWith); } } break; case PhysicsElement.Types.StaticRigidBody: { var rb = Simulation.CreateRigidBody(shape); rb.Entity = entity; rb.GetWorldTransformCallback = (out Matrix transform) => RigidBodyGetWorldTransform(element, out transform); rb.SetWorldTransformCallback = transform => RigidBodySetWorldTransform(element, transform); element.Collider = rb; element.UpdatePhysicsTransformation(); //this will set position and rotation of the collider rb.Type = RigidBodyTypes.Static; if (defaultGroups) { simulation.AddRigidBody(rb); } else { simulation.AddRigidBody(rb, (CollisionFilterGroupFlags)element.CollisionGroup, element.CanCollideWith); } } break; case PhysicsElement.Types.DynamicRigidBody: { var rb = Simulation.CreateRigidBody(shape); rb.Entity = entity; rb.GetWorldTransformCallback = (out Matrix transform) => RigidBodyGetWorldTransform(element, out transform); rb.SetWorldTransformCallback = transform => RigidBodySetWorldTransform(element, transform); element.Collider = rb; element.UpdatePhysicsTransformation(); //this will set position and rotation of the collider rb.Type = RigidBodyTypes.Dynamic; rb.Mass = 1.0f; if (defaultGroups) { simulation.AddRigidBody(rb); } else { simulation.AddRigidBody(rb, (CollisionFilterGroupFlags)element.CollisionGroup, element.CanCollideWith); } } break; case PhysicsElement.Types.KinematicRigidBody: { var rb = Simulation.CreateRigidBody(shape); rb.Entity = entity; rb.GetWorldTransformCallback = (out Matrix transform) => RigidBodyGetWorldTransform(element, out transform); rb.SetWorldTransformCallback = transform => RigidBodySetWorldTransform(element, transform); element.Collider = rb; element.UpdatePhysicsTransformation(); //this will set position and rotation of the collider rb.Type = RigidBodyTypes.Kinematic; rb.Mass = 0.0f; if (defaultGroups) { simulation.AddRigidBody(rb); } else { simulation.AddRigidBody(rb, (CollisionFilterGroupFlags)element.CollisionGroup, element.CanCollideWith); } } break; case PhysicsElement.Types.CharacterController: { var ch = Simulation.CreateCharacter(shape, element.StepHeight); element.Collider = ch; element.Collider.Entity = entity; element.UpdatePhysicsTransformation(); //this will set position and rotation of the collider if (defaultGroups) { simulation.AddCharacter(ch); } else { simulation.AddCharacter(ch, (CollisionFilterGroupFlags)element.CollisionGroup, element.CanCollideWith); } characters.Add(element); } break; } elements.Add(element); if (element.BoneIndex != -1) { boneElements.Add(element); } }