root/trunk/dglut/vector.d

Revision 166, 3.0 kB (checked in by FeepingCreature, 4 years ago)
  • Moved to package dglut
  • Added alternative function-based texture instantiation
Line 
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;
Note: See TracBrowser for help on using the browser.