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 }