Advertisement
GeneralGDA

vector with swizzling

Mar 2nd, 2015
645
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
D 6.23 KB | None | 0 0
  1. module ru.nsk.sampler.math.vector;
  2.  
  3. //math stuff (sqrt, cos, sin)
  4. import std.math;
  5.  
  6. //'zip', 'repeat', 'take' lie here
  7. import std.range;
  8.  
  9. //'map' and 'reduce' lie here
  10. import std.algorithm;
  11.  
  12. //to make char upper case + 'format' - a sprintf-like function
  13. import std.string;
  14.  
  15. public static immutable X = 0;
  16. public static immutable Y = 1;
  17. public static immutable Z = 2;
  18. public static immutable W = 3;
  19.  
  20. public struct Vector4
  21. {
  22.     public
  23.     {
  24.  
  25.         static immutable DIMENSION = 4;
  26.  
  27.         this(Range)(Range coords)
  28.         {
  29.             assert(DIMENSION >= coords.length);
  30.  
  31.             auto i = 0u;
  32.             foreach (immutable coord; coords)
  33.             {
  34.                 this.coords[i] = coord;
  35.                 i++;
  36.             }
  37.         }
  38.  
  39.         this(T...)(T coords) pure if (T.length <= DIMENSION)
  40.         {
  41.             auto i = 0u;
  42.             foreach (immutable coord; coords)
  43.             {
  44.                 this.coords[i] = coord;
  45.                 i++;
  46.             }
  47.         }
  48.  
  49.         @property float[] get() pure nothrow
  50.         {
  51.             return coords;
  52.         }
  53.  
  54.         @property const (float[]) get() const pure nothrow
  55.         {
  56.             return coords;
  57.         }
  58.  
  59.         alias get this;
  60.  
  61.         mixin(acessor('x'));
  62.         mixin(acessor('y'));
  63.         mixin(acessor('z'));
  64.         mixin(acessor('w'));
  65.  
  66.         auto opUnary(const string op)() const pure if ("-" == op || "+" == op)
  67.         {
  68.             return Vector4 ( coords[0..$-1].map!(op ~ "a") );
  69.         }
  70.  
  71.         auto opBinary(const string op)(in Vector4 right) const pure if ("-" == op || "+" == op)
  72.         {
  73.             return Vector4 ( zip(this.coords[0..$-1], right.coords[0..$-1]).map!("a[0]" ~ op ~ "a[1]") );
  74.         }
  75.  
  76.         auto opBinary(const string op)(in float scalar) const pure if ("/" == op || "*" == op)
  77.         {
  78.             return Vector4 ( this.coords[0..$-1].map!( element => mixin(format("element %s scalar", op)) ));
  79.         }
  80.  
  81.         @property auto opDispatch(const string swizzling)() const pure
  82.         {
  83.             immutable expression = "coords".repeat().take(swizzling.length)
  84.             .zip(swizzling).map!( a => format("%s[%c]", a[0], a[1].toUpper()) ).reduce!((a,b) => a ~ "," ~ b);
  85.  
  86.             mixin( "return Vector4 (" ~ expression ~ ");" );
  87.         }
  88.  
  89.         auto opEquals(in Vector4 other) const pure nothrow
  90.         {
  91.             return this.coords == other.coords;
  92.         }
  93.  
  94.     } // public
  95.  
  96.     private
  97.     {
  98.         static string acessor(in char name) pure
  99.         {
  100.     immutable setter = format("@property ref float %c()       pure nothrow { return coords[%c]; }", name, name.toUpper);
  101.     immutable getter = format("@property     float %c() const pure nothrow { return coords[%c]; }", name, name.toUpper);
  102.  
  103.             return setter ~ getter;
  104.         }
  105.  
  106.         float[DIMENSION] coords = [0.0f, 0.0f, 0.0f, 1.0f,];
  107.  
  108.     } // private
  109. };
  110.  
  111. private float dot(in float[] left, in float[] right) pure
  112. {
  113.     return zip(left, right).map!(a => a[0] * a[1]).reduce!((a, b) => a + b);
  114. }
  115.  
  116. public
  117. {
  118.    
  119.     float dot3(T)(in T left, in T right) pure
  120.     {
  121.         return dot(left.coords[0..$-1], right.coords[0..$-1]);
  122.     }
  123.  
  124.     float dot4(T)(in T left, in T right) pure
  125.     {
  126.         return dot(left.coords[0..$], right.coords[0..$]);
  127.     }
  128.  
  129.     float norm(T)(in T vector) pure
  130.     {
  131.         return sqrt(dot3(vector, vector));
  132.     }
  133.  
  134.     T identity(T)(in T vector) pure
  135.     {
  136.         return vector / norm(vector);
  137.     }
  138.  
  139.     T mul(T)(in T left, in T right) pure
  140.     {
  141.         return Vector4( zip(left.get(), right.get()).map!(a => a[0] * a[1]) );
  142.     }
  143.  
  144.     auto cross(in Vector4 l, in Vector4 r) pure
  145.     {
  146.         return mul( l.yzx, r.zxy ) - mul( l.zxy, r.yzx );
  147.     }
  148.  
  149.     auto rotateAroundY(in Vector4 v, in float angleDegrees) pure nothrow
  150.     {
  151.         import ru.nsk.sampler.math.utils:radians;
  152.  
  153.         immutable angleRadians = radians(angleDegrees);
  154.  
  155.         immutable c = cos(angleRadians);
  156.         immutable s = sin(angleRadians);
  157.  
  158.         immutable x = v.x * c - v.z * s;
  159.         immutable y = v.y;
  160.         immutable z = v.x * s + v.z * c;
  161.  
  162.         return Vector4(x, y, z);
  163.     }
  164.  
  165.     auto rotateAroundX(in Vector4 v, in float angleDegrees) pure nothrow
  166.     {
  167.         import ru.nsk.sampler.math.utils:radians;
  168.  
  169.         immutable angleRadians = radians(angleDegrees);
  170.  
  171.         immutable c = cos(angleRadians);
  172.         immutable s = sin(angleRadians);
  173.  
  174.         immutable x = v.x;
  175.         immutable y = v.y * c - v.z * s;
  176.         immutable z = v.y * s + v.z * c;
  177.  
  178.         return Vector4(x, y, z);
  179.     }
  180.  
  181. } // public
  182.  
  183. unittest
  184. {
  185.     immutable Vector4 v;
  186.  
  187.     immutable wwww = v.wwww;
  188.     immutable xwxw = v.xwxw;
  189.     immutable wxxx = v.wxxx;
  190.  
  191.     assert(wwww == Vector4(1, 1, 1, 1) );
  192.     assert(xwxw == Vector4(0, 1, 0, 1) );
  193.     assert(wxxx == Vector4(1, 0, 0, 0) );
  194. }
  195.  
  196. unittest
  197. {
  198.     const v = Vector4(1, 2, 3, 4);
  199.    
  200.     assert(v.yzx == Vector4(2, 3, 1) );
  201.     assert(v.zxy == Vector4(3, 1, 2) );
  202. }
  203.  
  204. unittest
  205. {
  206.     const v = Vector4();
  207.  
  208.     assert(0.0f == v.norm());
  209. }
  210.  
  211. unittest
  212. {
  213.     const a = Vector4(1,0,0);
  214.     const b = Vector4(1,1,1);
  215.  
  216.     assert(1.0f == a.dot3(b));
  217. }
  218.  
  219. unittest
  220. {
  221.     const a = Vector4(1,0,0);
  222.     const b = Vector4(0,1,0);
  223.  
  224.     assert(Vector4(0,0,+1) == a.cross(b));
  225.     assert(Vector4(0,0,-1) == b.cross(a));
  226.    
  227.     assert(Vector4(0,0,0) == cross(Vector4(), Vector4()));
  228. }
  229.  
  230. unittest
  231. {
  232.     assert (Vector4.sizeof == Vector4.DIMENSION * float.sizeof);
  233. }
  234.  
  235. unittest
  236. {
  237.     const v = Vector4(1, 2, 3, 4);
  238.  
  239.     assert (v.zz == Vector4(3, 3));
  240.     assert (v.wx == Vector4(4, 1));
  241.     assert (v.yy == Vector4(2, 2));
  242.     assert (v.xz == Vector4(1, 3));
  243. }
  244.  
  245. unittest
  246. {
  247.     const v = Vector4();
  248.  
  249.     assert (0.0f == v.x);
  250.     assert (0.0f == v[X]);
  251.  
  252.     assert (0.0f == v.y);
  253.     assert (0.0f == v[Y]);
  254.  
  255.     assert (0.0f == v.z);
  256.     assert (0.0f == v[Z]);
  257.  
  258.     assert (1.0f == v.w);
  259.     assert (1.0f == v[W]);
  260. }
  261.  
  262. unittest
  263. {
  264.     auto v = Vector4();
  265.     v.x = 2.0f;
  266.  
  267.     assert (2.0f == v.x);
  268.     assert (2.0f == v[X]);
  269.  
  270.     assert (0.0f == v.y);
  271.     assert (0.0f == v[Y]);
  272.  
  273.     assert (0.0f == v.z);
  274.     assert (0.0f == v[Z]);
  275.  
  276.     assert (1.0f == v.w);
  277.     assert (1.0f == v[W]);
  278. }
  279.  
  280. unittest
  281. {
  282.     auto v = Vector4();
  283.     v.y = 2.0f;
  284.  
  285.     assert (0.0f == v.x);
  286.     assert (0.0f == v[X]);
  287.  
  288.     assert (2.0f == v.y);
  289.     assert (2.0f == v[Y]);
  290.  
  291.     assert (0.0f == v.z);
  292.     assert (0.0f == v[Z]);
  293.  
  294.     assert (1.0f == v.w);
  295.     assert (1.0f == v[W]);
  296. }
  297.  
  298. unittest
  299. {
  300.     auto v = Vector4();
  301.     v.z = 3.0f;
  302.  
  303.     assert (0.0f == v.x);
  304.     assert (0.0f == v[X]);
  305.  
  306.     assert (0.0f == v.y);
  307.     assert (0.0f == v[Y]);
  308.  
  309.     assert (3.0f == v.z);
  310.     assert (3.0f == v[Z]);
  311.  
  312.     assert (1.0f == v.w);
  313.     assert (1.0f == v[W]);
  314. }
  315.  
  316. unittest
  317. {
  318.     auto v = Vector4();
  319.     v.w = 2.0f;
  320.  
  321.     assert (0.0f == v.x);
  322.     assert (0.0f == v[X]);
  323.  
  324.     assert (0.0f == v.y);
  325.     assert (0.0f == v[Y]);
  326.  
  327.     assert (0.0f == v.z);
  328.     assert (0.0f == v[Z]);
  329.  
  330.     assert (2.0f == v.w);
  331.     assert (2.0f == v[W]);
  332. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement