1 module grape.math; 2 3 public import std.math; 4 import std.stdio; 5 import std.algorithm; 6 7 alias Vector3 Vec3; 8 struct Vector3 { 9 public: 10 this(in float[] coord) { 11 set(coord); 12 } 13 14 this(in float x, in float y, in float z) { 15 set(x, y, z); 16 } 17 18 Vec3 opBinary(string op)(Vec3 vec3) if (op == "+") { 19 auto tmp = new float[_coord.length]; 20 tmp[] = _coord[] + vec3.coord[]; 21 auto result = Vec3(tmp); 22 return result; 23 } 24 25 Vec3 opBinary(string op)(Vec3 vec3) if (op == "-") { 26 auto tmp = new float[_coord.length]; 27 tmp[] = _coord[] - vec3.coord[]; 28 auto result = Vec3(tmp); 29 return result; 30 } 31 32 Vec3 opBinary(string op)(float ratio) if (op == "*") { 33 auto tmp = new float[_coord.length]; 34 tmp[] = _coord[] * ratio; 35 auto result = Vec3(tmp); 36 return result; 37 } 38 39 Vec3 opBinaryRight(string op)(float ratio) if (op == "*") { 40 return opBinary!op(ratio); 41 } 42 43 Vec3 opOpAssign(string op)(Vec3 vec3) if (op == "+") { 44 auto tmp = new float[_coord.length]; 45 tmp[] = _coord[] + vec3.coord[]; 46 _coord = tmp; 47 return this; 48 } 49 50 Vec3 opOpAssign(string op)(Vec3 vec3) if (op == "-") { 51 auto tmp = new float[_coord.length]; 52 tmp[] = _coord[] - vec3.coord[]; 53 _coord = tmp; 54 return this; 55 } 56 57 void set(in float[] coord) { 58 _coord = coord.dup; 59 } 60 61 void set(in float x, in float y, in float z) { 62 _coord = [x, y, z]; 63 } 64 65 void set_x(in float x) { 66 _coord[0] = x; 67 } 68 69 void set_y(in float y) { 70 _coord[1] = y; 71 } 72 73 void set_z(in float z) { 74 _coord[2] = z; 75 } 76 77 float dot(Vec3 vec3) { 78 return ( _coord[0]*vec3.x + _coord[1]*vec3.y + _coord[2]*vec3.z ); 79 } 80 81 Vec3 cross(Vec3 vec3) { 82 return Vec3( _coord[1]*vec3.z - _coord[2]*vec3.y, 83 _coord[2]*vec3.x - _coord[0]*vec3.z, 84 _coord[0]*vec3.y - _coord[1]*vec3.x ); 85 } 86 87 @property { 88 float[] coord() { 89 return _coord; 90 } 91 92 float x() { 93 return _coord[0]; 94 } 95 96 float y() { 97 return _coord[1]; 98 } 99 100 float z() { 101 return _coord[2]; 102 } 103 104 float magnitude() { 105 return sqrt(pow(_coord[0], 2) + pow(_coord[1], 2) + pow(_coord[2], 2)); 106 } 107 108 void normalize() { 109 auto m = magnitude(); 110 if (m == 0) return; 111 _coord[0] = _coord[0] / m; 112 _coord[1] = _coord[1] / m; 113 _coord[2] = _coord[2] / m; 114 } 115 } 116 117 private: 118 float[3] _coord; 119 } 120 121 alias Matrix4 Mat4; 122 struct Matrix4 { 123 public: 124 this(in float[] coords...) { 125 set(coords); 126 } 127 128 void set(in float[] coords...) { 129 assert(coords.length == 16); 130 _mat[] = coords[]; 131 } 132 133 Mat4 translate(in float x, in float y, in float z) { 134 Mat4 mat4 = Mat4( 1, 0, 0, 0, 135 0, 1, 0, 0, 136 0, 0, 1, 0, 137 x, y, z, 1 ); 138 return multiply(mat4); 139 } 140 141 Mat4 multiply(Mat4 mat4) { 142 float a = _mat[0], b = _mat[1], c = _mat[2], d = _mat[3], 143 e = _mat[4], f = _mat[5], g = _mat[6], h = _mat[7], 144 i = _mat[8], j = _mat[9], k = _mat[10], l = _mat[11], 145 m = _mat[12], n = _mat[13], o = _mat[14], p = _mat[15], 146 A = mat4.mat[0], B = mat4.mat[1], C = mat4.mat[2], D = mat4.mat[3], 147 E = mat4.mat[4], F = mat4.mat[5], G = mat4.mat[6], H = mat4.mat[7], 148 I = mat4.mat[8], J = mat4.mat[9], K = mat4.mat[10], L = mat4.mat[11], 149 M = mat4.mat[12], N = mat4.mat[13], O = mat4.mat[14], P = mat4.mat[15]; 150 return Mat4( A * a + B * e + C * i + D * m, 151 A * b + B * f + C * j + D * n, 152 A * c + B * g + C * k + D * o, 153 A * d + B * h + C * l + D * p, 154 E * a + F * e + G * i + H * m, 155 E * b + F * f + G * j + H * n, 156 E * c + F * g + G * k + H * o, 157 E * d + F * h + G * l + H * p, 158 I * a + J * e + K * i + L * m, 159 I * b + J * f + K * j + L * n, 160 I * c + J * g + K * k + L * o, 161 I * d + J * h + K * l + L * p, 162 M * a + N * e + O * i + P * m, 163 M * b + N * f + O * j + P * n, 164 M * c + N * g + O * k + P * o, 165 M * d + N * h + O * l + P * p ); 166 } 167 168 Mat4 inverse() { 169 float a = _mat[0], b = _mat[1], c = _mat[2], d = _mat[3], 170 e = _mat[4], f = _mat[5], g = _mat[6], h = _mat[7], 171 i = _mat[8], j = _mat[9], k = _mat[10], l = _mat[11], 172 m = _mat[12], n = _mat[13], o = _mat[14], p = _mat[15], 173 q = a * f - b * e, r = a * g - c * e, 174 s = a * h - d * e, t = b * g - c * f, 175 u = b * h - d * f, v = c * h - d * g, 176 w = i * n - j * m, x = i * o - k * m, 177 y = i * p - l * m, z = j * o - k * n, 178 A = j * p - l * n, B = k * p - l * o, 179 ivd = 1 / (q * B - r * A + s * z + t * y - u * x + v * w); 180 return Mat4( ( f * B - g * A + h * z) * ivd, 181 (-b * B + c * A - d * z) * ivd, 182 ( n * v - o * u + p * t) * ivd, 183 (-j * v + k * u - l * t) * ivd, 184 (-e * B + g * y - h * x) * ivd, 185 ( a * B - c * y + d * x) * ivd, 186 (-m * v + o * s - p * r) * ivd, 187 ( i * v - k * s + l * r) * ivd, 188 ( e * A - f * y + h * w) * ivd, 189 (-a * A + b * y - d * w) * ivd, 190 ( m * u - n * s + p * q) * ivd, 191 (-i * u + j * s - l * q) * ivd, 192 (-e * z + f * x - g * w) * ivd, 193 ( a * z - b * x + c * w) * ivd, 194 (-m * t + n * r - o * q) * ivd, 195 ( i * t - j * r + k * q) * ivd ); 196 } 197 198 @property { 199 float[16] mat() { 200 return _mat; 201 } 202 203 Mat4 identity() { 204 return Mat4( 1, 0, 0, 0, 205 0, 1, 0, 0, 206 0, 0, 1, 0, 207 0, 0, 0, 1 ); 208 } 209 } 210 211 private: 212 float[16] _mat; 213 } 214 215 alias Quaternion Quat; 216 struct Quaternion { 217 public: 218 this(Vec3 vec3) { 219 set(vec3, 0.0); 220 } 221 222 this(Vec3 vec3, in float rad) { // 回転行列の生成 223 rotate(vec3, rad); 224 } 225 226 Quat opBinary(string op)(Quat quat) if (op == "*") { 227 auto rad = _rad*quat.rad - _vec3.dot(quat.vec3); 228 auto vec3 = _rad*quat.vec3 + quat.rad*_vec3 + _vec3.cross(quat.vec3); 229 Quat result; 230 result.set(vec3, rad); 231 return result; 232 } 233 234 void set(in Vec3 vec3) { 235 _vec3 = vec3; 236 } 237 238 void set(in float rad) { 239 _rad = rad; 240 } 241 242 void set(in Vec3 vec3, in float rad) { 243 _rad = rad; 244 _vec3 = vec3; 245 } 246 247 void rotate(Vec3 vec3, in float rad) { 248 vec3.normalize; 249 250 _rad = cos(rad / 2); 251 _vec3 = Vec3( vec3.x * sin(rad / 2), 252 vec3.y * sin(rad / 2), 253 vec3.z * sin(rad / 2) ); 254 } 255 256 @property { 257 Quat conjugate() { 258 Quat quat; 259 quat.set(Vec3(-_vec3.x, -_vec3.y, -_vec3.z), rad); // TODO 260 return quat; 261 } 262 263 Mat4 to_mat4() { 264 auto x = _vec3.x; 265 auto y = _vec3.y; 266 auto z = _vec3.z; 267 auto w = _rad; 268 return Mat4( 1-2*y^^2-2*z^^2, 2*x*y-2*w*z, 2*x*z+2*w*y, 0, 269 2*x*y+2*w*z, 1-2*x^^2-2*z^^2, 2*y*z-2*w*x, 0, 270 2*x*z-2*w*y, 2*y*z+2*w*x, 1-2*x^^2-2*y^^2, 0, 271 0, 0, 0, 1 ); 272 } 273 274 float rad() { 275 return _rad; 276 } 277 278 Vec3 vec3() { 279 return _vec3; 280 } 281 } 282 283 private: 284 Vec3 _vec3; 285 float _rad; 286 } 287