// Copyright (C) 2012 Rémi Bèges - Jérôme Leclercq // This file is part of the "Nazara Engine - Mathematics module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include #include #include #include #include ///FIXME: Les calculs effectués ici sont probablements tous faux, la composante W étant spéciale dans le monde de la 3D #define F(a) static_cast(a) template NzVector4::NzVector4(T X, T Y, T Z, T W) { Set(X, Y, Z, W); } template NzVector4::NzVector4(T scale) { Set(scale); } template NzVector4::NzVector4(const T vec[4]) { Set(vec); } template NzVector4::NzVector4(const NzVector3& vec, T W) { Set(vec, W); } template template NzVector4::NzVector4(const NzVector4& vec) { Set(vec); } template T NzVector4::AbsDotProduct(const NzVector4& vec) const { return std::fabs(x * vec.x) + std::fabs(y * vec.y) + std::fabs(z * vec.z) + std::fabs(w * vec.w); } template<> inline int NzVector4::AbsDotProduct(const NzVector4& vec) const { return std::labs(x * vec.x) + std::labs(y * vec.y) + std::labs(z * vec.z) + std::labs(w * vec.w); } template<> inline unsigned int NzVector4::AbsDotProduct(const NzVector4& vec) const { return std::labs(x * vec.x) + std::labs(y * vec.y) + std::labs(z * vec.z) + std::labs(w * vec.w); } template T NzVector4::DotProduct(const NzVector4& vec) const { return x*vec.x + y*vec.y + z*vec.z + w*vec.w; } template NzVector4& NzVector4::MakeUnitX() { return Set(F(1.0), F(0.0), F(0.0), F(1.0)); } template NzVector4& NzVector4::MakeUnitY() { return Set(F(0.0), F(1.0), F(0.0), F(1.0)); } template NzVector4& NzVector4::MakeUnitZ() { return Set(F(0.0), F(0.0), F(1.0), F(1.0)); } template NzVector4& NzVector4::MakeZero() { return Set(F(0.0), F(0.0), F(0.0), F(0.0)); } template NzVector4& NzVector4::Maximize(const NzVector4& vec) { if (vec.x > x) x = vec.x; if (vec.y > y) y = vec.y; if (vec.z > z) z = vec.z; if (vec.w > w) w = vec.w; return *this; } template NzVector4& NzVector4::Minimize(const NzVector4& vec) { if (vec.x < x) x = vec.x; if (vec.y < y) y = vec.y; if (vec.z < z) z = vec.z; if (vec.w < w) w = vec.w; return *this; } template NzVector4& NzVector4::Normalize(T* length) { x /= w; y /= w; z /= w; w = F(1.0); if (length) *length = w; return *this; } template NzVector4& NzVector4::Set(T X, T Y, T Z, T W) { w = W; x = X; y = Y; z = Z; return *this; } template NzVector4& NzVector4::Set(T scale) { w = scale; x = scale; y = scale; z = scale; return *this; } template NzVector4& NzVector4::Set(const T vec[4]) { std::memcpy(&x, vec, 4*sizeof(T)); return *this; } template NzVector4& NzVector4::Set(const NzVector3& vec, T W) { x = vec.x; y = vec.y; z = vec.z; w = W; return *this; } template template NzVector4& NzVector4::Set(const NzVector4& vec) { w = F(vec.w); x = F(vec.x); y = F(vec.y); z = F(vec.z); return *this; } template NzString NzVector4::ToString() const { NzStringStream ss; return ss << "Vector4(" << x << ", " << y << ", " << z << ", " << w << ')'; } template NzVector4::operator NzString() const { return ToString(); } template NzVector4::operator T*() { return &x; } template NzVector4::operator const T*() const { return &x; } template T& NzVector4::operator[](unsigned int i) { #if NAZARA_MATH_SAFE if (i >= 4) { NzStringStream ss; ss << "Index out of range: (" << i << " >= 4)"; NazaraError(ss); throw std::domain_error(ss.ToString()); } #endif return *(&x+i); } template T NzVector4::operator[](unsigned int i) const { #if NAZARA_MATH_SAFE if (i >= 4) { NzStringStream ss; ss << "Index out of range: (" << i << " >= 4)"; NazaraError(ss); throw std::domain_error(ss.ToString()); } #endif return *(&x+i); } template const NzVector4& NzVector4::operator+() const { return *this; } template NzVector4 NzVector4::operator-() const { return NzVector4(-x, -y, -z, -w); } template NzVector4 NzVector4::operator+(const NzVector4& vec) const { return NzVector4(x + vec.x, y + vec.y, z + vec.z, w + vec.w); } template NzVector4 NzVector4::operator-(const NzVector4& vec) const { return NzVector4(x - vec.x, y - vec.y, z - vec.z, w - vec.w); } template NzVector4 NzVector4::operator*(const NzVector4& vec) const { return NzVector4(x * vec.x, y * vec.y, z * vec.z, w * vec.w); } template NzVector4 NzVector4::operator*(T scale) const { return NzVector4(x * scale, y * scale, z * scale, w * scale); } template NzVector4 NzVector4::operator/(const NzVector4& vec) const { #if NAZARA_MATH_SAFE if (NzNumberEquals(vec.x, F(0.0)) || NzNumberEquals(vec.y, F(0.0)) || NzNumberEquals(vec.z, F(0.0)) || NzNumberEquals(vec.w, F(0.0))) { NzString error("Division by zero"); NazaraError(error); throw std::domain_error(error); } #endif return NzVector4(x / vec.x, y / vec.y, z / vec.z, w / vec.w); } template NzVector4 NzVector4::operator/(T scale) const { #if NAZARA_MATH_SAFE if (NzNumberEquals(scale, F(0.0))) { NzString error("Division by zero"); NazaraError(error); throw std::domain_error(error); } #endif return NzVector4(x / scale, y / scale, z / scale, w / scale); } template NzVector4& NzVector4::operator+=(const NzVector4& vec) { x += vec.x; y += vec.y; z += vec.z; w += vec.w; return *this; } template NzVector4& NzVector4::operator-=(const NzVector4& vec) { x -= vec.x; y -= vec.y; z -= vec.z; w -= vec.w; return *this; } template NzVector4& NzVector4::operator*=(const NzVector4& vec) { x *= vec.x; y *= vec.y; z *= vec.z; w *= vec.w; return *this; } template NzVector4& NzVector4::operator*=(T scale) { x *= scale; y *= scale; z *= scale; w *= scale; return *this; } template NzVector4& NzVector4::operator/=(const NzVector4& vec) { #if NAZARA_MATH_SAFE if (NzNumberEquals(vec.x, F(0.0)) || NzNumberEquals(vec.y, F(0.0)) || NzNumberEquals(vec.z, F(0.0)) || NzNumberEquals(vec.w, F(0.0))) { NzString error("Division by zero"); NazaraError(error); throw std::domain_error(error); } #endif x /= vec.x; y /= vec.y; z /= vec.z; w /= vec.w; return *this; } template NzVector4& NzVector4::operator/=(T scale) { #if NAZARA_MATH_SAFE if (NzNumberEquals(scale, F(0.0))) { NzString error("Division by zero"); NazaraError(error); throw std::domain_error(error); } #endif x /= scale; y /= scale; z /= scale; w /= scale; return *this; } template bool NzVector4::operator==(const NzVector4& vec) const { return NzNumberEquals(x, vec.x) && NzNumberEquals(y, vec.y) && NzNumberEquals(z, vec.z) && NzNumberEquals(w, vec.w); } template bool NzVector4::operator!=(const NzVector4& vec) const { return !operator==(vec); } template bool NzVector4::operator<(const NzVector4& vec) const { if (x == vec.x) { if (y == vec.y) { if (z == vec.z) return w < vec.w; else return z < vec.z; } else return y < vec.y; } else return x < vec.x; } template bool NzVector4::operator<=(const NzVector4& vec) const { if (x == vec.x) { if (y == vec.y) { if (z == vec.z) return w <= vec.w; else return z < vec.z; } else return y < vec.y; } else return x < vec.x; } template bool NzVector3::operator>(const NzVector3& vec) const { return !operator<=(vec); } template bool NzVector3::operator>=(const NzVector3& vec) const { return !operator<(vec); } template NzVector4 NzVector4::UnitX() { NzVector4 vector; vector.MakeUnitX(); return vector; } template NzVector4 NzVector4::UnitY() { NzVector4 vector; vector.MakeUnitY(); return vector; } template NzVector4 NzVector4::UnitZ() { NzVector4 vector; vector.MakeUnitZ(); return vector; } template NzVector4 NzVector4::Zero() { NzVector4 vector; vector.MakeZero(); return vector; } template std::ostream& operator<<(std::ostream& out, const NzVector4& vec) { return out << vec.ToString(); } template NzVector4 operator*(T scale, const NzVector4& vec) { return NzVector4(scale * vec.x, scale * vec.y, scale * vec.z, scale * vec.w); } template NzVector4 operator/(T scale, const NzVector4& vec) { #if NAZARA_MATH_SAFE if (NzNumberEquals(vec.x, F(0.0)) || NzNumberEquals(vec.y, F(0.0)) || NzNumberEquals(vec.z, F(0.0)) || NzNumberEquals(vec.w, F(0.0))) { NzString error("Division by zero"); NazaraError(error); throw std::domain_error(error); } #endif return NzVector4(scale / vec.x, scale / vec.y, scale / vec.z, scale / vec.w); } #undef F #include