/*==LICENSE==* CyanWorlds.com Engine - MMOG client, server and tools Copyright (C) 2011 Cyan Worlds, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . You can contact Cyan Worlds, Inc. by email legal@cyan.com or by snail mail at: Cyan Worlds, Inc. 14617 N Newport Hwy Mead, WA 99021 *==LICENSE==*/ #ifndef hsGGeometry3Defined #define hsGGeometry3Defined #include "hsTypes.h" struct hsVector3; struct hsPoint3; struct hsScalarTriple; class hsStream; /* If value is already close to hsScalar1, then this is a good approx. of 1/sqrt(value) */ static inline hsScalar hsInvSqrt(hsScalar value) { hsScalar guess; hsScalar threeOverTwo = hsScalar1 + hsScalarHalf; value = hsScalarDiv2(value); guess = threeOverTwo - value; // with initial guess = 1.0 // repeat this line for better approx guess = hsScalarMul(guess, threeOverTwo - hsScalarMul(hsScalarMul(value, guess), guess)); guess = hsScalarMul(guess, threeOverTwo - hsScalarMul(hsScalarMul(value, guess), guess)); return guess; } ///////////////////////////////////////////////////////////////////////////////////////////// struct hsScalarTriple { //protected: // hsScalarTriple() : fX(privateData[0]), fY(privateData[1]), fZ(privateData[2]) {} // hsScalarTriple(hsScalar x, hsScalar y, hsScalar z) // : fX(privateData[0]), fY(privateData[1]), fZ(privateData[2]) { fX = x, fY = y, fZ = z; } // // union { // u_long128 privateTemp; // hsScalar privateData[4]; // }; //public: // // int operator=(const hsScalarTriple& o) { privateTemp = o.privateTemp; } // hsScalarTriple(const hsScalarTriple& o) : fX(privateData[0]), fY(privateData[1]), fZ(privateData[2]) // { *this = o; } // // hsScalar& fX; // hsScalar& fY; // hsScalar& fZ; protected: hsScalarTriple() {} hsScalarTriple(hsScalar x, hsScalar y, hsScalar z) : fX(x), fY(y), fZ(z) {} public: hsScalar fX, fY, fZ; hsScalarTriple* Set(hsScalar x, hsScalar y, hsScalar z) { fX= x; fY = y; fZ = z; return this;} hsScalarTriple* Set(const hsScalarTriple *p) { fX = p->fX; fY = p->fY; fZ = p->fZ; return this;} hsScalar InnerProduct(const hsScalarTriple &p) const; hsScalar InnerProduct(const hsScalarTriple *p) const; // hsScalarTriple LERP(hsScalarTriple &other, hsScalar t); #if HS_SCALAR_IS_FIXED hsScalar Magnitude() const; hsScalar MagnitudeSquared() const; #else hsScalar Magnitude() const { return hsSquareRoot(MagnitudeSquared()); } hsScalar MagnitudeSquared() const { return (fX * fX + fY * fY + fZ * fZ); } #endif hsBool IsEmpty() const { return fX == 0 && fY == 0 && fZ == 0; } hsScalar operator[](int i) const; hsScalar& operator[](int i); void Read(hsStream *stream); void Write(hsStream *stream) const; }; /////////////////////////////////////////////////////////////////////////// inline hsScalar& hsScalarTriple::operator[] (int i) { hsAssert(i >=0 && i <3, "Bad index for hsScalarTriple::operator[]"); return *(&fX + i); } inline hsScalar hsScalarTriple::operator[] (int i) const { hsAssert(i >=0 && i <3, "Bad index for hsScalarTriple::operator[]"); return *(&fX + i); } inline hsScalar hsScalarTriple::InnerProduct(const hsScalarTriple &p) const { hsScalar tmp = fX*p.fX; tmp += fY*p.fY; tmp += fZ*p.fZ; return tmp; } inline hsScalar hsScalarTriple::InnerProduct(const hsScalarTriple *p) const { hsScalar tmp = fX*p->fX; tmp += fY*p->fY; tmp += fZ*p->fZ; return tmp; } //inline hsScalarTriple hsScalarTriple::LERP(hsScalarTriple &other, hsScalar t) //{ // hsScalarTriple p = other - this; // p = p / t; // return this + p; //} ///////////////////////////////////////////////////////////////////////////////////////////// struct hsPoint3 : public hsScalarTriple { hsPoint3() {}; hsPoint3(hsScalar x, hsScalar y, hsScalar z) : hsScalarTriple(x,y,z) {} explicit hsPoint3(const hsScalarTriple& p) : hsScalarTriple(p) {} hsPoint3* Set(hsScalar x, hsScalar y, hsScalar z) { return (hsPoint3*)this->hsScalarTriple::Set(x,y,z);} hsPoint3* Set(const hsScalarTriple* p) { return (hsPoint3*)this->hsScalarTriple::Set(p) ;} friend inline hsPoint3 operator+(const hsPoint3& s, const hsPoint3& t); friend inline hsPoint3 operator+(const hsPoint3& s, const hsVector3& t); friend inline hsPoint3 operator-(const hsPoint3& s, const hsPoint3& t); friend inline hsPoint3 operator-(const hsPoint3& s); friend inline hsPoint3 operator*(const hsScalar& s, const hsPoint3& t); friend inline hsPoint3 operator*(const hsPoint3& t, const hsScalar& s); friend inline hsPoint3 operator/(const hsPoint3& t, const hsScalar& s); hsBool operator==(const hsPoint3& ss) const { return (ss.fX == fX && ss.fY == fY && ss.fZ == fZ); } hsBool operator!=(const hsPoint3& ss) const { return !(*this == ss); } hsPoint3 &operator+=(const hsScalarTriple &s) { fX += s.fX; fY += s.fY; fZ += s.fZ; return *this; } hsPoint3 &operator*=(const hsScalar s) { fX *= s; fY *= s; fZ *= s; return *this; } }; ///////////////////////////////////////////////////////////////////////////////////////////// struct hsVector3 : public hsScalarTriple { hsVector3() {}; hsVector3(hsScalar x, hsScalar y, hsScalar z) : hsScalarTriple(x,y,z) {} explicit hsVector3(const hsScalarTriple& p) : hsScalarTriple(p) { } hsVector3(const hsPoint3 *p1, const hsPoint3 *p2) { fX = p1->fX - p2->fX, fY= p1->fY - p2->fY, fZ = p1->fZ - p2->fZ; } hsVector3* Set(hsScalar x, hsScalar y, hsScalar z) { return (hsVector3*)hsScalarTriple::Set(x,y,z); } hsVector3* Set(const hsScalarTriple* p) { return (hsVector3*)hsScalarTriple::Set(p) ;} hsVector3* Set(const hsScalarTriple* p1, const hsScalarTriple* p2) { return Set(p1->fX-p2->fX,p1->fY-p2->fY,p1->fZ-p2->fZ);} void Normalize() { #if HS_BUILD_FOR_PS2 hsScalar length = this->Magnitude(); hsIfDebugMessage(length == 0, "Err: Normalizing hsVector3 of length 0", 0); if (length == 0) return; NormalizeVU0(length, (MATRIX4)this); #else hsScalar length = this->Magnitude(); // hsIfDebugMessage(length == 0, "Err: Normalizing hsVector3 of length 0", 0); if (length == 0) return; hsScalar invMag = hsScalarInvert(length); fX = hsScalarMul(fX, invMag); fY = hsScalarMul(fY, invMag); fZ = hsScalarMul(fZ, invMag); #endif } inline void Renormalize() // if the vector is already close to unit length { hsScalar mag2 = *this * *this; hsIfDebugMessage(mag2 == 0, "Err: Renormalizing hsVector3 of length 0", 0); if (mag2 == 0) return; hsScalar invMag = hsInvSqrt(mag2); fX = hsScalarMul(fX, invMag); fY = hsScalarMul(fY, invMag); fZ = hsScalarMul(fZ, invMag); } // hsVector3 &Sub(const hsPoint3& s, const hsPoint3& t) // { Set(s.fX - t.fX, s.fY - t.fY, s.fZ - t.fZ); // return *this; }; friend inline hsVector3 operator+(const hsVector3& s, const hsVector3& t); friend inline hsVector3 operator-(const hsVector3& s, const hsVector3& t); friend inline hsVector3 operator-(const hsVector3& s); friend inline hsVector3 operator*(const hsScalar& s, const hsVector3& t); friend inline hsVector3 operator*(const hsVector3& t, const hsScalar& s); friend inline hsVector3 operator/(const hsVector3& t, const hsScalar& s); friend inline hsScalar operator*(const hsVector3& t, const hsVector3& s); friend hsVector3 operator%(const hsVector3& t, const hsVector3& s); #if 0 // Havok reeks friend hsBool32 operator==(const hsVector3& s, const hsVector3& t) { return (s.fX == t.fX && s.fY == t.fY && s.fZ == t.fZ); } #else // Havok reeks hsBool operator==(const hsVector3& ss) const { return (ss.fX == fX && ss.fY == fY && ss.fZ == fZ); } #endif // Havok reeks hsVector3 &operator+=(const hsScalarTriple &s) { fX += s.fX; fY += s.fY; fZ += s.fZ; return *this; } hsVector3 &operator-=(const hsScalarTriple &s) { fX -= s.fX; fY -= s.fY; fZ -= s.fZ; return *this; } hsVector3 &operator*=(const hsScalar s) { fX *= s; fY *= s; fZ *= s; return *this; } hsVector3 &operator/=(const hsScalar s) { fX /= s; fY /= s; fZ /= s; return *this; } }; struct hsPoint4 { hsScalar fX, fY, fZ, fW; hsPoint4() {} hsPoint4(hsScalar x, hsScalar y, hsScalar z, hsScalar w) : fX(x), fY(y), fZ(z), fW(w) {} hsScalar& operator[](int i); hsScalar operator[](int i) const; hsPoint4& operator=(const hsPoint3&p) { Set(p.fX, p.fY, p.fZ, hsScalar1); return *this; } hsPoint4* Set(hsScalar x, hsScalar y, hsScalar z, hsScalar w) { fX = x; fY = y; fZ = z; fW = w; return this; } }; inline hsVector3 operator+(const hsVector3& s, const hsVector3& t) { hsVector3 result; return *result.Set(s.fX + t.fX, s.fY + t.fY, s.fZ + t.fZ); } inline hsVector3 operator-(const hsVector3& s, const hsVector3& t) { hsVector3 result; return *result.Set(s.fX - t.fX, s.fY - t.fY, s.fZ - t.fZ); } // unary minus inline hsVector3 operator-(const hsVector3& s) { hsVector3 result; return *result.Set(-s.fX, -s.fY, -s.fZ); } inline hsVector3 operator*(const hsVector3& s, const hsScalar& t) { hsVector3 result; return *result.Set(hsScalarMul(s.fX, t), hsScalarMul(s.fY, t), hsScalarMul(s.fZ, t)); } inline hsVector3 operator/(const hsVector3& s, const hsScalar& t) { hsVector3 result; return *result.Set(hsScalarDiv(s.fX, t), hsScalarDiv(s.fY, t), hsScalarDiv(s.fZ, t)); } inline hsVector3 operator*(const hsScalar& t, const hsVector3& s) { hsVector3 result; return *result.Set(hsScalarMul(s.fX, t), hsScalarMul(s.fY, t), hsScalarMul(s.fZ, t)); } inline hsScalar operator*(const hsVector3& t, const hsVector3& s) { return hsScalarMul(t.fX, s.fX) + hsScalarMul(t.fY, s.fY) + hsScalarMul(t.fZ, s.fZ); } //////////////////////////////////////////////////////////////////////////// inline hsPoint3 operator+(const hsPoint3& s, const hsPoint3& t) { hsPoint3 result; return *result.Set(s.fX + t.fX, s.fY + t.fY, s.fZ + t.fZ); } inline hsPoint3 operator+(const hsPoint3& s, const hsVector3& t) { hsPoint3 result; return *result.Set(s.fX + t.fX, s.fY + t.fY, s.fZ + t.fZ); } inline hsPoint3 operator-(const hsPoint3& s, const hsPoint3& t) { hsPoint3 result; return *result.Set(s.fX - t.fX, s.fY - t.fY, s.fZ - t.fZ); } // unary - inline hsPoint3 operator-(const hsPoint3& s) { hsPoint3 result; return *result.Set(-s.fX, -s.fY, -s.fZ); } inline hsPoint3 operator-(const hsPoint3& s, const hsVector3& t) { hsPoint3 result; return *result.Set(s.fX - t.fX, s.fY - t.fY, s.fZ - t.fZ); } inline hsPoint3 operator*(const hsPoint3& s, const hsScalar& t) { hsPoint3 result; return *result.Set(hsScalarMul(s.fX, t), hsScalarMul(s.fY, t), hsScalarMul(s.fZ, t)); } inline hsPoint3 operator/(const hsPoint3& s, const hsScalar& t) { hsPoint3 result; return *result.Set(hsScalarDiv(s.fX, t), hsScalarDiv(s.fY, t), hsScalarDiv(s.fZ, t)); } inline hsPoint3 operator*(const hsScalar& t, const hsPoint3& s) { hsPoint3 result; return *result.Set(hsScalarMul(s.fX, t), hsScalarMul(s.fY, t), hsScalarMul(s.fZ, t)); } inline hsScalar hsPoint4::operator[] (int i) const { hsAssert(i >=0 && i <4, "Bad index for hsPoint4::operator[]"); return *(&fX + i); } inline hsScalar& hsPoint4::operator[] (int i) { hsAssert(i >=0 && i <4, "Bad index for hsPoint4::operator[]"); return *(&fX + i); } typedef hsPoint3 hsGUv; struct hsPointNorm { hsPoint3 fPos; hsVector3 fNorm; void Read(hsStream* s) { fPos.Read(s); fNorm.Read(s); } void Write(hsStream* s) const { fPos.Write(s); fNorm.Write(s); } }; struct hsPlane3 { hsVector3 fN; hsScalar fD; hsPlane3() { } hsPlane3(const hsVector3* nrml, hsScalar d) { fN = *nrml; fD=d; } hsPlane3(const hsPoint3* pt, const hsVector3* nrml) { fN = *nrml; fD = -pt->InnerProduct(nrml); } // create plane from a triangle (assumes clockwise winding of vertices) hsPlane3(const hsPoint3* pt1, const hsPoint3* pt2, const hsPoint3* pt3); hsVector3 GetNormal() const { return fN; } void Read(hsStream *stream); void Write(hsStream *stream) const; }; #endif