| 1 |
module dglut.vector; |
|---|
| 2 |
|
|---|
| 3 |
import std.math; |
|---|
| 4 |
|
|---|
| 5 |
private template Init(T) { T Init; } |
|---|
| 6 |
|
|---|
| 7 |
template Tuple(T...) { alias T Tuple; } |
|---|
| 8 |
|
|---|
| 9 |
struct TupleWrapper(T...) { alias T Tuple; } |
|---|
| 10 |
|
|---|
| 11 |
template isArray(T) { const bool isArray=false; } |
|---|
| 12 |
template isArray(T: T[]) { const bool isArray=true; } |
|---|
| 13 |
|
|---|
| 14 |
template ElemType(T: T[]) { alias T ElemType; } |
|---|
| 15 |
|
|---|
| 16 |
template Accessor(string name, string what) { |
|---|
| 17 |
mixin(" |
|---|
| 18 |
typeof("~what~") "~name~"() { return "~what~"; } |
|---|
| 19 |
void "~name~"(typeof("~what~") nval) { this."~what~"=nval; } |
|---|
| 20 |
"); |
|---|
| 21 |
} |
|---|
| 22 |
|
|---|
| 23 |
template opGeneric(string name, string param, string assign) { |
|---|
| 24 |
mixin("Vector "~name~"("~param~") { |
|---|
| 25 |
Vector res=void; |
|---|
| 26 |
foreach (idx, part; parts) res.parts[idx]="~assign~"; |
|---|
| 27 |
return res; |
|---|
| 28 |
}"); |
|---|
| 29 |
} |
|---|
| 30 |
|
|---|
| 31 |
template CountTo(size_t what) { |
|---|
| 32 |
static if (!what) alias Tuple!() CountTo; |
|---|
| 33 |
else alias Tuple!(CountTo!(what-1), what-1) CountTo; |
|---|
| 34 |
} |
|---|
| 35 |
|
|---|
| 36 |
// stolen from quake |
|---|
| 37 |
float InvSqrt(float x) { |
|---|
| 38 |
float xhalf = 0.5f * x; |
|---|
| 39 |
int i = *cast(int*)&x; // store floating-point bits in integer |
|---|
| 40 |
i = 0x5f3759d5 - (i >> 1); // initial guess for Newton's method |
|---|
| 41 |
x = *cast(float*)&i; // convert new bits into float |
|---|
| 42 |
x = x*(1.5f - xhalf*x*x); // One round of Newton's method |
|---|
| 43 |
return x; |
|---|
| 44 |
} |
|---|
| 45 |
|
|---|
| 46 |
import std.math, std.stdio: format; |
|---|
| 47 |
struct Vector(T, int size) { |
|---|
| 48 |
T[size] parts; |
|---|
| 49 |
static if ((T.sizeof==4) && (size==3)) T filler=0; // for 16-byte alignment |
|---|
| 50 |
static if (size>0) mixin Accessor!("x", "parts[0]"); |
|---|
| 51 |
static if (size>1) mixin Accessor!("y", "parts[1]"); |
|---|
| 52 |
static if (size>2) mixin Accessor!("z", "parts[2]"); |
|---|
| 53 |
T opIndex(size_t which) { return parts[which]; } |
|---|
| 54 |
void opIndexAssign(size_t which, T n) { parts[which]=n; } |
|---|
| 55 |
static Vector opCall(T[] what...) { |
|---|
| 56 |
Vector res=void; res.parts[]=what[0..size]; |
|---|
| 57 |
static if (is(typeof(res.filler))) res.filler=0; |
|---|
| 58 |
return res; |
|---|
| 59 |
} |
|---|
| 60 |
static Vector opCall(T[size] what) { |
|---|
| 61 |
Vector res=void; res.parts[]=what; |
|---|
| 62 |
static if (is(typeof(res.filler))) res.filler=0; |
|---|
| 63 |
return res; |
|---|
| 64 |
} |
|---|
| 65 |
// who said D has no duck typing? |
|---|
| 66 |
static if (is(typeof(Init!(T)*Init!(T)))) { |
|---|
| 67 |
float length() { return 1f/invlength; } |
|---|
| 68 |
float invlength() { |
|---|
| 69 |
float res=0; |
|---|
| 70 |
foreach (id; CountTo!(size)) res += parts[id]*parts[id]; |
|---|
| 71 |
return InvSqrt(res); |
|---|
| 72 |
} |
|---|
| 73 |
const bool use_iasm=true; |
|---|
| 74 |
void length(float f) { |
|---|
| 75 |
f *= invlength(); |
|---|
| 76 |
foreach (ref part; parts) part *= f; |
|---|
| 77 |
} |
|---|
| 78 |
void normalize() { |
|---|
| 79 |
auto len=invlength(); |
|---|
| 80 |
foreach (ref part; parts) part *= len; |
|---|
| 81 |
} |
|---|
| 82 |
Vector normalized() { Vector res=*this; res.normalize; return res; } |
|---|
| 83 |
static if (size==3) { |
|---|
| 84 |
Vector cross(ref Vector other) { |
|---|
| 85 |
return Vector(y*other.z-z*other.y, z*other.x-x*other.z, x*other.y-y*other.x); |
|---|
| 86 |
} |
|---|
| 87 |
} |
|---|
| 88 |
mixin opGeneric!("opAdd", "ref Vector other", "part+other.parts[idx]"); |
|---|
| 89 |
mixin opGeneric!("opSub", "ref Vector other", "part-other.parts[idx]"); |
|---|
| 90 |
mixin opGeneric!("opMul", "float f", "part*f"); |
|---|
| 91 |
mixin opGeneric!("opDiv", "float f", "part/f"); |
|---|
| 92 |
string toString() { return format("vec(", T.stringof, "[", size, "]) = ", parts); } |
|---|
| 93 |
} |
|---|
| 94 |
} |
|---|
| 95 |
alias Vector!(float, 3) vec3f; |
|---|