//This is called by the physics engine to update the transformation of Dynamic rigidbodies. private static void RigidBodySetWorldTransform(PhysicsElementBase element, ref Matrix physicsTransform) { element.Data.PhysicsComponent.Simulation.SimulationProfiler.Mark(); element.Data.PhysicsComponent.Simulation.UpdatedRigidbodies++; if (element.BoneIndex == -1) { element.UpdateTransformationComponent(ref physicsTransform); } else { element.UpdateBoneTransformation(ref physicsTransform); } if (element.DebugEntity == null) { return; } Vector3 scale, pos; Quaternion rot; physicsTransform.Decompose(out scale, out rot, out pos); element.DebugEntity.Transform.Position = pos; element.DebugEntity.Transform.Rotation = rot; }
public Entity CreateDebugEntity(PhysicsElementBase physicsElement) { if (physicsElement?.ColliderShape == null) { return(null); } if (physicsElement.DebugEntity != null) { return(null); } var debugEntity = new Entity(); var colliderEntity = CreateChildEntity(physicsElement.ColliderShape, physicsElement.Type, true); if (colliderEntity == null) { return(null); } debugEntity.AddChild(colliderEntity); if (physicsElement.CanScaleShape) { debugEntity.Transform.Scale = physicsElement.ColliderShape.Scaling; } var skinnedElement = physicsElement as PhysicsSkinnedElementBase; if (skinnedElement != null && skinnedElement.BoneIndex != -1) { Vector3 scale, pos; Quaternion rot; skinnedElement.BoneWorldMatrixOut.Decompose(out scale, out rot, out pos); debugEntity.Transform.Position = pos; debugEntity.Transform.Rotation = rot; } else { Vector3 scale, pos; Quaternion rot; physicsElement.Data.TransformComponent.WorldMatrix.Decompose(out scale, out rot, out pos); debugEntity.Transform.Position = pos; debugEntity.Transform.Rotation = rot; } return(debugEntity); }
public Entity CreateDebugEntity(PhysicsElementBase physicsElement) { if (physicsElement?.ColliderShape == null) return null; if (physicsElement.DebugEntity != null) return null; var debugEntity = new Entity(); var colliderEntity = CreateChildEntity(physicsElement.ColliderShape, physicsElement.Type, true); if (colliderEntity == null) return null; debugEntity.AddChild(colliderEntity); if (physicsElement.CanScaleShape) { debugEntity.Transform.Scale = physicsElement.ColliderShape.Scaling; } var skinnedElement = physicsElement as PhysicsSkinnedElementBase; if (skinnedElement != null && skinnedElement.BoneIndex != -1) { Vector3 scale, pos; Quaternion rot; skinnedElement.BoneWorldMatrixOut.Decompose(out scale, out rot, out pos); debugEntity.Transform.Position = pos; debugEntity.Transform.Rotation = rot; } else { Vector3 scale, pos; Quaternion rot; physicsElement.Data.TransformComponent.WorldMatrix.Decompose(out scale, out rot, out pos); debugEntity.Transform.Position = pos; debugEntity.Transform.Rotation = rot; } return debugEntity; }
private void DeleteElement(PhysicsElementBase element) { element.Data = null; //might be possible that this element was not valid during creation so it would be already null if (element.InternalCollider == null) { return; } var toDispose = new List <IDisposable>(); elements.Remove(element); if (element.BoneIndex != -1) { boneElements.Remove((PhysicsSkinnedElementBase)element); } switch (element.Type) { case PhysicsElementBase.Types.PhantomCollider: case PhysicsElementBase.Types.StaticCollider: { simulation.RemoveCollider(element.Collider); } break; case PhysicsElementBase.Types.StaticRigidBody: case PhysicsElementBase.Types.DynamicRigidBody: case PhysicsElementBase.Types.KinematicRigidBody: { var rb = (RigidBody)element.Collider; var constraints = rb.LinkedConstraints.ToArray(); foreach (var c in constraints) { simulation.RemoveConstraint(c); toDispose.Add(c); } simulation.RemoveRigidBody(rb); } break; case PhysicsElementBase.Types.CharacterController: { characters.Remove(element); simulation.RemoveCharacter((Character)element.Collider); } break; } toDispose.Add(element.Collider); if (element.ColliderShape != null && !element.ColliderShape.IsPartOfAsset) { toDispose.Add(element.ColliderShape); } 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(PhysicsElementBase element, AssociatedData data, Entity entity) { element.Data = data; if (element.ColliderShapes.Count == 0) { return; //no shape no purpose } if (element.ColliderShape == null) { element.ComposeShape(); } var shape = element.ColliderShape; if (shape == null) { return; //no shape no purpose } element.BoneIndex = -1; var skinnedElement = element as PhysicsSkinnedElementBase; if (skinnedElement != null && !skinnedElement.NodeName.IsNullOrEmpty() && data.ModelComponent?.Skeleton != null) { if (!data.BoneMatricesUpdated) { Vector3 position, scaling; Quaternion rotation; entity.Transform.WorldMatrix.Decompose(out scaling, out rotation, out position); var isScalingNegative = scaling.X * scaling.Y * scaling.Z < 0.0f; data.ModelComponent.Skeleton.NodeTransformations[0].LocalMatrix = entity.Transform.WorldMatrix; data.ModelComponent.Skeleton.NodeTransformations[0].IsScalingNegative = isScalingNegative; data.ModelComponent.Skeleton.UpdateMatrices(); data.BoneMatricesUpdated = true; } skinnedElement.BoneIndex = data.ModelComponent.Skeleton.Nodes.IndexOf(x => x.Name == skinnedElement.NodeName); if (element.BoneIndex == -1) { throw new Exception("The specified NodeName doesn't exist in the model hierarchy."); } element.BoneWorldMatrixOut = element.BoneWorldMatrix = data.ModelComponent.Skeleton.NodeTransformations[element.BoneIndex].WorldMatrix; } var defaultGroups = element.CanCollideWith == 0 || element.CollisionGroup == 0; switch (element.Type) { case PhysicsElementBase.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, CollisionFilterGroupFlags.DefaultFilter, CollisionFilterGroupFlags.AllFilter); } else { simulation.AddCollider(c, (CollisionFilterGroupFlags)element.CollisionGroup, element.CanCollideWith); } } break; case PhysicsElementBase.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 if (defaultGroups) { simulation.AddCollider(c, CollisionFilterGroupFlags.DefaultFilter, CollisionFilterGroupFlags.AllFilter); } else { simulation.AddCollider(c, (CollisionFilterGroupFlags)element.CollisionGroup, element.CanCollideWith); } } break; case PhysicsElementBase.Types.StaticRigidBody: { var rb = simulation.CreateRigidBody(shape); rb.Entity = entity; rb.GetWorldTransformCallback = (out Matrix transform) => RigidBodyGetWorldTransform(element, out transform); rb.SetWorldTransformCallback = transform => RigidBodySetWorldTransform(element, ref transform); element.Collider = rb; element.UpdatePhysicsTransformation(); //this will set position and rotation of the collider rb.Type = RigidBodyTypes.Static; rb.Mass = 0.0f; if (defaultGroups) { simulation.AddRigidBody(rb, CollisionFilterGroupFlags.DefaultFilter, CollisionFilterGroupFlags.AllFilter); } else { simulation.AddRigidBody(rb, (CollisionFilterGroupFlags)element.CollisionGroup, element.CanCollideWith); } } break; case PhysicsElementBase.Types.DynamicRigidBody: { var rb = simulation.CreateRigidBody(shape); rb.Entity = entity; rb.GetWorldTransformCallback = (out Matrix transform) => RigidBodyGetWorldTransform(element, out transform); rb.SetWorldTransformCallback = transform => RigidBodySetWorldTransform(element, ref transform); element.Collider = rb; element.UpdatePhysicsTransformation(); //this will set position and rotation of the collider rb.Type = RigidBodyTypes.Dynamic; if (rb.Mass == 0.0f) { rb.Mass = 1.0f; } if (defaultGroups) { simulation.AddRigidBody(rb, CollisionFilterGroupFlags.DefaultFilter, CollisionFilterGroupFlags.AllFilter); } else { simulation.AddRigidBody(rb, (CollisionFilterGroupFlags)element.CollisionGroup, element.CanCollideWith); } } break; case PhysicsElementBase.Types.KinematicRigidBody: { var rb = simulation.CreateRigidBody(shape); rb.Entity = entity; rb.GetWorldTransformCallback = (out Matrix transform) => RigidBodyGetWorldTransform(element, out transform); rb.SetWorldTransformCallback = transform => RigidBodySetWorldTransform(element, ref transform); element.Collider = rb; element.UpdatePhysicsTransformation(); //this will set position and rotation of the collider rb.Type = RigidBodyTypes.Kinematic; if (rb.Mass == 0.0f) { rb.Mass = 1.0f; } if (defaultGroups) { simulation.AddRigidBody(rb, CollisionFilterGroupFlags.DefaultFilter, CollisionFilterGroupFlags.AllFilter); } else { simulation.AddRigidBody(rb, (CollisionFilterGroupFlags)element.CollisionGroup, element.CanCollideWith); } } break; case PhysicsElementBase.Types.CharacterController: { var charElem = (CharacterElement)element; var ch = simulation.CreateCharacter(shape, charElem.StepHeight); element.Collider = ch; element.Collider.Entity = entity; element.UpdatePhysicsTransformation(); //this will set position and rotation of the collider if (defaultGroups) { simulation.AddCharacter(ch, CollisionFilterGroupFlags.DefaultFilter, CollisionFilterGroupFlags.AllFilter); } else { simulation.AddCharacter(ch, (CollisionFilterGroupFlags)element.CollisionGroup, element.CanCollideWith); } characters.Add(element); } break; } if (colliderShapesRendering) { element.AddDebugEntity(sceneSystem.SceneInstance.Scene); } elements.Add(element); if (element.BoneIndex != -1) { boneElements.Add(skinnedElement); } }
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; } } }