1 /* 2 * DSFML - The Simple and Fast Multimedia Library for D 3 * 4 * Copyright (c) 2013 - 2018 Jeremy DeHaan (dehaan.jeremiah@gmail.com) 5 * 6 * This software is provided 'as-is', without any express or implied warranty. 7 * In no event will the authors be held liable for any damages arising from the 8 * use of this software. 9 * 10 * Permission is granted to anyone to use this software for any purpose, 11 * including commercial applications, and to alter it and redistribute it 12 * freely, subject to the following restrictions: 13 * 14 * 1. The origin of this software must not be misrepresented; you must not claim 15 * that you wrote the original software. If you use this software in a product, 16 * an acknowledgment in the product documentation would be appreciated but is 17 * not required. 18 * 19 * 2. Altered source versions must be plainly marked as such, and must not be 20 * misrepresented as being the original software. 21 * 22 * 3. This notice may not be removed or altered from any source distribution 23 * 24 * 25 * DSFML is based on SFML (Copyright Laurent Gomila) 26 */ 27 28 /** 29 * Vector3 is a simple structure that defines a mathematical vector with three 30 * coordinates (x, y and z). It can be used to represent anything that has three 31 * dimensions: a size, a point, a velocity, etc. 32 * 33 * The template parameter `T` is the type of the coordinates. It can be any type 34 * that supports arithmetic operations (+, -, /, *) and comparisons (==, !=), 35 * for example int or float. 36 * 37 * You generally don't have to care about the templated form (Vector2!(T)), 38 * the most common specializations have special aliases: 39 * $(UL 40 * $(LI Vector3!(float) is Vector2f) 41 * $(LI Vector3!(int) is Vector2i)) 42 * 43 * Example: 44 * --- 45 * auto v1 = Vector3f(16.5f, 24.f, -8.2f); 46 * v1.x = 18.2f; 47 * float y = v1.y; 48 * float z = v1.z; 49 * 50 * auto v2 = v1 * 5.f; 51 * Vector3f v3; 52 * v3 = v1 + v2; 53 * 54 * bool different = (v2 != v3); 55 * --- 56 * 57 * See_Also: 58 * $(VECTOR2_LINK) 59 */ 60 module dsfml.system.vector3; 61 62 import std.traits; 63 64 /** 65 * Utility template struct for manipulating 3-dimensional vectors. 66 */ 67 struct Vector3(T) 68 if(isNumeric!(T) || is(T == bool)) 69 { 70 /// X coordinate of the vector. 71 T x; 72 73 /// Y coordinate of the vector. 74 T y; 75 76 /// Z coordinate of the vector. 77 T z; 78 79 /** 80 * Construct the vector from its coordinates 81 * 82 * Params: 83 * X = X coordinate 84 * Y = Y coordinate 85 * Z = Z coordinate 86 */ 87 this(T X,T Y,T Z) 88 { 89 90 x = X; 91 y = Y; 92 z = Z; 93 94 } 95 96 /** 97 * Construct the vector from another type of vector 98 * 99 * Params: 100 * otherVector = Vector to convert. 101 */ 102 this(E)(Vector3!(E) otherVector) 103 { 104 x = cast(T)(otherVector.x); 105 y = cast(T)(otherVector.y); 106 z = cast(T)(otherVector.z); 107 } 108 109 /// Invert the members of the vector. 110 Vector3!(T) opUnary(string s)() const 111 if(s == "-") 112 { 113 return Vector3!(T)(-x,-y,-z); 114 } 115 116 /// Add/Subtract between two vector3's. 117 Vector3!(T) opBinary(string op,E)(Vector3!(E) otherVector) const 118 if(isNumeric!(E) && ((op == "+") || (op == "-"))) 119 { 120 static if (op == "+") 121 { 122 return Vector3!(T)(cast(T)(x+otherVector.x),cast(T)(y+otherVector.y),cast(T)(z + otherVector.z)); 123 } 124 static if(op == "-") 125 { 126 return Vector3!(T)(cast(T)(x-otherVector.x),cast(T)(y-otherVector.y),cast(T)(z - otherVector.z)); 127 } 128 } 129 130 /// Multiply/Divide a Vector3 with a numaric value. 131 Vector3!(T) opBinary(string op,E)(E num) const 132 if(isNumeric!(E) && ((op == "*") || (op == "/"))) 133 { 134 static if (op == "*") 135 { 136 return Vector3!(T)(cast(T)(x*num),cast(T)(y*num),cast(T)(z*num)); 137 } 138 static if(op == "/") 139 { 140 return Vector3!(T)(cast(T)(x/num),cast(T)(y/num),cast(T)(z/num)); 141 } 142 } 143 144 /// Assign Add/Subtract with another vector3. 145 ref Vector3!(T) opOpAssign(string op, E)(Vector3!(E) otherVector) 146 if(isNumeric!(E) && ((op == "+") || (op == "-"))) 147 { 148 static if(op == "+") 149 { 150 x += otherVector.x; 151 y += otherVector.y; 152 z += otherVector.z; 153 return this; 154 } 155 static if(op == "-") 156 { 157 x -= otherVector.x; 158 y -= otherVector.y; 159 z -= otherVector.z; 160 return this; 161 } 162 } 163 164 // Assign Multiply/Divide a Vector3 with a numaric value. 165 ref Vector3!(T) opOpAssign(string op,E)(E num) 166 if(isNumeric!(E) && ((op == "*") || (op == "/"))) 167 { 168 static if(op == "*") 169 { 170 x *= num; 171 y *= num; 172 z *= num; 173 return this; 174 } 175 static if(op == "/") 176 { 177 x /= num; 178 y /= num; 179 z /= num; 180 return this; 181 } 182 } 183 184 /// Assign the value of another vector whose type can be converted to T. 185 ref Vector3!(T) opAssign(E)(Vector3!(E) otherVector) 186 { 187 x = cast(T)(otherVector.x); 188 y = cast(T)(otherVector.y); 189 z = cast(T)(otherVector.z); 190 return this; 191 } 192 193 /// Compare two vectors for equality. 194 bool opEquals(E)(const Vector3!(E) otherVector) const 195 if(isNumeric!(E)) 196 { 197 return ((x == otherVector.x) && (y == otherVector.y) 198 && (z == otherVector.z)); 199 } 200 201 /// Output the string representation of the Vector3. 202 string toString() const 203 { 204 import std.conv; 205 return "X: " ~ text(x) ~ " Y: " ~ text(y) ~ " Z: " ~ text(z); 206 } 207 } 208 209 /// Definition of a Vector3 of integers. 210 alias Vector3!(int) Vector3i; 211 212 /// Definition of a Vector3 of floats. 213 alias Vector3!(float) Vector3f; 214 215 unittest 216 { 217 version(DSFML_Unittest_System) 218 { 219 import std.stdio; 220 221 writeln("Unit test for Vector3"); 222 223 auto floatVector3 = Vector3f(100,100,100); 224 225 assert((floatVector3/2) == Vector3f(50,50,50)); 226 227 assert((floatVector3*2) == Vector3f(200,200,200)); 228 229 assert((floatVector3 + Vector3f(50, 0,100)) == Vector3f(150, 100,200)); 230 231 assert((floatVector3 - Vector3f(50,0,300)) == Vector3f(50,100,-200)); 232 233 floatVector3/=2; 234 235 assert(floatVector3 == Vector3f(50,50,50)); 236 237 floatVector3*=2; 238 239 assert(floatVector3 == Vector3f(100,100,100)); 240 241 floatVector3+= Vector3f(50,0,100); 242 243 assert(floatVector3 == Vector3f(150,100,200)); 244 245 floatVector3-=Vector3f(50,100,50); 246 247 assert(floatVector3 == Vector3f(100,0,150)); 248 249 writeln("Vector3 tests passed"); 250 writeln(); 251 } 252 }