1 module dlangui.graphics.scene.transform;
2
3 public import dlangui.core.config;
4 static if (ENABLE_OPENGL):
5 static if (BACKEND_GUI):
6
7 import dlangui.core.math3d;
8 import dlangui.core.types;
9
10 /// 3d transform: scale + translation + rotation
11 class Transform : RefCountedObject {
12 // transform flags
13 protected bool _dirtyTransform = true;
14 protected bool _hasScale = false;
15 protected bool _hasTranslation = false;
16 protected bool _hasRotation = false;
17 // transform parameters
18 protected vec3 _scale = vec3(1.0f, 1.0f, 1.0f);
19 protected vec3 _translation = vec3(0.0f, 0.0f, 0.0f);
20 protected mat4 _rotation = mat4.identity;
21 // resulting transform matrix
22 protected mat4 _matrix;
23
24 this() {
25 setIdentity();
26 }
27
28 protected void invalidateTransform() {
29 _dirtyTransform = true;
30 }
31
32 /// get scale vector
33 public @property ref const(vec3) scaling() const { return _scale; }
34 /// get scale X
35 public @property float scalingX() const { return _scale.x; }
36 /// get scale Y
37 public @property float scalingY() const { return _scale.y; }
38 /// get scale Z
39 public @property float scalingZ() const { return _scale.z; }
40
41 /// set scale vector
42 public @property void scaling(const ref vec3 value) { _scale = value; _hasScale = true; invalidateTransform(); }
43 /// set scale vector x, y, z to the same value
44 public @property void scaling(float value) { _scale.x = _scale.y = _scale.z = value; _hasScale = true; invalidateTransform(); }
45 /// set scale X
46 public @property void scalingX(float value) { _scale.x = value; _hasScale = true; invalidateTransform(); }
47 /// set scale Y
48 public @property void scalingY(float value) { _scale.y = value; _hasScale = true; invalidateTransform(); }
49 /// set scale Z
50 public @property void scalingZ(float value) { _scale.z = value; _hasScale = true; invalidateTransform(); }
51
52 /// get translation vector
53 public @property ref const(vec3) translation() const { return _translation; }
54 /// get translation X
55 public @property float translationX() const { return _translation.x; }
56 /// get translation Y
57 public @property float translationY() const { return _translation.y; }
58 /// get translation Z
59 public @property float translationZ() const { return _translation.z; }
60
61 /// set translation vector
62 public @property void translation(inout vec3 value) { _translation = value; _hasTranslation = true; invalidateTransform(); }
63 /// set translation vector x, y, z to the same value
64 public @property void translation(float value) { _translation.x = _translation.y = _translation.z = value; _hasTranslation = true; invalidateTransform(); }
65 /// set translation x
66 public @property void translationX(float value) { _translation.x = value; _hasTranslation = true; invalidateTransform(); }
67 /// set translation y
68 public @property void translationY(float value) { _translation.y = value; _hasTranslation = true; invalidateTransform(); }
69 /// set translation z
70 public @property void translationZ(float value) { _translation.z = value; _hasTranslation = true; invalidateTransform(); }
71
72 /// translate by vector
73 public void translate(vec3 value) { _translation += value; _hasTranslation = true; invalidateTransform(); }
74 /// translate X
75 public void translateX(float value) { _translation.x += value; _hasTranslation = true; invalidateTransform(); }
76 /// translate Y
77 public void translateY(float value) { _translation.y += value; _hasTranslation = true; invalidateTransform(); }
78 /// translate Z
79 public void translateZ(float value) { _translation.z += value; _hasTranslation = true; invalidateTransform(); }
80
81 /// scale by vector
82 public void scale(vec3 value) { _scale.x *= value.x; _scale.y *= value.y; _scale.z *= value.z; _hasScale = true; invalidateTransform(); }
83 /// scale all axis by the same values
84 public void scale(float value) { _scale *= value; _hasScale = true; invalidateTransform(); }
85 /// scale X
86 public void scaleX(float value) { _scale.x *= value; _hasScale = true; invalidateTransform(); }
87 /// scale Y
88 public void scaleY(float value) { _scale.y *= value; _hasScale = true; invalidateTransform(); }
89 /// scale Z
90 public void scaleZ(float value) { _scale.z *= value; _hasScale = true; invalidateTransform(); }
91
92 /// rotate around X axis
93 public void rotateX(float angle) { _rotation.rotateX(angle); _hasRotation = true; invalidateTransform(); }
94 /// rotate around Y axis
95 public void rotateY(float angle) { _rotation.rotateY(angle); _hasRotation = true; invalidateTransform(); }
96 /// rotate around Z axis
97 public void rotateZ(float angle) { _rotation.rotateZ(angle); _hasRotation = true; invalidateTransform(); }
98 /// rotate around custom axis
99 public void rotate(float angle, const ref vec3 axis) { _rotation.rotate(angle, axis); _hasRotation = true; invalidateTransform(); }
100
101 /// set transform to identity transform
102 public void setIdentity() {
103 _hasTranslation = _hasRotation = _hasScale = _dirtyTransform = false;
104 _scale = vec3(1.0f, 1.0f, 1.0f);
105 _translation = vec3(0.0f, 0.0f, 0.0f);
106 _rotation.setIdentity();
107 _matrix.setIdentity();
108 }
109
110 /// get transform matrix, recalculates if needed
111 public @property ref const(mat4) matrix() {
112 if (_dirtyTransform) {
113 _matrix.setIdentity();
114 if (_hasTranslation)
115 _matrix.translate(_translation);
116 if (_hasRotation)
117 _matrix *= _rotation;
118 if (_hasScale)
119 _matrix.scale(_scale);
120 _dirtyTransform = false;
121 }
122 return _matrix;
123 }
124
125 @property void matrix(ref const(mat4) m) {
126 _matrix = m;
127 _dirtyTransform = false;
128 }
129
130 void lookAt(const vec3 eye, const vec3 center, const vec3 up) {
131 _matrix.setIdentity();
132 _matrix.lookAt(eye, center, up);
133 _dirtyTransform = false;
134 }
135 }