1 module beziermeshmaker.datastructures.vec3;
2 
3 import std.stdio;
4 import std..string;
5 import std.conv;
6 import std.math;
7 
8 /*
9  *This acts as an ordinary Vector3f, except that it can also be passed into openGL functions
10  */
11 class vec3{
12 	float* values;
13 	alias values this;
14 	
15 	this(){
16 		this(0, 0, 0);
17 	}
18 	this(float a, float b, float c){
19 		values = [a, b, c].ptr;
20 	}
21 	this(vec3 input){
22 		this(input.x, input.y, input.z);
23 	}
24 	
25 	@property{
26 		nothrow float x(){ return values[0]; }
27 		nothrow float x(float newX){ return values[0] = newX; }
28 		nothrow float y(){ return values[1]; }
29 		nothrow float y(float newY){ return values[1] = newY; }
30 		nothrow float z(){ return values[2]; }
31 		nothrow float z(float newZ){ return values[2] = newZ; }
32 
33 		float u() { return x; }
34 		float u(float newU){ return x(newU); }
35 		float q() { return y; }
36 		float q(float newQ){ return y(newQ); }
37 		float v() { return z; }
38 		float v(float newV){ return z(newV); }
39 	}
40 	
41 	float dot(vec3 other){
42 		return (x * other.x) + (y * other.y) + (z * other.z);
43 	}
44 	vec3 cross(vec3 v){
45 		return new vec3(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x);
46 	}
47 	vec3 normalize(){
48 		return this / length();
49 	}
50 	//Returns a copy of this vector, interpolated by <amount> between this vector and <other>
51 	vec3 interpolate(float amount, vec3 other) {
52 		float inverse = 1 - amount;
53 		
54 		return new vec3(x * inverse + other.x * amount, y * inverse + other.y * amount, z * inverse + other.z * amount);
55 	}
56 	//Returns a copy of this vector, rotated around <axis> by <theta> radians.
57 	//This uses Rodrigues' rotation formula https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula
58 	vec3 rotateAround(vec3 axis, float theta) {
59 		axis = axis.normalize();
60 
61 		return (this * cos(theta) ) + (axis.cross(this) * sin(theta) ) + (axis * (axis.dot(this)) * (1 - cos(theta) ) );
62 	}
63 	float length(){
64 		return sqrt(x * x + y * y + z * z);
65 	}
66 	float angleBetween(vec3 other){
67 		float value = dot(other) / (length() * other.length() );
68 		
69 		return acos(value);
70 	}
71 	float distanceBetween(vec3 other) {
72 		float xDiff = x - other.x;
73 		float yDiff = y - other.y;
74 		float zDiff = z - other.z;
75 		
76 		return sqrt(xDiff * xDiff + yDiff * yDiff + zDiff * zDiff);
77 	}
78 	
79 	vec3 opBinary(string op)(float val){
80 		if(op == "*"){
81 			return new vec3(x * val, y * val, z * val);
82 		}
83 		else if(op == "/"){
84 			return new vec3(x / val, y / val, z / val);
85 		}
86 		else{
87 			assert(0, "Operator "~op~" not implemented");
88 		}
89 	}
90 	vec3 opBinaryRight(string op)(float val){
91 		if(op == "*"){
92 			return new vec3(x * val, y * val, z * val);
93 		}
94 		else{
95 			assert(0, "Operator "~op~" not implemented");
96 		}
97 	}
98 	vec3 opBinary(string op)(vec3 val){
99 		if(op == "+"){
100 			return new vec3(x + val.x, y + val.y, z + val.z);
101 		}
102 		else if(op == "-"){
103 			return new vec3(x - val.x, y - val.y, z - val.z);
104 		}
105 		else{
106 			assert(0, "Operator "~op~" not implemented");
107 		}
108 	}
109 
110 	override bool opEquals(Object o) {
111 		vec3 other = cast(vec3) o;
112 
113 		if (other is null) {
114 			return false;
115 		}
116 		else {
117 			return approxEqual(x, other.x, 0.00001) && approxEqual(y, other.y, 0.00001) && approxEqual(z, other.z, 0.00001);
118 		}
119 	}
120 	override @trusted size_t toHash() {
121 		return cast(ulong)(x * 10000 + y * 10000 + z * 10000);
122 	}
123 
124 	override string toString(){
125 		return "vec3(" ~ to!string(x) ~ ", " ~ to!string(y) ~ ", " ~ to!string(z) ~ ")";
126 	}
127 	string toNiceString(int chars){
128 		string xStr = to!string(x);
129 		string yStr = to!string(y);
130 		string zStr = to!string(z);
131 		
132 		xStr = leftJustify!string(xStr, chars, ' ');
133 		yStr = leftJustify!string(yStr, chars, ' ');
134 		zStr = leftJustify!string(zStr, chars, ' ');
135 		
136 		return "vec3(" ~ xStr ~ ", " ~ yStr ~ ", " ~ zStr ~ ")";
137 	}
138 }