1 /* 2 * DSFML - The Simple and Fast Multimedia Library for D 3 * 4 * Copyright (c) 2013 - 2017 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 /** 26 * Vector3 is a simple class that defines a mathematical vector with three 27 * coordinates (x, y and z). It can be used to represent anything that has three 28 * dimensions: a size, a point, a velocity, etc. 29 * 30 * The template parameter `T` is the type of the coordinates. It can be any type 31 * that supports arithmetic operations (+, -, /, *) and comparisons (==, !=), 32 * for example int or float. 33 * 34 * You generally don't have to care about the templated form (Vector2!(T), 35 * the most common specializations have special aliases: 36 * $(UL 37 * $(LI Vector3!(float) is Vector2f) 38 * $(LI Vector3!(int) is Vector2i)) 39 * 40 * Example: 41 * --- 42 * auto v1 = Vector3f(16.5f, 24.f, -8.2f); 43 * v1.x = 18.2f; 44 * float y = v1.y; 45 * float z = v1.z; 46 * 47 * auto v2 = v1 * 5.f; 48 * Vector3f v3; 49 * v3 = v1 + v2; 50 * 51 * bool different = (v2 != v3); 52 * --- 53 * 54 * See_Also: 55 * $(VECTOR2_LINK) 56 */ 57 module dsfml.system.vector3; 58 59 import std.traits; 60 61 /** 62 * Utility template struct for manipulating 3-dimensional vectors. 63 */ 64 struct Vector3(T) 65 if(isNumeric!(T) || is(T == bool)) 66 { 67 /// X coordinate of the vector. 68 T x; 69 /// Y coordinate of the vector. 70 T y; 71 /// Z coordinate of the vector. 72 T z; 73 74 /** 75 * Construct the vector from its coordinates 76 * 77 * Params: 78 * X = X coordinate 79 * Y = Y coordinate 80 * Z = Z coordinate 81 */ 82 this(T X,T Y,T Z) 83 { 84 85 x = X; 86 y = Y; 87 z = Z; 88 89 } 90 91 /** 92 * Construct the vector from another type of vector 93 * 94 * Params: 95 * otherVector = Vector to convert. 96 */ 97 this(E)(Vector3!(E) otherVector) 98 { 99 x = cast(T)(otherVector.x); 100 y = cast(T)(otherVector.y); 101 z = cast(T)(otherVector.z); 102 } 103 104 /// Invert the members of the vector. 105 Vector3!(T) opUnary(string s)() const 106 if(s == "-") 107 { 108 return Vector3!(T)(-x,-y,-z); 109 } 110 111 /// Add/Subtract between two vector3's. 112 Vector3!(T) opBinary(string op,E)(Vector3!(E) otherVector) const 113 if(isNumeric!(E) && ((op == "+") || (op == "-"))) 114 { 115 static if (op == "+") 116 { 117 return Vector3!(T)(cast(T)(x+otherVector.x),cast(T)(y+otherVector.y),cast(T)(z + otherVector.z)); 118 } 119 static if(op == "-") 120 { 121 return Vector3!(T)(cast(T)(x-otherVector.x),cast(T)(y-otherVector.y),cast(T)(z - otherVector.z)); 122 } 123 124 } 125 126 /// Multiply/Divide a Vector3 with a numaric value. 127 Vector3!(T) opBinary(string op,E)(E num) const 128 if(isNumeric!(E) && ((op == "*") || (op == "/"))) 129 { 130 static if (op == "*") 131 { 132 return Vector3!(T)(cast(T)(x*num),cast(T)(y*num),cast(T)(z*num)); 133 } 134 static if(op == "/") 135 { 136 return Vector3!(T)(cast(T)(x/num),cast(T)(y/num),cast(T)(z/num)); 137 } 138 } 139 140 /// Assign Add/Subtract with another vector3. 141 ref Vector3!(T) opOpAssign(string op, E)(Vector3!(E) otherVector) 142 if(isNumeric!(E) && ((op == "+") || (op == "-"))) 143 { 144 static if(op == "+") 145 { 146 x += otherVector.x; 147 y += otherVector.y; 148 z += otherVector.z; 149 return this; 150 } 151 static if(op == "-") 152 { 153 x -= otherVector.x; 154 y -= otherVector.y; 155 z -= otherVector.z; 156 return this; 157 } 158 } 159 160 // Assign Multiply/Divide a Vector3 with a numaric value. 161 ref Vector3!(T) opOpAssign(string op,E)(E num) 162 if(isNumeric!(E) && ((op == "*") || (op == "/"))) 163 { 164 static if(op == "*") 165 { 166 x *= num; 167 y *= num; 168 z *= num; 169 return this; 170 } 171 static if(op == "/") 172 { 173 x /= num; 174 y /= num; 175 z /= num; 176 return this; 177 } 178 } 179 180 /// Assign the value of another vector whose type can be converted to T. 181 ref Vector3!(T) opAssign(E)(Vector3!(E) otherVector) 182 { 183 x = cast(T)(otherVector.x); 184 y = cast(T)(otherVector.y); 185 z = cast(T)(otherVector.z); 186 return this; 187 } 188 189 /// Compare two vectors for equality. 190 bool opEquals(E)(const Vector3!(E) otherVector) const 191 if(isNumeric!(E)) 192 { 193 return ((x == otherVector.x) && (y == otherVector.y) 194 && (z == otherVector.z)); 195 } 196 197 /// Output the string representation of the Vector3. 198 string toString() const 199 { 200 import std.conv; 201 return "X: " ~ text(x) ~ " Y: " ~ text(y) ~ " Z: " ~ text(z); 202 } 203 } 204 205 /// Definition of a Vector3 of integers. 206 alias Vector3!(int) Vector3i; 207 /// Definition of a Vector3 of floats. 208 alias Vector3!(float) Vector3f; 209 210 unittest 211 { 212 version(DSFML_Unittest_System) 213 { 214 import std.stdio; 215 216 writeln("Unit test for Vector3"); 217 218 auto floatVector3 = Vector3f(100,100,100); 219 220 assert((floatVector3/2) == Vector3f(50,50,50)); 221 222 assert((floatVector3*2) == Vector3f(200,200,200)); 223 224 assert((floatVector3 + Vector3f(50, 0,100)) == Vector3f(150, 100,200)); 225 226 assert((floatVector3 - Vector3f(50,0,300)) == Vector3f(50,100,-200)); 227 228 floatVector3/=2; 229 230 assert(floatVector3 == Vector3f(50,50,50)); 231 232 floatVector3*=2; 233 234 assert(floatVector3 == Vector3f(100,100,100)); 235 236 floatVector3+= Vector3f(50,0,100); 237 238 assert(floatVector3 == Vector3f(150,100,200)); 239 240 floatVector3-=Vector3f(50,100,50); 241 242 assert(floatVector3 == Vector3f(100,0,150)); 243 244 writeln("Vector3 tests passed"); 245 writeln(); 246 } 247 248 }