1 /* 2 Copyright © 2020, Inochi2D Project 3 Distributed under the 2-Clause BSD License, see LICENSE file. 4 5 Authors: 6 Luna Nielsen 7 Asahi Lina 8 */ 9 module inochi2d.math.transform; 10 public import inochi2d.math; 11 import inochi2d.fmt.serialize; 12 13 /** 14 A transform 15 */ 16 struct Transform { 17 private: 18 @Ignore 19 mat4 trs = mat4.identity; 20 21 public: 22 23 /** 24 The translation of the transform 25 */ 26 vec3 translation = vec3(0, 0, 0); 27 28 /** 29 The rotation of the transform 30 */ 31 vec3 rotation = vec3(0, 0, 0);//; = quat.identity; 32 33 /** 34 The scale of the transform 35 */ 36 vec2 scale = vec2(1, 1); 37 38 /** 39 Whether the transform should snap to pixels 40 */ 41 bool pixelSnap = false; 42 43 /** 44 Initialize a transform 45 */ 46 this(vec3 translation, vec3 rotation = vec3(0), vec2 scale = vec2(1, 1)) { 47 this.translation = translation; 48 this.rotation = rotation; 49 this.scale = scale; 50 } 51 52 Transform calcOffset(Transform other) { 53 Transform tnew; 54 55 tnew.translation = this.translation+other.translation; 56 tnew.rotation = this.rotation+other.rotation; 57 tnew.scale = this.scale*other.scale; 58 tnew.update(); 59 60 return tnew; 61 } 62 63 /** 64 Returns the result of 2 transforms multiplied together 65 */ 66 Transform opBinary(string op : "*")(Transform other) { 67 Transform tnew; 68 69 mat4 strs = other.trs * this.trs; 70 71 // TRANSLATION 72 tnew.translation = vec3(strs * vec4(1, 1, 1, 1)); 73 74 // ROTATION 75 tnew.rotation = this.rotation+other.rotation; 76 77 // SCALE 78 tnew.scale = this.scale*other.scale; 79 tnew.trs = strs; 80 tnew.update(); 81 return tnew; 82 } 83 84 /** 85 Gets the matrix for this transform 86 */ 87 @Ignore 88 mat4 matrix() { 89 return trs; 90 } 91 92 /** 93 Updates the internal matrix of this transform 94 */ 95 void update() { 96 trs = 97 mat4.translation(this.translation) * 98 quat.eulerRotation(this.rotation.x, this.rotation.y, this.rotation.z).toMatrix!(4, 4) * 99 mat4.scaling(this.scale.x, this.scale.y, 1); 100 } 101 102 void clear() { 103 translation = vec3(0); 104 rotation = vec3(0); 105 scale = vec2(1, 1); 106 } 107 108 @Ignore 109 string toString() { 110 import std.format : format; 111 return "%s,\n%s,\n%s\n%s".format(trs.toPrettyString, translation.toString, rotation.toString, scale.toString); 112 } 113 114 void serialize(S)(ref S serializer) { 115 auto state = serializer.objectBegin(); 116 serializer.putKey("trans"); 117 translation.serialize(serializer); 118 119 serializer.putKey("rot"); 120 rotation.serialize(serializer); 121 122 serializer.putKey("scale"); 123 scale.serialize(serializer); 124 125 serializer.objectEnd(state); 126 } 127 128 SerdeException deserializeFromFghj(Fghj data) { 129 translation.deserialize(data["trans"]); 130 rotation.deserialize(data["rot"]); 131 scale.deserialize(data["scale"]); 132 return null; 133 } 134 } 135 /** 136 A 2D transform; 137 */ 138 struct Transform2D { 139 private: 140 @Ignore 141 mat3 trs; 142 143 public: 144 /** 145 Translate 146 */ 147 vec2 translation; 148 /** 149 Scale 150 */ 151 vec2 scale; 152 153 /** 154 Rotation 155 */ 156 float rotation; 157 158 /** 159 Gets the matrix for this transform 160 */ 161 mat3 matrix() { 162 return trs; 163 } 164 165 /** 166 Updates the internal matrix of this transform 167 */ 168 void update() { 169 mat3 translation_ = mat3.translation(vec3(translation, 0)); 170 mat3 rotation_ = mat3.zRotation(rotation); 171 mat3 scale_ = mat3.scaling(scale.x, scale.y, 1); 172 trs = translation_ * rotation_ * scale_; 173 } 174 175 }