diff --git a/DSFML/import/dsfml/audio/listener.d b/DSFML/import/dsfml/audio/listener.d index 7bec3360..cc973ddb 100644 --- a/DSFML/import/dsfml/audio/listener.d +++ b/DSFML/import/dsfml/audio/listener.d @@ -27,7 +27,7 @@ module dsfml.audio.listener; import dsfml.system.common; -import dsfml.system.vector3; +import dsfml.system.vector; /** * Listener is a global interface for defining the audio diff --git a/DSFML/import/dsfml/audio/music.d b/DSFML/import/dsfml/audio/music.d index 666f5aae..3f7d8a1a 100644 --- a/DSFML/import/dsfml/audio/music.d +++ b/DSFML/import/dsfml/audio/music.d @@ -31,7 +31,7 @@ import dsfml.audio.soundsource; import dsfml.system.common; import dsfml.system.exception; import dsfml.system.stringutil; -import dsfml.system.vector3; +import dsfml.system.vector; /** * Music defines a big sound played using streaming, diff --git a/DSFML/import/dsfml/audio/sound.d b/DSFML/import/dsfml/audio/sound.d index 0e835cca..e4403512 100644 --- a/DSFML/import/dsfml/audio/sound.d +++ b/DSFML/import/dsfml/audio/sound.d @@ -31,7 +31,7 @@ import dsfml.audio.soundsource; import dsfml.system.common; import dsfml.system.exception; -import dsfml.system.vector3; +import dsfml.system.vector; /** * Sound defines the properties of the sound such as position, diff --git a/DSFML/import/dsfml/audio/soundsource.d b/DSFML/import/dsfml/audio/soundsource.d index a7b85e08..3ed76792 100644 --- a/DSFML/import/dsfml/audio/soundsource.d +++ b/DSFML/import/dsfml/audio/soundsource.d @@ -25,7 +25,7 @@ module dsfml.audio.soundsource; -import dsfml.system.vector3; +import dsfml.system.vector; import dsfml.system.common; diff --git a/DSFML/import/dsfml/audio/soundstream.d b/DSFML/import/dsfml/audio/soundstream.d index 8f4699b7..17dea098 100644 --- a/DSFML/import/dsfml/audio/soundstream.d +++ b/DSFML/import/dsfml/audio/soundstream.d @@ -28,7 +28,7 @@ module dsfml.audio.soundstream; import dsfml.system.alloc; import dsfml.system.common; -import dsfml.system.vector3; +import dsfml.system.vector; import dsfml.system.linkedlist; import dsfml.system.lock; diff --git a/DSFML/import/dsfml/graphics/drawableimpl.d b/DSFML/import/dsfml/graphics/drawableimpl.d index 3d8b2fd1..ee2ef5c3 100644 --- a/DSFML/import/dsfml/graphics/drawableimpl.d +++ b/DSFML/import/dsfml/graphics/drawableimpl.d @@ -27,7 +27,7 @@ module dsfml.graphics.drawableimpl; public import dsfml.system.common; -import dsfml.system.vector2; +import dsfml.system.vector; import dsfml.graphics.irendertarget; import dsfml.graphics.idrawable, @@ -61,148 +61,146 @@ protected: } public: - - void rotate(float angle) + override void rotate(float angle) { sfDrawable_Rotate(m_ptr, angle); } - void move(float offsetX, float offsetY) + override void move(float offsetX, float offsetY) { sfDrawable_Move(m_ptr, offsetX, offsetY); } - void move(Vector2f offset) + override void move(Vector2f offset) { sfDrawable_Move(m_ptr, offset.x, offset.y); } - Vector2f tranformToLocal(Vector2f point) + override Vector2f transformToLocal(Vector2f point) const { Vector2f ret; sfDrawable_TransformToLocal(m_ptr, point.x, point.y, &ret.x, &ret.y); return ret; } - Vector2f tranformToGlobal(Vector2f point) + override Vector2f transformToGlobal(Vector2f point) const { Vector2f ret; sfDrawable_TransformToLocal(m_ptr, point.x, point.y, &ret.x, &ret.y); return ret; } - void render(IRenderTarget window) + override void render(IRenderTarget window) { sfRenderWindow_DrawThis((cast(DSFMLObject)window).nativePointer, m_ptr); } - void renderWithShader(IRenderTarget window, Shader shader) + override void renderWithShader(IRenderTarget window, Shader shader) { sfRenderWindow_DrawThisWithShader((cast(DSFMLObject)window).nativePointer, m_ptr, shader.nativePointer); } - void setPosition(float x, float y) + override void setPosition(float x, float y) { sfDrawable_SetPosition(m_ptr, x, y); } - void setScale(float scaleX, float scaleY) + override void setScale(float scaleX, float scaleY) { sfDrawable_SetScale(m_ptr, scaleX, scaleY); } - void setOrigin(float originX, float originY) + override void setOrigin(float originX, float originY) { sfDrawable_SetOrigin(m_ptr, originX, originY); } @property { - void x(float x) + override void x(float x) { sfDrawable_SetX(m_ptr, x); } - void y(float y) + override void y(float y) { sfDrawable_SetY(m_ptr, y); } - void position(Vector2f vec) + override void position(Vector2f vec) { sfDrawable_SetPosition(m_ptr, vec.x, vec.y); } - void scaleX(float scale) + override void scaleX(float scale) { if (scale > 0) sfDrawable_SetScaleX(m_ptr, scale); } - void scaleY(float scale) + override void scaleY(float scale) { if (scale > 0) sfDrawable_SetScaleY(m_ptr, scale); } - void scale(Vector2f scale) + override void scale(Vector2f scale) { if (scale.x > 0 && scale.y > 0) sfDrawable_SetScale(m_ptr, scale.x, scale.y); } - - void origin(Vector2f origin) + override void origin(Vector2f origin) { sfDrawable_SetOrigin(m_ptr, origin.x, origin.y); } - void rotation(float angle) + override void rotation(float angle) { sfDrawable_SetRotation(m_ptr, angle); } - void color(Color c) + override void color(Color c) { sfDrawable_SetColor(m_ptr, c); } - void blendMode(BlendMode mode) + override void blendMode(BlendMode mode) { sfDrawable_SetBlendMode(m_ptr, mode); } - Vector2f position() + override Vector2f position() const { return Vector2f(sfDrawable_GetX(m_ptr), sfDrawable_GetY(m_ptr)); } - Vector2f scale() + override Vector2f scale() const { return Vector2f(sfDrawable_GetScaleX(m_ptr), sfDrawable_GetScaleY(m_ptr)); } - Vector2f origin() + override Vector2f origin() const { return Vector2f(sfDrawable_GetOriginX(m_ptr), sfDrawable_GetOriginY(m_ptr)); } - float rotation() + override float rotation() const { return sfDrawable_GetRotation(m_ptr); } - Color color() + override Color color() const { return sfDrawable_GetColor(m_ptr); } - BlendMode blendMode() + override BlendMode blendMode() const { return cast(BlendMode)(sfDrawable_GetBlendMode(m_ptr)); } - void scale(Vector2f scale) + override void scale(Vector2f scale) { sfDrawable_SetScale(m_ptr, scale.x, scale.y); } diff --git a/DSFML/import/dsfml/graphics/idrawable.d b/DSFML/import/dsfml/graphics/idrawable.d index daaf4a66..064c9931 100644 --- a/DSFML/import/dsfml/graphics/idrawable.d +++ b/DSFML/import/dsfml/graphics/idrawable.d @@ -26,7 +26,7 @@ module dsfml.graphics.idrawable; -import dsfml.system.vector2; +import dsfml.system.vector; import dsfml.graphics.irendertarget; import dsfml.graphics.color, @@ -49,7 +49,7 @@ interface IDrawable * Params: * x = New left coordinate * y = New top coordinate - */ + */ void setPosition(float x, float y); /** @@ -60,7 +60,7 @@ interface IDrawable * scaleY = New vertical scale > 0 */ void setScale(float scalex, float scaley); -// in {assert(scalex > 0 && scalex > 0);} // TODO: add in again when interface contracts work + // in {assert(scalex > 0 && scalex > 0);} // TODO: add in again when interface contracts work /** * Set the origin of the object, in coordinates relative to the @@ -96,7 +96,7 @@ interface IDrawable * * Params: * vec = new position - */ + */ void position(Vector2f vec); /** @@ -104,7 +104,7 @@ interface IDrawable * * Params: * scale = New horizontal scale (Strictly positive) - */ + */ void scaleX(float scale); /** @@ -140,7 +140,7 @@ interface IDrawable * * Params: * angle = Angle of rotation, in degree - */ + */ void rotation(float angle); /** @@ -148,7 +148,7 @@ interface IDrawable * * Params: * c = New color - */ + */ void color(Color c); /** @@ -160,6 +160,8 @@ interface IDrawable */ void blendMode(BlendMode mode); +const +{ /** * Get the position of the object * @@ -174,7 +176,7 @@ interface IDrawable * * Returns: * Current scale - */ + */ Vector2f scale(); /** @@ -191,7 +193,7 @@ interface IDrawable * * Returns: * Angle of rotation, in degree - */ + */ float rotation(); /** @@ -199,7 +201,7 @@ interface IDrawable * * Returns: * Current color - */ + */ Color color(); /** @@ -209,7 +211,8 @@ interface IDrawable * Current blending mode */ BlendMode blendMode(); -} +} // const +} // @property /** * Rotate the object @@ -217,7 +220,7 @@ interface IDrawable * * Params: * angle = Angle of rotation in degree - */ + */ void rotate(float angle); /** @@ -227,7 +230,7 @@ interface IDrawable * Params: * offsetX = Offset on the X axis * offsetY = Offset on the Y axis - */ + */ void move(float offsetX, float offsetY); /** @@ -236,7 +239,7 @@ interface IDrawable * * Params: * offset = Amount of units to move the object of - */ + */ void move(Vector2f offset); /** @@ -248,8 +251,8 @@ interface IDrawable * * Returns: * Transformed point - */ - Vector2f tranformToLocal(Vector2f point); + */ + Vector2f tranformToLocal(Vector2f point) const; /** * Transform a point from local coordinates into global coordinates @@ -260,15 +263,15 @@ interface IDrawable * * Returns: * Transformed point - */ - Vector2f tranformToGlobal(Vector2f point); + */ + Vector2f tranformToGlobal(Vector2f point) const; /** * Render the specific geometry of the object * * Params: * window = Target into which render the object - */ + */ void render(IRenderTarget window); /** diff --git a/DSFML/import/dsfml/graphics/irendertarget.d b/DSFML/import/dsfml/graphics/irendertarget.d index 9a9e92c5..719a2a48 100644 --- a/DSFML/import/dsfml/graphics/irendertarget.d +++ b/DSFML/import/dsfml/graphics/irendertarget.d @@ -25,7 +25,7 @@ module dsfml.graphics.irendertarget; -import dsfml.system.vector2; +import dsfml.system.vector; import dsfml.graphics.idrawable; import dsfml.graphics.rect; import dsfml.graphics.shader; diff --git a/DSFML/import/dsfml/graphics/rect.d b/DSFML/import/dsfml/graphics/rect.d index 39c2156b..3e8b9df1 100644 --- a/DSFML/import/dsfml/graphics/rect.d +++ b/DSFML/import/dsfml/graphics/rect.d @@ -56,14 +56,11 @@ else */ struct Rect(T) { - -private: T left; // Left coordinate of the rectangle T top; // Top coordinate of the rectangle T width; // width T height; // height -public: static if (!isIntegerType!(T) && !isRealType!(T)) { static assert (0, "This type is not supported by Rectangle"); diff --git a/DSFML/import/dsfml/graphics/renderimage.d b/DSFML/import/dsfml/graphics/renderimage.d index a0d4db57..76bdbe6c 100644 --- a/DSFML/import/dsfml/graphics/renderimage.d +++ b/DSFML/import/dsfml/graphics/renderimage.d @@ -29,7 +29,7 @@ module dsfml.graphics.renderimage; import dsfml.system.common, dsfml.system.exception, dsfml.system.stringutil, - dsfml.system.vector2; + dsfml.system.vector; import dsfml.graphics.idrawable, dsfml.graphics.image, diff --git a/DSFML/import/dsfml/graphics/renderwindow.d b/DSFML/import/dsfml/graphics/renderwindow.d index 04fb9c83..7084de5c 100644 --- a/DSFML/import/dsfml/graphics/renderwindow.d +++ b/DSFML/import/dsfml/graphics/renderwindow.d @@ -44,7 +44,7 @@ import dsfml.window.event, import dsfml.system.common, dsfml.system.stringutil, - dsfml.system.vector2; + dsfml.system.vector; /** * Simple wrapper for Window that allows easy 2D rendering. diff --git a/DSFML/import/dsfml/graphics/shape.d b/DSFML/import/dsfml/graphics/shape.d index 7e6e9c55..3b29abdf 100644 --- a/DSFML/import/dsfml/graphics/shape.d +++ b/DSFML/import/dsfml/graphics/shape.d @@ -26,7 +26,7 @@ module dsfml.graphics.shape; -import dsfml.system.vector2; +import dsfml.system.vector; import dsfml.graphics.blendmode; import dsfml.graphics.color; diff --git a/DSFML/import/dsfml/graphics/sprite.d b/DSFML/import/dsfml/graphics/sprite.d index 75fde382..a8f32df5 100644 --- a/DSFML/import/dsfml/graphics/sprite.d +++ b/DSFML/import/dsfml/graphics/sprite.d @@ -32,7 +32,7 @@ import dsfml.graphics.drawableimpl; import dsfml.graphics.image; import dsfml.graphics.rect; -import dsfml.system.vector2; +import dsfml.system.vector; /** * Sprite defines a sprite : texture, transformations, @@ -160,7 +160,7 @@ public: * Returns: * Color of pixel */ - Color getPixel(uint x, uint y) + Color getPixel(uint x, uint y) const { return sfSprite_GetPixel(m_ptr, x, y); } @@ -211,7 +211,7 @@ public: * Returns: * Size of the sprite */ - Vector2f size() + Vector2f size() const { return Vector2f(sfSprite_GetWidth(m_ptr), sfSprite_GetHeight(m_ptr)); } @@ -226,7 +226,7 @@ private: void function(SFMLClass, float, float) sfSprite_Resize; void function(SFMLClass, int) sfSprite_FlipX; void function(SFMLClass, int) sfSprite_FlipY; - SFMLClass function(SFMLClass) sfSprite_GetImage; + SFMLClass function(SFMLClass) sfSprite_GetImage; IntRect function(SFMLClass) sfSprite_GetSubRect; float function(SFMLClass) sfSprite_GetWidth; float function(SFMLClass) sfSprite_GetHeight; diff --git a/DSFML/import/dsfml/graphics/text.d b/DSFML/import/dsfml/graphics/text.d index 30068cd3..72a65c45 100644 --- a/DSFML/import/dsfml/graphics/text.d +++ b/DSFML/import/dsfml/graphics/text.d @@ -33,7 +33,7 @@ import dsfml.graphics.drawableimpl; import dsfml.graphics.rect; import dsfml.system.stringutil; -import dsfml.system.vector2; +import dsfml.system.vector; /** diff --git a/DSFML/import/dsfml/graphics/view.d b/DSFML/import/dsfml/graphics/view.d index f70f2e29..e02f1dbd 100644 --- a/DSFML/import/dsfml/graphics/view.d +++ b/DSFML/import/dsfml/graphics/view.d @@ -29,7 +29,7 @@ module dsfml.graphics.view; import dsfml.graphics.rect; import dsfml.system.common, - dsfml.system.vector2; + dsfml.system.vector; /** * This class defines a view (position, size and zoom) ; diff --git a/DSFML/import/dsfml/system/all.d b/DSFML/import/dsfml/system/all.d index fb6ccec9..1de561bf 100644 --- a/DSFML/import/dsfml/system/all.d +++ b/DSFML/import/dsfml/system/all.d @@ -44,5 +44,4 @@ version (darwin) public import dsfml.system.lock, - dsfml.system.vector2, - dsfml.system.vector3; + dsfml.system.vector; \ No newline at end of file diff --git a/DSFML/import/dsfml/system/vector.d b/DSFML/import/dsfml/system/vector.d new file mode 100644 index 00000000..c7467519 --- /dev/null +++ b/DSFML/import/dsfml/system/vector.d @@ -0,0 +1,437 @@ +/* +* DSFML - SFML Library wrapper for the D programming language. +* Copyright (C) 2010 Andreas Hollandt +* +* This software is provided 'as-is', without any express or +* implied warranty. In no event will the authors be held +* liable for any damages arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, +* including commercial applications, and to alter it and redistribute +* it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; +* you must not claim that you wrote the original software. +* If you use this software in a product, an acknowledgment +* in the product documentation would be appreciated but +* is not required. +* +* 2. Altered source versions must be plainly marked as such, +* and must not be misrepresented as being the original software. +* +* 3. This notice may not be removed or altered from any +* source distribution. +*/ +module dsfml.system.vector; + +import std.conv; +import std.math; +import std.traits : isFloatingPoint; + +import std.typetuple; + +/** + * generic fixed-size Vector struct + * + * Params: + * T = element type + * dim = vector dimension + */ +struct Vector(T, int dim) +{ + static assert (dim >= 2 && dim <= 4); + + // vectors of 3 floats are extended to 4 to make it possible to use SSE optimizations + private const realdim = (is(T == float) && dim == 3 && sseAvailable) ? 4 : dim; + // vectors of (3)4 floats or 2 doubles will use SSE + private const bool useSSE = (is(T == float) && realdim == 4 /* || is(T == double) && dim == 2 */ ) && sseAvailable; + + private alias LengthReturnType!(T) LengthType; // the type returned by length + union + { + /// normal struct element access + struct + { + static if (dim >= 1) T x; + static if (dim >= 2) T y; + static if (dim >= 3) T z; + static if (dim >= 4) T w; + } + + struct + { + static if (dim >= 1) T r; + static if (dim >= 2) T g; + static if (dim >= 3) T b; + static if (dim >= 4) T a; + } + + // only the array has the hidden 4th value in case of vec3f + // this is to be able to foreach over tuple without computing w unnecessarily + T[realdim] cell; /// array access + Repeat!(T, dim) tuple; /// for tuple access + } + + // zero vectors + static if (2 == dim) const static Vector zero = Vector(0, 0); + static if (3 == dim) const static Vector zero = Vector(0, 0, 0); + static if (4 == dim) const static Vector zero = Vector(0, 0, 0, 0); + + static if (2 == dim) const static Vector one = Vector(1, 1); + static if (3 == dim) const static Vector one = Vector(1, 1, 1); + static if (4 == dim) const static Vector one = Vector(1, 1, 1, 1); + + static if (2 == dim) const static Vector unitX = Vector(1, 0); + static if (3 == dim) const static Vector unitX = Vector(1, 0, 0); + static if (4 == dim) const static Vector unitX = Vector(1, 0, 0, 0); + + static if (2 == dim) const static Vector unitY = Vector(0, 1); + static if (3 == dim) const static Vector unitY = Vector(0, 1, 0); + static if (4 == dim) const static Vector unitY = Vector(0, 1, 0, 0); + + static if (3 == dim) const static Vector unitZ = Vector(0, 0, 1); + static if (4 == dim) const static Vector unitZ = Vector(0, 0, 1, 0); + + static if (4 == dim) const static Vector unitW = Vector(0, 0, 0, 1); + + + /// ensure that no component is a NaN + invariant() + { + assert(isValid()); + } + + // checks if the elements aren't NaNs + private bool isValid() const + { + static if (dim >= 1) if (isNaN(x)) return false; + static if (dim >= 2) if (isNaN(y)) return false; + static if (dim >= 3) if (isNaN(z)) return false; + static if (dim >= 4) if (isNaN(w)) return false; + return true; + } + + /************************************************************************************ + * Operator overloading + ***********************************************************************************/ + + /// negate the vector + Vector opUnary(string op : "-")() + { + static if (dim == 2) return Vector(-x, -y); + else static if (dim == 3) return Vector(-x, -y, -z); + else static if (dim == 4) return Vector(-x, -y, -z, -w); + } + + /// dot product + T opBinary(string op : "*")(typeof(this) v) + if (is(typeof(T+T)) && is(typeof(T*T))) + { + static if (dim == 2) return x*v.x + y*v.y; + else static if (dim == 3) return x*v.x + y*v.y + z*v.z; + else static if (dim == 4) return x*v.x + y*v.y + z*v.z + w*v.w; + } + + /// element-wise operations, +, -, + Vector opBinary(string op, U:typeof(this))(U v) + // check if the operation is supported on the type T + if (op != "*" && (op == "+" && is(typeof(T+T)) || op == "-" && is(typeof(T-T)) || op == "*" && is(typeof(T*T)) + || op == "/" && is(typeof(T/T)) || op == "%" && is(typeof(T%T)))) + { + Vector res = void; + foreach (i, x; tuple) + mixin("res.tuple[i] = tuple[i] " ~ op ~ " v.tuple[i];"); + return res; + } + + /// operations with a scalar + typeof(this) opBinary(string op)(T s) + { + Vector res = void; + foreach(i, x; tuple) + mixin("res.tuple[i] = tuple[i] " ~ op ~ " s;"); + return res; + } + + /// element-wise assign operations, +=, -=, ... + Vector opOpAssign(string op, U:Vector)(U v) + { + foreach (i, _; tuple) + mixin("tuple[i] " ~ op ~ "= v.tuple[i];"); + + return this; + } + + /// (*=) overload + Vector opOpAssign(string op)(T s) + { + foreach (i, _; tuple) + mixin("tuple[i] " ~ op ~ "= s;"); + + return this; + } + + /// return length*length + @property LengthType sqLength() + { + static if (2 == dim) return (x * x + y * y); + else static if (3 == dim) return (x * x + y * y + z * z); + else static if (4 == dim) return (x * x + y * y + z * z + w * w); + else static assert (false); + } + + /// return the vector length + @property LengthType length() + { + static if (useSSE) + { + static if (is(t == float) && dim == 3) // make sure that w is 0 + assert(w == 0); + + float res; + + auto p = cell.ptr; + asm + { +// movups XMM0, &cell; + mov EAX, p; + movups XMM0, [EAX]; + mulps XMM0, XMM0; // v0 = vec(x*x, y*y, z*z, w*w) + movaps XMM1, XMM0; // v1 = v0 + shufps XMM0, XMM1, 0x4e; // v0 = vec(z*z, w*w, x*x, y*y) + addps XMM0, XMM1; // v0 = vec(x*x + z*z, y*y + w*w, z*z + x*x, w*w + y*y) + movaps XMM1, XMM0; // v1 = v0 + shufps XMM1, XMM1, 0x11; // v1 = vec(w*w + y*y, z*z + x*x, w*w + y*y, z*z + x*x) + addps XMM0, XMM1; // v0 = |vec|^2 at all 4 positions + rsqrtss XMM0, XMM0; // v0 = 1/sqrt(v0) + rcpss XMM0, XMM0; // v= = 1/v0 + movss res, XMM0; + } + return res; + } + else + { + // compute squared length + auto ret = sqLength(); + + // compute sqrt + version(useFastSqrt) + { + static if (is(T == float)) + return fastSqrt(ret); + } + return sqrt(ret); + } + } + + void normalize() + { + static if (useSSE) + { + static if (is(t == float) && dim == 3) // make sure that w is 0 + assert (w == 0, "vector component w isn't 0!"); + + auto p = cell.ptr; + asm + { + mov EAX, p; + movups XMM0, [EAX]; + movaps XMM2, XMM0; // save it for later + + mulps XMM0, XMM0; // v0 = vec(x*x, y*y, z*z, w*w) + movaps XMM1, XMM0; // v1 = v0 + shufps XMM0, XMM1, 0x4e; // v0 = vec(z*z, w*w, x*x, y*y) + addps XMM0, XMM1; // v0 = vec(x*x + z*z, y*y + w*w, z*z + x*x, w*w + y*y) + movaps XMM1, XMM0; // v1 = v0 + shufps XMM1, XMM1, 0x11; // v1 = vec(w*w + y*y, z*z + x*x, w*w + y*y, z*z + x*x) + addps XMM0, XMM1; // v0 = |vec|^2 at all 4 positions + rsqrtps XMM0, XMM0; // v0 = 1/sqrt(v0) + mulps XMM2, XMM0; // v2 = vec * v0 + + movups [EAX], XMM0; + } + } + else + { + auto len = length(); + foreach(i, _; tuple) // bug 2411 workaround, foreach ref on tuples doesn't work + tuple[i] /= len; + } + } + + /// return normalized version of this vector + Vector normalized() + { + Vector res = this; + res.normalize(); + return res; + } + + /// + string toString() + { + string res = "["; + + res ~= to!(string)(x); + static if (dim >= 2) res ~= ", " ~ to!(string)(y); + static if (dim >= 3) res ~= ", " ~ to!(string)(z); + static if (dim >= 4) res ~= ", " ~ to!(string)(w); + + return res ~ "]"; + } + + static if (is(T == float)) + { + /// do a quick normalize using fast approximate inverse sqrt + void quickNormalize() + { + T inv = invSqrt(sqLength); + this *= inv; + } + + /// return a normalized version of this vector + Vector quickNormalized() + { + auto res = this; + res.quickNormalize(); + return res; + } + } + + /// return a pointer to the vector data + @property T* ptr() + { + return &x; + } + + /// calculate distance to other vector + LengthType distance(Vector!(T,dim) other) + { + assert (isValid); + assert (other.isValid); + other -= this; + return other.length; + } + + /// + bool opEquals(ref const Vector v) const + { + assert (isValid); + assert (v.isValid); + + static if (dim >= 1) if (x != v.x) return false; + static if (dim >= 2) if (y != v.y) return false; + static if (dim >= 3) if (z != v.z) return false; + static if (dim >= 4) if (w != v.w) return false; + return true; + } + + /// + bool isUnit() + { + real sql = cast(real)sqLength(); + return abs(sql - 1.0) < 0.001; + } + +} + +/******* useful alias declarations *******/ + +alias Vector!(float, 2) Vector2f; /// +alias Vector!(float, 3) Vector3f; /// +alias Vector!(float, 4) Vector4f; /// + +alias Vector!(double, 2) Vector2d; /// +alias Vector!(double, 3) Vector3d; /// +alias Vector!(double, 4) Vector4d; /// + +alias Vector!(int, 2) Vector2i; /// +alias Vector!(int, 3) Vector3i; /// +alias Vector!(int, 4) Vector4i; /// + +alias Vector!(uint, 2) Vector2ui; /// +alias Vector!(uint, 3) Vector3ui; /// +alias Vector!(uint, 4) Vector4ui; /// + +alias Vector!(ushort, 2) Vector2us; /// +alias Vector!(ushort, 3) Vector3us; /// +alias Vector!(ushort, 4) Vector4us; /// + +alias Vector!(ubyte, 2) Vector2ub; /// +alias Vector!(ubyte, 3) Vector3ub; /// +alias Vector!(ubyte, 4) Vector4ub; /// + + +// TODO: do all kinds of unittesting +unittest +{ + Vector3f v = {1.5f, 1.f, 0.5f}; + Vector3f w = {-1.f, 2.f, -0.5f}; + + assert(v.length - sqrt(3.5f) < 0.0001, sseAvailable ? "SSE length calculation failed" : "normal length calculation failed"); + assert(w.length - sqrt(5.25f) < 0.0001, sseAvailable ? "SSE length calculation failed" : "normal length calculation failed"); + + assert(v+w == Vector3f(0.5f, 3.f, 0.f)); + assert(v-w == Vector3f(2.5f, -1.f, 1.f)); +} + +/** + * compute 1/sqrt(x) + * assumes x > 0 + * + * Copyright (C) 2002-2006 Chris Lomont + * explanation on www.lomont.org + */ +float invSqrt(float x) +{ + assert(x > 0); + + float xhalf = 0.5f * x; + int i = *cast(int*)&x; // get bits for floating value + i = 0x5f375a86 - (i >> 1); // gives initial guess y0 with magic number + x = *cast(float*)&i; // convert bits back to float + x = x*(1.5f - xhalf * x * x); // Newton step, repeating increases accuracy + return x; +} + + +/** + * compute sqrt(x) + * assumes x >= 0 + */ +float fastSqrt(float x) +{ + assert(x >= 0); + + int i = *cast(int*) &x; + if (0 == ((i >> 23)&255)) + return 0; // close + return x * invSqrt(x); +} + +// get the correct return type for the length function +private template LengthReturnType(T) +{ + static if (is(T == float) || is(T == double) || is(T == real)) + alias T LengthReturnType; + else + alias float LengthReturnType; +} + +/// repeat a type count times +template Repeat(T, int count) +{ + static if (!count) + alias TypeTuple!() Repeat; + else + alias TypeTuple!(T, Repeat!(T, count-1)) Repeat; +} + +// determine SSE usability +// TODO: make more sophisticated +version(X86) + version(D_InlineAsm_X86) + const bool sseAvailable = is(typeof({void* foo; asm { mov EAX, foo; movups XMM0, [EAX]; } })); +version(X86_64) + version(D_InlineAsm_X86_64) + const bool sseAvailable = false; // TODO: add this \ No newline at end of file diff --git a/DSFML/import/dsfml/system/vector2.d b/DSFML/import/dsfml/system/vector2.d deleted file mode 100644 index e18f98b2..00000000 --- a/DSFML/import/dsfml/system/vector2.d +++ /dev/null @@ -1,139 +0,0 @@ -/* -* DSFML - SFML Library wrapper for the D programming language. -* Copyright (C) 2008 Julien Dagorn (sirjulio13@gmail.com) -* Copyright (C) 2010 Andreas Hollandt -* -* This software is provided 'as-is', without any express or -* implied warranty. In no event will the authors be held -* liable for any damages arising from the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute -* it freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; -* you must not claim that you wrote the original software. -* If you use this software in a product, an acknowledgment -* in the product documentation would be appreciated but -* is not required. -* -* 2. Altered source versions must be plainly marked as such, -* and must not be misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any -* source distribution. -*/ - -module dsfml.system.vector2; - -/** - * Vector2 is an utility class for manipulating 2 dimensional - * vectors. Template parameter defines the type of coordinates - * (integer, float, ...) - */ -struct Vector2(T) -{ - T x; - T y; - - /// negate the vector - Vector2 opUnary(string op : "-")() - { - return Vector2!(T)(-x, -y); - } - - /// dot product - T opBinary(string op : "*", U:Vector2)(U v) - { - return x*v.x + y*v.y; - } - - /// element-wise operations, +, -, - Vector2 opBinary(string op, U:Vector2)(U v) - if (op != "*") - { -// pragma(msg, "opBinary!"~op); - mixin("return Vector2!(T)( cast(T)(x " ~ op ~ " v.x), cast(T)(y " ~ op ~ " v.y) );"); - } - - /// operations with a scalar - Vector2 opBinary(string op)(int i) - { - mixin("return Vector2!(T) ( cast(T)(x " ~ op ~ " i), cast(T)(y " ~ op ~ " i) );"); - } - - /// element-wise assign operations, +=, -=, ... - Vector2 opOpAssign(string op, U:Vector2)(U v) - { - mixin("x " ~ op ~ " v.x;"); - mixin("y " ~ op ~ " v.y;"); - return this; - } - - - - /// (*=) overload - Vector2 opOpAssign(string op)(int i) - { - mixin("x "~op~" i;"); - mixin("y "~op~" i;"); - return this; - } - - /// - const bool opEquals(ref const(Vector2) other) - { - return (x == other.x) && (y == other.y); - } - - T max() - { - return (x>y) ? x : y; - } -} - -unittest -{ - Vector2f main = Vector2f(10f, 10f); - Vector2f other = Vector2f(10f, 10f); - Vector2f result; - - result = -main; - assert (result == Vector2f(-10.f, -10.f) ); - - result = main; - result += other; - assert (result == Vector2f(20.f, 20.f)); - - result = main; - result -= other; - assert (result == Vector2f(0.f, 0.f)); - - result = main + other; - assert (result == Vector2f(20.f, 20.f)); - - result = main - other; - assert (result == Vector2f(0.f, 0.f)); - - result = main * 10; - assert (result == Vector2f(100.f, 100.f)); - - result *= 2; - assert (result == Vector2f(200.f, 200.f)); - - result = main / 2; - assert (result == Vector2f(5.f, 5.f)); - - result = main; - result /= 2; - assert (result == Vector2f(5.f, 5.f)); -} - -/// Aliases -alias Vector2!(float) Vector2f; -/// ditto -alias Vector2!(int) Vector2i; -/// ditto -alias Vector2!(uint) Vector2ui; -/// ditto -alias Vector2!(ubyte) Vector2ub; \ No newline at end of file diff --git a/DSFML/import/dsfml/system/vector3.d b/DSFML/import/dsfml/system/vector3.d deleted file mode 100644 index fdae9bea..00000000 --- a/DSFML/import/dsfml/system/vector3.d +++ /dev/null @@ -1,156 +0,0 @@ -/* -* DSFML - SFML Library wrapper for the D programming language. -* Copyright (C) 2008 Julien Dagorn (sirjulio13@gmail.com) -* Copyright (C) 2010 Andreas Hollandt -* -* This software is provided 'as-is', without any express or -* implied warranty. In no event will the authors be held -* liable for any damages arising from the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute -* it freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; -* you must not claim that you wrote the original software. -* If you use this software in a product, an acknowledgment -* in the product documentation would be appreciated but -* is not required. -* -* 2. Altered source versions must be plainly marked as such, -* and must not be misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any -* source distribution. -*/ - -module dsfml.system.vector3; - -/** -* Vector3 is an utility class for manipulating 3 dimensional -* vectors. Template parameter defines the type of coordinates -* (integer, float, ...) -*/ -struct Vector3(T) -{ - T x; - T y; - T z; - - /// unary (-) overload - Vector3 opNeg() - { - return Vector3!(T)(-x, -y, -z); - } - - /// (+=) overload - Vector3 opAddAssign(Vector3 other) - { - x += other.x; - y += other.y; - z += other.z; - return this; - } - - /// (-=) overload - Vector3 opSubAssign(Vector3 other) - { - x -= other.x; - y -= other.y; - z -= other.z; - return this; - } - - /// (+) overload - Vector3 opAdd(Vector3 other) - { - return Vector3!(T)( (x + other.x), (y + other.y), (z + other.z) ); - } - - /// (-) overload - Vector3 opSub(Vector3 other) - { - return Vector3!(T) ( (x - other.x), (y - other.y), (z - other.z) ); - } - - /// (*) overload - Vector3 opMul(int i) - { - return Vector3!(T) ( (x * i), (y * i), (z * i) ); - } - - /// (*=) overload - Vector3 opMulAssign(int i) - { - x *= i; - y *= i; - z *= i; - return this; - } - - /// (/) overload - Vector3 opDiv(int i) - { - return Vector3!(T) ( (x / i), (y / i), (z / i) ); - } - - /// (/=) overload - Vector3 opDivAssign(int i) - { - x /= i; - y /= i; - z /= i; - return this; - } - - /// - const bool opEquals(ref const(Vector3) other) - { - return (x == other.x) && (y == other.y) && (z == other.z) ; - } -} - -version (UnitTest) -{ - unittest - { - Vector3f main = Vector3f(10f, 10f, 10.f); - Vector3f other = Vector3f(10f, 10f, 10.f); - Vector3f result; - - result = -main; - assert (result == Vector3f(-10.f, -10.f, -10.f) ); - - result = main; - result += other; - assert (result == Vector3f(20.f, 20.f, 20.f)); - - result = main; - result -= other; - assert (result == Vector3f(0.f, 0.f, 0.f)); - - result = main + other; - assert (result == Vector3f(20.f, 20.f, 20.f)); - - result = main - other; - assert (result == Vector3f(0.f, 0.f, 0.f)); - - result = main * 10; - assert (result == Vector3f(100.f, 100.f, 100.f)); - - result *= 2; - assert (result == Vector3f(200.f, 200.f, 200.f)); - - result = main / 2; - assert (result == Vector3f(5.f, 5.f, 5.f)); - - result = main; - result /= 2; - assert (result == Vector3f(5.f, 5.f, 5.f)); - } -} - -/// Aliases -alias Vector3!(float) Vector3f; -/// ditto -alias Vector3!(int) Vector3i;