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 return tnew; 81 } 82 83 /** 84 Gets the matrix for this transform 85 */ 86 @Ignore 87 mat4 matrix() { 88 return trs; 89 } 90 91 /** 92 Updates the internal matrix of this transform 93 */ 94 void update() { 95 trs = 96 mat4.translation(this.translation) * 97 quat.eulerRotation(this.rotation.x, this.rotation.y, this.rotation.z).toMatrix!(4, 4) * 98 mat4.scaling(this.scale.x, this.scale.y, 1); 99 } 100 101 void clear() { 102 translation = vec3(0); 103 rotation = vec3(0); 104 scale = vec2(1, 1); 105 } 106 107 @Ignore 108 string toString() { 109 import std.format : format; 110 return "%s,\n%s,\n%s\n%s".format(trs.toPrettyString, translation.toString, rotation.toString, scale.toString); 111 } 112 113 void serialize(S)(ref S serializer) { 114 auto state = serializer.objectBegin(); 115 serializer.putKey("trans"); 116 translation.serialize(serializer); 117 118 serializer.putKey("rot"); 119 rotation.serialize(serializer); 120 121 serializer.putKey("scale"); 122 scale.serialize(serializer); 123 124 serializer.objectEnd(state); 125 } 126 127 SerdeException deserializeFromFghj(Fghj data) { 128 translation.deserialize(data["trans"]); 129 rotation.deserialize(data["rot"]); 130 scale.deserialize(data["scale"]); 131 return null; 132 } 133 } 134 /** 135 A 2D transform; 136 */ 137 struct Transform2D { 138 private: 139 @Ignore 140 mat3 trs; 141 142 public: 143 /** 144 Translate 145 */ 146 vec2 translation; 147 /** 148 Scale 149 */ 150 vec2 scale; 151 152 /** 153 Rotation 154 */ 155 float rotation; 156 157 /** 158 Gets the matrix for this transform 159 */ 160 mat3 matrix() { 161 return trs; 162 } 163 164 /** 165 Updates the internal matrix of this transform 166 */ 167 void update() { 168 mat3 translation_ = mat3.translation(vec3(translation, 0)); 169 mat3 rotation_ = mat3.zRotation(rotation); 170 mat3 scale_ = mat3.scaling(scale.x, scale.y, 1); 171 trs = translation_ * rotation_ * scale_; 172 } 173 174 }