1 /** 2 * Copyright: Copyright (C) 2018 Gabriel Gheorghe, All Rights Reserved 3 * Authors: $(Gabriel Gheorghe) 4 * License: $(LINK2 https://www.gnu.org/licenses/gpl-3.0.txt, GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007) 5 * Source: $(LINK2 https://github.com/GabyForceQ/LibertyEngine/blob/master/source/liberty/math/transform.d) 6 * Documentation: 7 * Coverage: 8 **/ 9 module liberty.math.transform; 10 11 import liberty.logger.impl; 12 import liberty.math.functions; 13 import liberty.math.vector; 14 import liberty.math.matrix; 15 import liberty.scene.component; 16 import liberty.scene.meta; 17 import liberty.scene.entity; 18 import liberty.framework.primitive.vertex; 19 import liberty.framework.terrain.vertex; 20 import liberty.framework.gui.widget; 21 import liberty.core.platform; 22 23 /** 24 * 25 **/ 26 final class Transform : IComponent { 27 private { 28 // getParent 29 Entity parent; 30 Matrix4F modelMatrix = Matrix4F.identity(); 31 Matrix4F tempModelMatrix = Matrix4F.identity(); 32 33 Vector3F location = Vector3F.zero; 34 Vector3F rotation = Vector3F.zero; 35 Vector3F scale = Vector3F.one; 36 37 Vector3F pivot = Vector3F.zero; 38 } 39 40 /** 41 * 42 **/ 43 this(Entity parent) { 44 this.parent = parent; 45 } 46 47 /** 48 * 49 **/ 50 this(Entity parent, Transform transform) { 51 this(parent); 52 location = transform.location; 53 54 tempModelMatrix.c[0][3] += location.x; 55 tempModelMatrix.c[1][3] += location.y; 56 tempModelMatrix.c[2][3] += location.z; 57 58 updateModelMatrix(); 59 } 60 61 /** 62 * Translate location using x, y and z scalars as coordinates. 63 * Location is done in space. 64 **/ 65 Transform setLocation(string op = "=")(float x, float y, float z) 66 if (op == "=" || op == "+=" || op == "-=") 67 do { 68 return setLocation!(op)(Vector3F(x, y, z)); 69 } 70 71 /** 72 * Translate location using a vector with x, y and z coordinates. 73 * Location is done in space. 74 * Returns reference to this so it can be used in a stream. 75 **/ 76 Transform setLocation(string op = "=")(Vector3F location) 77 if (op == "=" || op == "+=" || op == "-=") 78 do { 79 static if (op == "=") { 80 mixin("tempModelMatrix.c[0][3] " ~ op ~ " this.location.x + location.x;"); 81 mixin("tempModelMatrix.c[1][3] " ~ op ~ " this.location.y + location.y;"); 82 mixin("tempModelMatrix.c[2][3] " ~ op ~ " this.location.z + location.z;"); 83 } else { 84 mixin("tempModelMatrix.c[0][3] " ~ op ~ " location.x;"); 85 mixin("tempModelMatrix.c[1][3] " ~ op ~ " location.y;"); 86 mixin("tempModelMatrix.c[2][3] " ~ op ~ " location.z;"); 87 } 88 mixin("this.location " ~ op ~ " location;"); 89 90 updateModelMatrix; 91 return this; 92 } 93 94 /** 95 * Translate x-coordinate location. 96 * Location is done in space. 97 * Returns reference to this so it can be used in a stream. 98 **/ 99 Transform setLocationX(string op = "=")(float value) 100 if (op == "=" || op == "+=" || op == "-=") 101 do { 102 static if (op == "=") 103 mixin("tempModelMatrix.c[0][3] " ~ op ~ " location.x + value;"); 104 else 105 mixin("tempModelMatrix.c[0][3] " ~ op ~ " value;"); 106 mixin("location.x " ~ op ~ " value;"); 107 108 updateModelMatrix; 109 return this; 110 } 111 112 /** 113 * Translate y-coordinate location. 114 * Location is done in space. 115 * Returns reference to this so it can be used in a stream. 116 **/ 117 Transform setLocationY(string op = "=")(float value) 118 if (op == "=" || op == "+=" || op == "-=") 119 do { 120 static if (op == "=") 121 mixin("tempModelMatrix.c[1][3] " ~ op ~ " location.y + value;"); 122 else 123 mixin("tempModelMatrix.c[1][3] " ~ op ~ " value;"); 124 mixin("location.y " ~ op ~ " value;"); 125 126 updateModelMatrix; 127 return this; 128 } 129 130 /** 131 * Translate z-coordinate location. 132 * Location is done in space. 133 * Returns reference to this so it can be used in a stream. 134 **/ 135 Transform setLocationZ(string op = "=")(float value) 136 if (op == "=" || op == "+=" || op == "-=") 137 do { 138 static if (op == "=") 139 mixin("tempModelMatrix.c[2][3] " ~ op ~ " location.z + value;"); 140 else 141 mixin("tempModelMatrix.c[2][3] " ~ op ~ " value;"); 142 mixin("location.z " ~ op ~ " value;"); 143 144 updateModelMatrix; 145 return this; 146 } 147 148 /** 149 * Rotate object specifying the rotation angle and rotation coordinates using scalars x, y and z. 150 * Returns reference to this so it can be used in a stream. 151 **/ 152 //Transform setRotation(string op = "=")(float angle, float rotX, float rotY, float rotZ) 153 //if (op == "=" || op == "+=" || op == "-=") 154 //do { 155 // return setRotation!op(angle, Vector3F(rotX, rotY, rotZ)); 156 //} 157 158 /** 159 * Rotate object specifying the rotation angle and a vector of three scalars for x, y and z. 160 * Returns reference to this so it can be used in a stream. 161 **/ 162 //Transform setRotation(string op = "=")(float angle, Vector3F rotation) 163 //if (op == "=" || op == "+=" || op == "-=") 164 //do { 165 // return this; 166 //} 167 168 /*Transform setRotation(string op = "=")(Matrix3F rotation) 169 if (op == "=" || op == "+=" || op == "-=") 170 do { 171 mixin("tempModelMatrix.c[0][0] " ~ op ~ " rotation.c[0][0];"); 172 mixin("tempModelMatrix.c[0][1] " ~ op ~ " rotation.c[0][1];"); 173 mixin("tempModelMatrix.c[0][2] " ~ op ~ " rotation.c[0][2];"); 174 mixin("tempModelMatrix.c[1][0] " ~ op ~ " rotation.c[1][0];"); 175 mixin("tempModelMatrix.c[1][1] " ~ op ~ " rotation.c[1][1];"); 176 mixin("tempModelMatrix.c[1][2] " ~ op ~ " rotation.c[1][2];"); 177 mixin("tempModelMatrix.c[2][0] " ~ op ~ " rotation.c[2][0];"); 178 mixin("tempModelMatrix.c[2][1] " ~ op ~ " rotation.c[2][1];"); 179 mixin("tempModelMatrix.c[2][2] " ~ op ~ " rotation.c[2][2];"); 180 updateModelMatrix(); 181 return this; 182 }*/ 183 184 /** 185 * Rotate object specifying the rotation angle for pitch axis. 186 * Returns reference to this so it can be used in a stream. 187 **/ 188 Transform rotatePitch(string op = "=")(float angle) 189 if (op == "=" || op == "+=" || op == "-=") 190 do { 191 mixin("rotation.x " ~ op ~ " angle;"); 192 tempModelMatrix.rotateX(rotation.x.radians); 193 194 updateModelMatrix(); 195 return this; 196 } 197 198 /** 199 * Rotate object specifying the rotation angle for yaw axis. 200 * Returns reference to this so it can be used in a stream. 201 **/ 202 Transform rotateYaw(string op = "=")(float angle) 203 if (op == "=" || op == "+=" || op == "-=") 204 do { 205 mixin("rotation.y " ~ op ~ " angle;"); 206 tempModelMatrix.rotateY(rotation.y.radians); 207 208 updateModelMatrix(); 209 return this; 210 } 211 212 /** 213 * Rotate object specifying the rotation angle for roll axis. 214 * Returns reference to this so it can be used in a stream. 215 **/ 216 Transform rotateRoll(string op = "=")(float angle) 217 if (op == "=" || op == "+=" || op == "-=") 218 do { 219 mixin("rotation.z " ~ op ~ " angle;"); 220 tempModelMatrix.rotateZ(rotation.z.radians); 221 222 updateModelMatrix(); 223 return this; 224 } 225 226 /** 227 * Scale object using same value for x, y and z coordinates. 228 * Returns reference to this so it can be used in a stream. 229 **/ 230 Transform setScale(string op = "=")(float value) 231 if (op == "=" || op == "+=" || op == "-=") 232 do { 233 return setScale!op(Vector3F(value, value, value)); 234 } 235 236 /** 237 * Scale object using x, y and z scalars for coordinates. 238 * Returns reference to this so it can be used in a stream. 239 **/ 240 Transform setScale(string op = "=")(float x, float y, float z) 241 if (op == "=" || op == "+=" || op == "-=") 242 do { 243 return setScale!op(Vector3F(x, y, z)); 244 } 245 246 /** 247 * Scale object using a vector with x, y and z scalars for coordinates. 248 * Returns reference to this so it can be used in a stream. 249 **/ 250 Transform setScale(string op = "=")(Vector3F scale) 251 if (op == "=" || op == "+=" || op == "-=") 252 do { 253 mixin("tempModelMatrix.c[0][0] " ~ op ~ " scale.x;"); 254 mixin("tempModelMatrix.c[1][1] " ~ op ~ " scale.y;"); 255 mixin("tempModelMatrix.c[2][2] " ~ op ~ " scale.z;"); 256 257 updateModelMatrix(); 258 return this; 259 } 260 261 /** 262 * Scale object on x axis. 263 * Returns reference to this so it can be used in a stream. 264 **/ 265 Transform setScaleX(string op = "=")(float value) 266 if (op == "=" || op == "+=" || op == "-=") 267 do { 268 mixin("tempModelMatrix.c[0][0] " ~ op ~ " value;"); 269 270 updateModelMatrix(); 271 return this; 272 } 273 274 /** 275 * Scale object on y axis. 276 * Returns reference to this so it can be used in a stream. 277 **/ 278 Transform setScaleY(string op = "=")(float value) 279 if (op == "=" || op == "+=" || op == "-=") 280 do { 281 mixin("tempModelMatrix.c[1][1] " ~ op ~ " value;"); 282 283 updateModelMatrix(); 284 return this; 285 } 286 287 /** 288 * Scale object on z axis. 289 * Returns reference to this so it can be used in a stream. 290 **/ 291 Transform setScaleZ(string op = "=")(float value) 292 if (op == "=" || op == "+=" || op == "-=") 293 do { 294 mixin("tempModelMatrix.c[2][2] " ~ op ~ " value;"); 295 296 updateModelMatrix(); 297 return this; 298 } 299 300 /** 301 * Returns object location in relative space. 302 **/ 303 ref const(Vector3F) getLocation() const { 304 return location; 305 } 306 307 /** 308 * Returns object rotation in relative space. 309 **/ 310 ref const(Vector3F) getRotation() const { 311 return rotation; 312 } 313 314 /** 315 * Returns object scale in relative space. 316 **/ 317 ref const(Vector3F) getScale() const { 318 return scale; 319 } 320 321 /** 322 * 323 **/ 324 Transform setPivot(string op = "=")(float x, float y, float z) 325 if (op == "=" || op == "+=" || op == "-=") 326 do { 327 return setPivot!op(Vector3F(x, y, z)); 328 } 329 330 /** 331 * 332 * Returns reference to this so it can be used in a stream. 333 **/ 334 Transform setPivot(string op = "=")(Vector3F pivot) 335 if (op == "=" || op == "+=" || op == "-=") 336 do { 337 mixin("this.pivot " ~ op ~ " pivot;"); 338 updateModelMatrix(); 339 return this; 340 } 341 342 /** 343 * 344 * Returns reference to this so it can be used in a stream. 345 **/ 346 Transform setPivotX(string op = "=")(float value) 347 if (op == "=" || op == "+=" || op == "-=") 348 do { 349 mixin("pivot.x " ~ op ~ " value;"); 350 updateModelMatrix(); 351 return this; 352 } 353 354 /** 355 * 356 * Returns reference to this so it can be used in a stream. 357 **/ 358 Transform setPivotY(string op = "=")(float value) 359 if (op == "=" || op == "+=" || op == "-=") 360 do { 361 mixin("pivot.y " ~ op ~ " value;"); 362 updateModelMatrix(); 363 return this; 364 } 365 366 /** 367 * 368 * Returns reference to this so it can be used in a stream. 369 **/ 370 Transform setPivotZ(string op = "=")(float value) 371 if (op == "=" || op == "+=" || op == "-=") 372 do { 373 mixin("pivot.z " ~ op ~ " value;"); 374 updateModelMatrix(); 375 return this; 376 } 377 378 /** 379 * 380 **/ 381 ref const(Vector3F) getPivot() const { 382 return pivot; 383 } 384 385 /** 386 * Returns model matrix for the object representation. 387 **/ 388 ref const(Matrix4F) getModelMatrix() const { 389 return modelMatrix; 390 } 391 392 /** 393 * 394 **/ 395 Entity getParent() { 396 return parent; 397 } 398 399 private void updateModelMatrix() { 400 modelMatrix = tempModelMatrix; 401 modelMatrix.c[0][3] += pivot.x; 402 modelMatrix.c[1][3] -= pivot.y; 403 modelMatrix.c[2][3] += pivot.z; 404 } 405 }