// Copyright (C) 2012 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 #define F(a) static_cast(a) template NzCube::NzCube(T X, T Y, T Z, T Width, T Height, T Depth) { Set(X, Y, Z, Width, Height, Depth); } template NzCube::NzCube(const NzRect& rect) { Set(rect); } template NzCube::NzCube(const NzVector3& vec1, const NzVector3& vec2) { Set(vec1, vec2); } template NzCube::NzCube(const T vec[6]) { Set(vec); } template template NzCube::NzCube(const NzCube& cube) { Set(cube); } template bool NzCube::Contains(T X, T Y, T Z) const { return X >= x && X < x+width && Y >= y && Y < y+height && Z >= z && Z < z+depth; } template bool NzCube::Contains(const NzVector3& point) const { return Contains(point.x, point.y, point.z); } template bool NzCube::Contains(const NzCube& cube) const { return Contains(cube.x, cube.y, cube.z) && Contains(cube.x + cube.width, cube.y + cube.height, cube.z + cube.depth); } template NzCube& NzCube::ExtendTo(T X, T Y, T Z) { width = std::max(x + width, X); height = std::max(y + height, Y); depth = std::max(z + depth, Z); x = std::min(x, X); y = std::min(y, Y); z = std::min(z, Z); width -= x; height -= y; depth -= z; return *this; } template NzCube& NzCube::ExtendTo(const NzVector3& point) { return ExtendTo(point.x, point.y, point.z); } template NzCube& NzCube::ExtendTo(const NzCube& cube) { width = std::max(x + width, cube.x + cube.width); height = std::max(y + height, cube.y + cube.height); depth = std::max(z + depth, cube.z + cube.depth); x = std::min(x, cube.x); y = std::min(y, cube.y); z = std::min(z, cube.z); width -= x; height -= y; depth -= z; return *this; } template NzVector3 NzCube::GetCorner(nzCorner corner) const { switch (corner) { case nzCorner_FarLeftBottom: return NzVector3f(x, y, z); case nzCorner_FarLeftTop: return NzVector3f(x, y + height, z); case nzCorner_FarRightBottom: return NzVector3f(x + width, y, z); case nzCorner_FarRightTop: return NzVector3f(x + width, y + height, z); case nzCorner_NearLeftBottom: return NzVector3f(x, y, z + depth); case nzCorner_NearLeftTop: return NzVector3f(x, y + height, z + depth); case nzCorner_NearRightBottom: return NzVector3f(x + width, y, z + depth); case nzCorner_NearRightTop: return NzVector3f(x + width, y + height, z + depth); } NazaraError("Corner not handled (0x" + NzString::Number(corner, 16) + ')'); return NzVector3f(); } template NzSphere NzCube::GetBoundingSphere() const { return NzSphere(GetCenter(), GetRadius()); } template NzVector3 NzCube::GetCenter() const { return GetPosition() + F(0.5)*GetSize(); } template NzVector3 NzCube::GetNegativeVertex(const NzVector3& normal) const { NzVector3 neg(GetPosition()); if (normal.x < F(0.0)) neg.x += width; if (normal.y < F(0.0)) neg.y += height; if (normal.z < F(0.0)) neg.z += depth; return neg; } template NzVector3 NzCube::GetPosition() const { return NzVector3(x, y, z); } template NzVector3 NzCube::GetPositiveVertex(const NzVector3& normal) const { NzVector3 pos(GetPosition()); if (normal.x > F(0.0)) pos.x += width; if (normal.y > F(0.0)) pos.y += height; if (normal.z > F(0.0)) pos.z += depth; return pos; } template T NzCube::GetRadius() const { return std::sqrt(GetSquaredRadius()); } template NzVector3 NzCube::GetSize() const { return NzVector3(width, height, depth); } template T NzCube::GetSquaredRadius() const { NzVector3 size(GetSize()); size *= F(0.5); // La taille étant relative à la position (minimum) du cube et non pas à son centre return size.GetSquaredLength(); } template bool NzCube::Intersect(const NzCube& cube, NzCube* intersection) const { T left = std::max(x, cube.x); T right = std::min(x + width, cube.x + cube.width); T top = std::max(y, cube.y); T bottom = std::min(y + height, cube.y + cube.height); T up = std::max(z, cube.z); T down = std::min(z + depth, cube.z + cube.depth); if (left < right && top < bottom && up < down) { if (intersection) { intersection->x = left; intersection->y = top; intersection->z = up; intersection->width = right - left; intersection->height = bottom - top; intersection->depth = down - up; } return true; } else return false; } template bool NzCube::IsValid() const { return width > F(0.0) && height > F(0.0) && depth > F(0.0); } template NzCube& NzCube::MakeZero() { x = F(0.0); y = F(0.0); z = F(0.0); width = F(0.0); height = F(0.0); depth = F(0.0); return *this; } template NzCube& NzCube::Set(T X, T Y, T Z, T Width, T Height, T Depth) { x = X; y = Y; z = Z; width = Width; height = Height; depth = Depth; return *this; } template NzCube& NzCube::Set(const T cube[6]) { x = cube[0]; y = cube[1]; z = cube[2]; width = cube[3]; height = cube[4]; depth = cube[5]; return *this; } template NzCube& NzCube::Set(const NzCube& cube) { std::memcpy(this, &cube, sizeof(NzCube)); return *this; } template NzCube& NzCube::Set(const NzRect& rect) { x = rect.x; y = rect.y; z = F(0.0); width = rect.width; height = rect.height; depth = F(1.0); return *this; } template NzCube& NzCube::Set(const NzVector3& vec1, const NzVector3& vec2) { x = std::min(vec1.x, vec2.x); y = std::min(vec1.y, vec2.y); z = std::min(vec1.z, vec2.z); width = (vec2.x > vec1.x) ? vec2.x-vec1.x : vec1.x-vec2.x; height = (vec2.y > vec1.y) ? vec2.y-vec1.y : vec1.y-vec2.y; depth = (vec2.z > vec1.z) ? vec2.z-vec1.z : vec1.z-vec2.z; return *this; } template template NzCube& NzCube::Set(const NzCube& cube) { x = F(cube.x); y = F(cube.y); z = F(cube.z); width = F(cube.width); height = F(cube.height); depth = F(cube.depth); return *this; } template NzString NzCube::ToString() const { NzStringStream ss; return ss << "Cube(" << x << ", " << y << ", " << z << ", " << width << ", " << height << ", " << depth << ')'; } template NzCube& NzCube::Transform(const NzMatrix4& matrix, bool applyTranslation) { NzVector3 center = matrix.Transform(GetCenter(), (applyTranslation) ? F(1.0) : F(0.0)); // Valeur multipliant la translation NzVector3 halfSize = GetSize() * F(0.5); halfSize.Set(std::fabs(matrix(0,0))*halfSize.x + std::fabs(matrix(1,0))*halfSize.y + std::fabs(matrix(2,0))*halfSize.z, std::fabs(matrix(0,1))*halfSize.x + std::fabs(matrix(1,1))*halfSize.y + std::fabs(matrix(2,1))*halfSize.z, std::fabs(matrix(0,2))*halfSize.x + std::fabs(matrix(1,2))*halfSize.y + std::fabs(matrix(2,2))*halfSize.z); return Set(center - halfSize, center + halfSize); } template T& NzCube::operator[](unsigned int i) { #if NAZARA_MATH_SAFE if (i >= 6) { NzStringStream ss; ss << "Index out of range: (" << i << " >= 6)"; NazaraError(ss); throw std::domain_error(ss.ToString()); } #endif return *(&x+i); } template T NzCube::operator[](unsigned int i) const { #if NAZARA_MATH_SAFE if (i >= 6) { NzStringStream ss; ss << "Index out of range: (" << i << " >= 6)"; NazaraError(ss); throw std::domain_error(ss.ToString()); } #endif return *(&x+i); } template NzCube NzCube::operator*(T scalar) const { return NzCube(x, y, z, width*scalar, height*scalar, depth*scalar); } template NzCube& NzCube::operator*=(T scalar) { width *= scalar; height *= scalar; depth *= scalar; } template bool NzCube::operator==(const NzCube& cube) const { return NzNumberEquals(x, cube.x) && NzNumberEquals(y, cube.y) && NzNumberEquals(z, cube.z) && NzNumberEquals(width, cube.width) && NzNumberEquals(height, cube.height) && NzNumberEquals(depth, cube.depth); } template bool NzCube::operator!=(const NzCube& cube) const { return !operator==(cube); } template NzCube NzCube::Lerp(const NzCube& from, const NzCube& to, T interpolation) { #ifdef NAZARA_DEBUG if (interpolation < F(0.0) || interpolation > F(1.0)) { NazaraError("Interpolation must be in range [0..1] (Got " + NzString::Number(interpolation) + ')'); return Zero(); } #endif NzCube cube; cube.x = NzLerp(from.x, to.x, interpolation); cube.y = NzLerp(from.y, to.y, interpolation); cube.z = NzLerp(from.z, to.z, interpolation); cube.width = NzLerp(from.width, to.width, interpolation); cube.height = NzLerp(from.height, to.height, interpolation); cube.depth = NzLerp(from.depth, to.depth, interpolation); return cube; } template NzCube NzCube::Zero() { NzCube cube; cube.MakeZero(); return cube; } template std::ostream& operator<<(std::ostream& out, const NzCube& cube) { return out << cube.ToString(); } #undef F #include