Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
PhysicsElement.cs
Go to the documentation of this file.
1 using SiliconStudio.Core;
2 using SiliconStudio.Core.Mathematics;
3 using SiliconStudio.Core.Serialization.Converters;
4 using SiliconStudio.Paradox.Engine;
5 using SiliconStudio.Paradox.EntityModel;
6 
7 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
8 // This file is distributed under GPL v3. See LICENSE.md for details.
9 using System;
10 
11 namespace SiliconStudio.Paradox.Physics
12 {
13  [DataContract]
14  [DataConverter(AutoGenerate = true)]
15  public class PhysicsElement
16  {
17  public enum Types
18  {
19  PhantomCollider,
20  StaticCollider,
21  StaticRigidBody,
22  DynamicRigidBody,
23  KinematicRigidBody,
24  CharacterController
25  };
26 
27  /// <userdoc>
28  /// The physics type of this element.
29  /// </userdoc>
30  [DataMemberConvert]
31  public Types Type { get; set; }
32 
33  /// <summary>
34  /// Gets or sets the link (usually a bone).
35  /// </summary>
36  /// <value>
37  /// The mesh's linked bone name
38  /// </value>
39  /// <userdoc>
40  /// In the case of skinned mesh this must be the bone node name linked with this element.
41  /// </userdoc>
42  [DataMemberConvert]
43  public string LinkedBoneName { get; set; }
44 
45  /// <userdoc>
46  /// the Collider Shape of this element.
47  /// </userdoc>
48  [DataMemberConvert]
49  public PhysicsColliderShape Shape { get; set; }
50 
51  //todo: is there a better way to solve this?
52  public enum CollisionFilterGroups1 //needed for the editor as this is not tagged as flag...
53  {
54  DefaultFilter = 0x1,
55 
56  StaticFilter = 0x2,
57 
58  KinematicFilter = 0x4,
59 
60  DebrisFilter = 0x8,
61 
62  SensorTrigger = 0x10,
63 
64  CharacterFilter = 0x20,
65 
66  CustomFilter1 = 0x40,
67 
68  CustomFilter2 = 0x80,
69 
70  CustomFilter3 = 0x100,
71 
72  CustomFilter4 = 0x200,
73 
74  CustomFilter5 = 0x400,
75 
76  CustomFilter6 = 0x800,
77 
78  CustomFilter7 = 0x1000,
79 
80  CustomFilter8 = 0x2000,
81 
82  CustomFilter9 = 0x4000,
83 
84  CustomFilter10 = 0x8000,
85 
86  AllFilter = 0xFFFF
87  }
88 
89  /// <summary>
90  /// Gets or sets the collision group.
91  /// </summary>
92  /// <value>
93  /// The collision group.
94  /// </value>
95  /// <userdoc>
96  /// The collision group of this element, default is AllFilter.
97  /// </userdoc>
98  [DataMemberConvert]
99  public CollisionFilterGroups1 CollisionGroup { get; set; }
100 
101  /// <summary>
102  /// Gets or sets the can collide with.
103  /// </summary>
104  /// <value>
105  /// The can collide with.
106  /// </value>
107  /// <userdoc>
108  /// Which collider groups this element can collide with, when nothing is selected AllFilter is intended to be default.
109  /// </userdoc>
110  [DataMemberConvert]
111  public CollisionFilterGroups CanCollideWith { get; set; }
112 
113  /// <summary>
114  /// Gets or sets the height of the character step.
115  /// </summary>
116  /// <value>
117  /// The height of the character step.
118  /// </value>
119  /// <userdoc>
120  /// Only valid for CharacterController type, describes the max slope height a character can climb.
121  /// </userdoc>
122  [DataMemberConvert]
123  public float StepHeight { get; set; }
124 
125  /// <summary>
126  /// Gets or sets a value indicating whether this <see cref="PhysicsElement"/> is representing a sprite.
127  /// </summary>
128  /// <value>
129  /// <c>true</c> if sprite; otherwise, <c>false</c>.
130  /// </value>
131  /// <userdoc>
132  /// If this element is associated with a Sprite Component's sprite. This is necessary because Sprites use an inverted Y axis and the physics engine must be aware of that.
133  /// </userdoc>
134  [DataMemberConvert]
135  public bool Sprite { get; set; }
136 
137  #region Ignore or Private/Internal
138 
139  private Collider mCollider;
140 
141  [DataMemberIgnore]
142  public Collider Collider
143  {
144  get
145  {
146  if (mCollider == null)
147  {
148  throw new Exception("Collider is null, please make sure that you are trying to access this object after it is added to the game entities ( Entities.Add(entity) ).");
149  }
150 
151  return mCollider;
152  }
153  internal set { mCollider = value; }
154  }
155 
156  [DataMemberIgnore]
157  public RigidBody RigidBody
158  {
159  get { return (RigidBody)Collider; }
160  }
161 
162  [DataMemberIgnore]
163  public Character Character
164  {
165  get { return (Character)Collider; }
166  }
167 
168  internal Matrix BoneWorldMatrix;
169 
170  internal int BoneIndex;
171 
172  internal PhysicsProcessor.AssociatedData Data;
173 
174  #endregion Ignore or Private/Internal
175 
176  #region Utility
177 
178  /// <summary>
179  /// Computes the physics transformation from the TransformationComponent values
180  /// </summary>
181  /// <returns></returns>
182  internal Matrix DerivePhysicsTransformation()
183  {
184  var entity = (Entity)Collider.EntityObject;
185 
186  Quaternion rotation;
187  Vector3 translation;
188 
189  if (!entity.Transformation.UseTRS)
190  {
191  //derive rotation and translation, scale is ignored for now
192  Vector3 scale;
193  entity.Transformation.WorldMatrix.Decompose(out scale, out rotation, out translation);
194  }
195  else
196  {
197  rotation = entity.Transformation.Rotation;
198  translation = entity.Transformation.Translation;
199  }
200 
201  //Invert up axis in the case of a Sprite
202  if (Sprite)
203  {
204  translation.Y = -translation.Y;
205  }
206 
207  var physicsTransform = Matrix.RotationQuaternion(rotation) * Matrix.Translation(translation);
208 
209  //Handle collider shape offset
210  if (Shape.Shape.LocalOffset != Vector3.Zero || Shape.Shape.LocalRotation != Quaternion.Identity)
211  {
212  physicsTransform = Matrix.Multiply(Shape.Shape.PositiveCenterMatrix, physicsTransform);
213  }
214 
215  return physicsTransform;
216  }
217 
218  /// <summary>
219  /// Updades the graphics transformation from the given physics transformation
220  /// </summary>
221  /// <param name="physicsTransform"></param>
222  internal void UpdateTransformationComponent(Matrix physicsTransform)
223  {
224  var entity = (Entity)Collider.EntityObject;
225 
226  if (Shape.Shape.LocalOffset != Vector3.Zero || Shape.Shape.LocalRotation != Quaternion.Identity)
227  {
228  physicsTransform = Matrix.Multiply(Shape.Shape.NegativeCenterMatrix, physicsTransform);
229  }
230 
231  var rotation = Quaternion.RotationMatrix(physicsTransform);
232  var translation = physicsTransform.TranslationVector;
233 
234  //Invert up axis in the case of a Sprite
235  if (Sprite)
236  {
237  translation.Y = -translation.Y;
238  }
239 
240  if (entity.Transformation.UseTRS)
241  {
242  entity.Transformation.Translation = translation;
243  entity.Transformation.Rotation = rotation;
244  }
245  else
246  {
247  var worldMatrix = entity.Transformation.WorldMatrix;
248 
249  Vector3 scale;
250  scale.X = (float)Math.Sqrt((worldMatrix.M11 * worldMatrix.M11) + (worldMatrix.M12 * worldMatrix.M12) + (worldMatrix.M13 * worldMatrix.M13));
251  scale.Y = (float)Math.Sqrt((worldMatrix.M21 * worldMatrix.M21) + (worldMatrix.M22 * worldMatrix.M22) + (worldMatrix.M23 * worldMatrix.M23));
252  scale.Z = (float)Math.Sqrt((worldMatrix.M31 * worldMatrix.M31) + (worldMatrix.M32 * worldMatrix.M32) + (worldMatrix.M33 * worldMatrix.M33));
253 
254  TransformationComponent.CreateMatrixTRS(ref translation, ref rotation, ref scale, out entity.Transformation.WorldMatrix);
255  if (entity.Transformation.Parent == null)
256  {
257  entity.Transformation.LocalMatrix = entity.Transformation.WorldMatrix;
258  }
259  else
260  {
261  //We are not root so we need to derive the local matrix as well
262  var inverseParent = entity.Transformation.Parent.WorldMatrix;
263  inverseParent.Invert();
264  entity.Transformation.LocalMatrix = Matrix.Multiply(entity.Transformation.WorldMatrix, inverseParent);
265  }
266  }
267  }
268 
269  /// <summary>
270  /// Forces an update from the TransformationComponent to the Collider.PhysicsWorldTransform.
271  /// Useful to manually force movements.
272  /// In the case of dynamic rigidbodies a velocity reset should be applied first.
273  /// </summary>
275  {
276  Collider.PhysicsWorldTransform = DerivePhysicsTransformation();
277  }
278 
279  #endregion Utility
280  }
281 }
Game entity. It usually aggregates multiple EntityComponent
Definition: Entity.cs:28
void UpdatePhysicsTransformation()
Forces an update from the TransformationComponent to the Collider.PhysicsWorldTransform. Useful to manually force movements. In the case of dynamic rigidbodies a velocity reset should be applied first.
Base class for converters to/from a data type.
Represents a three dimensional mathematical vector.
Definition: Vector3.cs:42
static void Translation(ref Vector3 value, out Matrix result)
Creates a translation matrix using the specified offsets.
Definition: Matrix.cs:2672
static readonly Vector3 Zero
A SiliconStudio.Core.Mathematics.Vector3 with all of its components set to zero.
Definition: Vector3.cs:52
static readonly Quaternion Identity
The identity SiliconStudio.Core.Mathematics.Quaternion (0, 0, 0, 1).
Definition: Quaternion.cs:65
Represents a four dimensional mathematical quaternion.
Definition: Quaternion.cs:45
object EntityObject
Gets or sets the entity object. Should always cast this as an Entity
Definition: Collider.cs:451
using SiliconStudio.Paradox. Physics
Represents a 4x4 mathematical matrix.
Definition: Matrix.cs:47