1 /+
2    Vasaro Copyright © 2018 Andrea Fontana
3    This file is part of Vasaro.
4 
5    Vasaro is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation, either version 3 of the License, or
8    (at your option) any later version.
9 
10    Vasaro is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with Vasaro.  If not, see <http://www.gnu.org/licenses/>.
17 +/
18 module vec3;
19 
20 struct Vec3
21 {
22 	import std.traits: isNumeric;
23    import core.simd;
24 
25    version(D_SIMD) { pragma(msg, "SIMD enabled"); }
26    else { pragma(msg, "SIMD not enabled"); }
27 
28    union 
29    { 
30       version(D_SIMD)
31       {
32          float4 	simd = 0;
33       }
34 
35       float[3] 	data; 
36       struct 	   { float x; float y; float z; }
37    }
38 
39    // Better avoid copy c-tors
40    @disable this(this); 
41    
42    this(float x, float y, float z) 	{ this.data = [x,y,z]; }
43    this(float[3] data) 				   { this.data[] = data[]; } 
44    
45    Vec3 opBinary(string op)(const ref Vec3 v) const if((op == "+") || (op == "-") || (op == "*") || (op == "/")) {
46       Vec3 result;
47       version(D_SIMD) { result.simd =  mixin("simd" ~ op ~ "v.simd"); }
48       else { result.data[] = mixin("data[]" ~ op ~ "v.data[]"); }
49       return result;
50    }
51    
52    Vec3 opBinary(string op, T)(const T v) const if(((op == "+") || (op == "-") || (op == "*") || (op == "/")) && isNumeric!T) {
53       Vec3 result;
54       version(D_SIMD) { result.simd =  mixin("simd" ~ op ~ "v"); }
55       else { result.data[] = mixin("data[]" ~ op ~ "v"); }
56       return result;
57    }
58    
59    void opOpAssign(string op)(const ref Vec3 v) if((op == "+") || (op == "-") || (op == "*") || (op == "/")) {
60       version(D_SIMD) { mixin("simd = simd " ~ op ~ "v.simd;"); }
61       else { mixin("this.data[] " ~ op ~ "= v.data[];"); }
62    }
63    
64    void opOpAssign(string op, T)(const T v) if(((op == "+") || (op == "-") || (op == "*") || (op == "/")) && isNumeric!T) {
65       version(D_SIMD) { mixin("simd = simd " ~ op ~ "v;"); }
66       else { mixin("this.data[] " ~ op ~ "= v;"); }
67    }
68    
69    void opAssign(const ref Vec3 v) 
70    {
71       version(D_SIMD) { simd = v.simd; }
72       else { this.data[] = v.data[]; } 
73    }
74 
75    void opAssign(Vec3 v) 
76    { 
77       version(D_SIMD) { simd = v.simd; }
78       else { this.data[] = v.data[]; }
79    }
80 
81    @property float magnitude() const
82    { 
83       import std.math : sqrt;
84       return sqrt(x*x + y*y + z*z);
85    }
86    
87    Vec3 normalized() const
88    {
89       auto m = magnitude();
90       if (m == 0) return Vec3();
91       else return this / magnitude; 
92    }
93    
94    void normalize() 
95    { 
96       auto m = magnitude();
97       if (m == 0) return;
98       else this /= magnitude; 
99    }
100    
101    Vec3 dotProduct   (const ref Vec3 v) const  { return this*v; }
102    Vec3 crossProduct (Vec3 v)           const  { return Vec3(y*v.z - z*v.y, z*v.x - x*v.z, x*v.y - y*v.x); }
103 
104 }