-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathTransform.cs
More file actions
239 lines (202 loc) · 8 KB
/
Transform.cs
File metadata and controls
239 lines (202 loc) · 8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
using OpenTK;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
namespace WindEditor
{
public class WTransform : INotifyPropertyChanged
{
// WPF
public event PropertyChangedEventHandler PropertyChanged;
/// <summary> The parent of this transform that this transform moves locally to. null if a root object. </summary>
public WTransform Parent
{
get { return m_parent; }
set
{
// Remove ourself from our current parents children (if we have any)
if (m_parent != null)
{
m_parent.m_children.Remove(this);
}
// Then assign our new parent, and add ourself to that new parent's children (if non null)
m_parent = value;
if (m_parent != null)
{
m_parent.m_children.Add(this);
}
}
}
public BindingVector3 PositionBase { get; set; }
public BindingVector3 ScaleBase { get; set; }
/// <summary> Position of the object in global space. </summary>
public Vector3 Position
{
get
{
// Walk the tree until there's no more parents and add up our local position distributed across all.
Vector3 transformedPoint = LocalPosition;
WTransform curParent = m_parent;
while (curParent != null)
{
transformedPoint = Vector3.Transform(transformedPoint, curParent.LocalRotation);
transformedPoint += curParent.LocalPosition;
curParent = curParent.m_parent;
}
return transformedPoint;
}
set
{
Vector3 transformedPoint = value;
WTransform curParent = m_parent;
while (curParent != null)
{
// Calculate the inverse of the parent's rotation so we can subtract that rotation.
Quaternion inverseRot = curParent.LocalRotation.Inverted();
transformedPoint -= curParent.LocalPosition;
transformedPoint = Vector3.Transform(transformedPoint, inverseRot);
curParent = curParent.m_parent;
}
LocalPosition = transformedPoint;
OnPropertyChanged("Position");
}
}
/// <summary> Rotation of the object in global space. </summary>
public Quaternion Rotation
{
get
{
// Walk the tree until no more parents adding up the local rotations of each.
Quaternion transformedRot = LocalRotation;
WTransform curParent = m_parent;
while (curParent != null)
{
transformedRot = curParent.LocalRotation * transformedRot;
curParent = curParent.m_parent;
}
return transformedRot;
}
set
{
Quaternion transformedRot = value;
WTransform curParent = m_parent;
while (curParent != null)
{
// Calculate the inverse of the parents rotation so we can subtract that rotation.
Quaternion inverseRot = curParent.LocalRotation.Inverted();
transformedRot = inverseRot * transformedRot;
curParent = curParent.m_parent;
}
m_localRotation = transformedRot;
}
}
/// <summary> Local scale of the object. Global scale is not supported. </summary>
public Vector3 LocalScale
{
get { return ScaleBase.BackingVector; }
set
{
ScaleBase.BackingVector = value;
OnPropertyChanged("ScaleBase");
}
}
/// <summary> Local position relative to the parent. Equivelent to Position if parent is null. </summary>
public Vector3 LocalPosition
{
get { return PositionBase.BackingVector; }
set
{
PositionBase.BackingVector = value;
OnPropertyChanged("PositionBase");
}
}
/// <summary> Local rotation relative to the parent. Equivelent to Rotation if parent is null. </summary>
public Quaternion LocalRotation
{
get { return m_localRotation; }
set
{
m_localRotation = value;
}
}
/// <summary> The number of children in this transform. </summary>
public int ChildCount
{
get { return m_children.Count; }
}
/// <summary> The local up axis of this object as a direction in world space. </summary>
public Vector3 Up
{
get { return Vector3.Transform(Vector3.UnitY, Rotation); }
}
/// <summary> The local right axis of this object as a direction in world space. </summary>
public Vector3 Right
{
get { return Vector3.Transform(Vector3.UnitX, Rotation); }
}
/// <summary> The local forward axis of this object as a direction in world space. </summary>
public Vector3 Forward
{
get { return Vector3.Transform(Vector3.UnitZ, Rotation); }
}
/// <summary>
/// Returns a child transform by the specified index. Throws <see cref="ArgumentOutOfRangeException"/> if an invalid child index is specified. </summary>
/// <param name="index">Index of the child to return. Get total child count via <see cref="ChildCount"/>.</param>
/// <returns></returns>
public WTransform GetChild(int index)
{
if (index < 0 || index >= ChildCount)
throw new ArgumentOutOfRangeException("index");
return m_children[index];
}
private WTransform m_parent;
private Vector3 m_localPosition;
private Vector3 m_localScale;
private Quaternion m_localRotation;
/// <summary> Children of this transform. It's marked as private and only accessible via GetEnumerator as we don't want people arbitrarily adding children. </summary>
private List<WTransform> m_children;
public WTransform()
{
PositionBase = new BindingVector3();
ScaleBase = new BindingVector3();
LocalPosition = Vector3.Zero;
LocalRotation = Quaternion.Identity;
LocalScale = Vector3.One;
Parent = null;
m_children = new List<WTransform>();
}
public void Rotate(Vector3 axis, float angleInDegrees)
{
Quaternion rotQuat = Quaternion.FromAxisAngle(axis, WMath.DegreesToRadians(angleInDegrees));
Rotation = rotQuat * Rotation;
}
//public IEnumerator GetEnumerator()
//{
// foreach (WTransform trns in m_children)
// {
// yield return trns;
// }
//}
public override bool Equals(object o)
{
WTransform otherTrns = o as WTransform;
if (otherTrns == null)
return false;
return Position == otherTrns.Position && Rotation == otherTrns.Rotation && LocalScale == otherTrns.LocalScale;
}
public override int GetHashCode()
{
return Position.GetHashCode() ^ Rotation.GetHashCode();
}
public override string ToString()
{
return string.Format("Transform (Position: {0} Rotation: {1} LocalScale: {2})", Position, Rotation, LocalScale);
}
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}