4 // ////////////////////////////////////////////////////////////////////////// //
5 // i don't want to create a new module for this
6 ubyte clampToByte(T
) (T n
) pure nothrow @safe @nogc if (__traits(isIntegral
, T
)) {
7 //static assert(!__traits(isUnsigned, T), "clampToByte can't process unsigned types");
8 static if (__VERSION__
> 2067) pragma(inline
, true);
9 static if (T
.sizeof
== 2 || T
.sizeof
== 4) {
10 static if (__traits(isUnsigned
, T
)) {
11 return cast(ubyte)(n
&0xff|
(255-((-cast(int)(n
< 256))>>24)));
13 n
&= -cast(int)(n
>= 0);
14 return cast(ubyte)(n|
((255-cast(int)n
)>>31));
16 } else static if (T
.sizeof
== 1) {
17 static assert(__traits(isUnsigned
, T
), "clampToByte: signed byte? no, really?");
20 static assert(false, "clampToByte: integer too big");
25 // ////////////////////////////////////////////////////////////////////////// //
27 import std
.format
: FormatSpec
;
28 void toString (scope void delegate(const(char)[]) sink
, FormatSpec
!char fmt
) const @trusted {
31 sink
.formatValue(x
, fmt
);
33 sink
.formatValue(y
, fmt
);
35 sink
.formatValue(z
, fmt
);
40 float x
= 0, y
= 0, z
= 0;
42 @property float opIndex (size_t idx
) const pure {
43 static if (__VERSION__
> 2067) pragma(inline
, true);
44 if (idx
> 2) assert(0, "invalid index in Vec3 opindex");
45 return (idx
== 0 ? x
: (idx
== 1 ? y
: z
));
48 @property float opIndexAssign (float v
, size_t idx
) {
49 static if (__VERSION__
> 2067) pragma(inline
, true);
50 if (idx
> 2) assert(0, "invalid index in Vec3 opindex");
59 ref Vec3
normalize () {
60 //pragma(inline, true);
61 import std
.math
: sqrt
;
62 immutable invlen
= 1.0f/sqrt(x
*x
+y
*y
+z
*z
);
70 static float length (float x
, float y
) {
71 //pragma(inline, true);
72 import std
.math
: sqrt
;
76 static float length (float x
, float y
, float z
) {
77 //pragma(inline, true);
78 import std
.math
: sqrt
;
79 return sqrt(x
*x
+y
*y
+z
*z
);
83 //pragma(inline, true);
84 import std
.math
: sqrt
;
85 return sqrt(x
*x
+y
*y
+z
*z
);
86 //return length(x, y, z);
90 //pragma(inline, true);
91 import std
.math
: sqrt
;
92 immutable invlen
= 1.0f/sqrt(x
*x
+y
*y
+z
*z
);
93 return Vec3(x
*invlen
, y
*invlen
, z
*invlen
);
97 //pragma(inline, true);
98 import std
.math
: abs
;
99 return Vec3(abs(x
), abs(y
), abs(z
));
102 Vec3
minmax(string op
) (in auto ref Vec3 b
) if (op
== "min" || op
== "max") {
103 //pragma(inline, true);
104 mixin("import std.algorithm : "~op
~";");
105 return mixin("Vec3("~op
~"(x, b.x), "~op
~"(y, b.y), "~op
~"(z, b.z))");
108 Vec3
minmax(string op
) (float v
) if (op
== "min" || op
== "max") {
109 //pragma(inline, true);
110 mixin("import std.algorithm : "~op
~";");
111 return mixin("Vec3("~op
~"(x, v), "~op
~"(y, v), "~op
~"(z, v))");
115 alias min = minmax!"min";
116 alias max = minmax!"max";
119 Vec3
opBinary(string op
) (in auto ref Vec3 b
) if (op
== "+" || op
== "-" || op
== "*" || op
== "/") {
120 static if (__VERSION__
> 2067) pragma(inline
, true);
121 return mixin("Vec3(x"~op
~"b.x, y"~op
~"b.y, z"~op
~"b.z)");
124 Vec3
opBinary(string op
) (in float b
) if (op
== "+" || op
== "-" || op
== "*" || op
== "/") {
125 static if (__VERSION__
> 2067) pragma(inline
, true);
126 return mixin("Vec3(x"~op
~"b, y"~op
~"b, z"~op
~"b)");
129 // cross product (normal to plane containing a and b)
130 Vec3
opBinary(string op
: "%") (in auto ref Vec3 b
) {
131 static if (__VERSION__
> 2067) pragma(inline
, true);
132 return Vec3(y
*b
.z
-z
*b
.y
, z
*b
.x
-x
*b
.z
, x
*b
.y
-y
*b
.x
);
135 float dot() (in auto ref Vec3 b
) {
136 static if (__VERSION__
> 2067) pragma(inline
, true);
137 return x
*b
.x
+y
*b
.y
+z
*b
.z
;
140 float anglev() (in auto ref Vec3 b
) {
141 static if (__VERSION__
> 2067) pragma(inline
, true);
142 import std
.math
: acos
;
143 return acos(dot(b
)/(length
*b
.length
));
146 // n is normal; normalized! ;-)
147 Vec3
reflect() (in auto ref Vec3 n
) {
148 //I - 2.0 * dot(N, I) * N
149 auto res
= Vec3(x
, y
, z
);
150 res
-= n
*(2.0f*n
.dot(this));
154 // things like `.xyy`
155 Vec3
opDispatch(string type
) ()
156 if (type
.length
== 3 &&
157 (type
[0] == 'x' || type
[0] == 'y' || type
[0] == 'z') &&
158 (type
[1] == 'x' || type
[1] == 'y' || type
[1] == 'z') &&
159 (type
[2] == 'x' || type
[2] == 'y' || type
[2] == 'z'))
161 static if (__VERSION__
> 2067) pragma(inline
, true);
162 return mixin("Vec3("~type
[0]~","~type
[1]~","~type
[2]~")");
166 auto rotx() (float angle) {
167 //pragma(inline, true);
168 float sine = void, cosine = void;
169 asm pure nothrow @trusted @nogc {
175 return Vec3(x, y*cosine-z*sine, y*sine+z*cosine);
178 auto roty() (float angle) {
179 //pragma(inline, true);
180 float sine = void, cosine = void;
181 asm pure nothrow @trusted @nogc {
187 return Vec3(x*cosine-z*sine, y, x*sine+z*cosine);
190 auto rotz() (float angle) {
191 //pragma(inline, true);
192 float sine = void, cosine = void;
193 asm pure nothrow @trusted @nogc {
199 return Vec3(x*cosine-y*sine, x*sine+y*cosine, z);
204 ref Vec3
opOpAssign(string op
) (in auto ref Vec3 b
) if (op
== "+" || op
== "-" || op
== "*" || op
== "/") {
205 static if (__VERSION__
> 2067) pragma(inline
, true);
206 mixin("x"~op
~"=b.x;");
207 mixin("y"~op
~"=b.y;");
208 mixin("z"~op
~"=b.z;");
212 ref Vec3
opOpAssign(string op
) (float b
) if (op
== "+" || op
== "-" || op
== "*" || op
== "/") {
213 static if (__VERSION__
> 2067) pragma(inline
, true);
220 //static float smoothstep (float x) pure { static if (__VERSION__ > 2067) pragma(inline, true); return x*x*(3-2*x); }