diff options
author | Brad Linden <brad@lindenlab.com> | 2024-05-23 11:31:19 -0700 |
---|---|---|
committer | Brad Linden <brad@lindenlab.com> | 2024-05-23 11:31:19 -0700 |
commit | a1f49564d670a2c41bfa25c833bba2564b9b7f48 (patch) | |
tree | 1d205e51bc37621916a17d459ad83782fe41f975 /indra/llmath | |
parent | 6af5db09faf5ea33a2d4c47b64e76f42edae178a (diff) | |
parent | 6377610f6587989c126b00f490dfc8d527a1c2ce (diff) |
Merge remote-tracking branch 'origin/DRTVWR-600-maint-A' into brad/merge-maint-a-to-dev
Diffstat (limited to 'indra/llmath')
97 files changed, 24583 insertions, 24583 deletions
diff --git a/indra/llmath/camera.h b/indra/llmath/camera.h index 26f3c3d19f..14a08c5985 100644 --- a/indra/llmath/camera.h +++ b/indra/llmath/camera.h @@ -1,25 +1,25 @@ -/** +/** * @file camera.h * @brief Legacy wrapper header. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ diff --git a/indra/llmath/coordframe.h b/indra/llmath/coordframe.h index 271bcb433c..e7395b1212 100644 --- a/indra/llmath/coordframe.h +++ b/indra/llmath/coordframe.h @@ -1,25 +1,25 @@ -/** +/** * @file coordframe.h * @brief Legacy wrapper header. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ diff --git a/indra/llmath/llbbox.cpp b/indra/llmath/llbbox.cpp index 395992e68f..fa1253e421 100644 --- a/indra/llmath/llbbox.cpp +++ b/indra/llmath/llbbox.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llbbox.cpp * @brief General purpose bounding box class (Not axis aligned) * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -34,145 +34,145 @@ void LLBBox::addPointLocal(const LLVector3& p) { - if (mEmpty) - { - mMinLocal = p; - mMaxLocal = p; - mEmpty = false; - } - else - { - mMinLocal.mV[VX] = llmin( p.mV[VX], mMinLocal.mV[VX] ); - mMinLocal.mV[VY] = llmin( p.mV[VY], mMinLocal.mV[VY] ); - mMinLocal.mV[VZ] = llmin( p.mV[VZ], mMinLocal.mV[VZ] ); - mMaxLocal.mV[VX] = llmax( p.mV[VX], mMaxLocal.mV[VX] ); - mMaxLocal.mV[VY] = llmax( p.mV[VY], mMaxLocal.mV[VY] ); - mMaxLocal.mV[VZ] = llmax( p.mV[VZ], mMaxLocal.mV[VZ] ); - } + if (mEmpty) + { + mMinLocal = p; + mMaxLocal = p; + mEmpty = false; + } + else + { + mMinLocal.mV[VX] = llmin( p.mV[VX], mMinLocal.mV[VX] ); + mMinLocal.mV[VY] = llmin( p.mV[VY], mMinLocal.mV[VY] ); + mMinLocal.mV[VZ] = llmin( p.mV[VZ], mMinLocal.mV[VZ] ); + mMaxLocal.mV[VX] = llmax( p.mV[VX], mMaxLocal.mV[VX] ); + mMaxLocal.mV[VY] = llmax( p.mV[VY], mMaxLocal.mV[VY] ); + mMaxLocal.mV[VZ] = llmax( p.mV[VZ], mMaxLocal.mV[VZ] ); + } } void LLBBox::addPointAgent( LLVector3 p) { - p -= mPosAgent; - p.rotVec( ~mRotation ); - addPointLocal( p ); + p -= mPosAgent; + p.rotVec( ~mRotation ); + addPointLocal( p ); } void LLBBox::addBBoxAgent(const LLBBox& b) { - if (mEmpty) - { - mPosAgent = b.mPosAgent; - mRotation = b.mRotation; - mMinLocal.clearVec(); - mMaxLocal.clearVec(); - } - LLVector3 vertex[8]; - vertex[0].setVec( b.mMinLocal.mV[VX], b.mMinLocal.mV[VY], b.mMinLocal.mV[VZ] ); - vertex[1].setVec( b.mMinLocal.mV[VX], b.mMinLocal.mV[VY], b.mMaxLocal.mV[VZ] ); - vertex[2].setVec( b.mMinLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMinLocal.mV[VZ] ); - vertex[3].setVec( b.mMinLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMaxLocal.mV[VZ] ); - vertex[4].setVec( b.mMaxLocal.mV[VX], b.mMinLocal.mV[VY], b.mMinLocal.mV[VZ] ); - vertex[5].setVec( b.mMaxLocal.mV[VX], b.mMinLocal.mV[VY], b.mMaxLocal.mV[VZ] ); - vertex[6].setVec( b.mMaxLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMinLocal.mV[VZ] ); - vertex[7].setVec( b.mMaxLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMaxLocal.mV[VZ] ); - - LLMatrix4 m( b.mRotation ); - m.translate( b.mPosAgent ); - m.translate( -mPosAgent ); - m.rotate( ~mRotation ); - - for( S32 i=0; i<8; i++ ) - { - addPointLocal( vertex[i] * m ); - } + if (mEmpty) + { + mPosAgent = b.mPosAgent; + mRotation = b.mRotation; + mMinLocal.clearVec(); + mMaxLocal.clearVec(); + } + LLVector3 vertex[8]; + vertex[0].setVec( b.mMinLocal.mV[VX], b.mMinLocal.mV[VY], b.mMinLocal.mV[VZ] ); + vertex[1].setVec( b.mMinLocal.mV[VX], b.mMinLocal.mV[VY], b.mMaxLocal.mV[VZ] ); + vertex[2].setVec( b.mMinLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMinLocal.mV[VZ] ); + vertex[3].setVec( b.mMinLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMaxLocal.mV[VZ] ); + vertex[4].setVec( b.mMaxLocal.mV[VX], b.mMinLocal.mV[VY], b.mMinLocal.mV[VZ] ); + vertex[5].setVec( b.mMaxLocal.mV[VX], b.mMinLocal.mV[VY], b.mMaxLocal.mV[VZ] ); + vertex[6].setVec( b.mMaxLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMinLocal.mV[VZ] ); + vertex[7].setVec( b.mMaxLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMaxLocal.mV[VZ] ); + + LLMatrix4 m( b.mRotation ); + m.translate( b.mPosAgent ); + m.translate( -mPosAgent ); + m.rotate( ~mRotation ); + + for( S32 i=0; i<8; i++ ) + { + addPointLocal( vertex[i] * m ); + } } LLBBox LLBBox::getAxisAligned() const { - // no rotation = axis aligned rotation - LLBBox aligned(mPosAgent, LLQuaternion(), LLVector3(), LLVector3()); + // no rotation = axis aligned rotation + LLBBox aligned(mPosAgent, LLQuaternion(), LLVector3(), LLVector3()); - // add the center point so that it's not empty - aligned.addPointAgent(mPosAgent); + // add the center point so that it's not empty + aligned.addPointAgent(mPosAgent); - // add our BBox - aligned.addBBoxAgent(*this); + // add our BBox + aligned.addBBoxAgent(*this); - return aligned; + return aligned; } void LLBBox::expand( F32 delta ) { - mMinLocal.mV[VX] -= delta; - mMinLocal.mV[VY] -= delta; - mMinLocal.mV[VZ] -= delta; - mMaxLocal.mV[VX] += delta; - mMaxLocal.mV[VY] += delta; - mMaxLocal.mV[VZ] += delta; + mMinLocal.mV[VX] -= delta; + mMinLocal.mV[VY] -= delta; + mMinLocal.mV[VZ] -= delta; + mMaxLocal.mV[VX] += delta; + mMaxLocal.mV[VY] += delta; + mMaxLocal.mV[VZ] += delta; } LLVector3 LLBBox::localToAgent(const LLVector3& v) const { - LLMatrix4 m( mRotation ); - m.translate( mPosAgent ); - return v * m; + LLMatrix4 m( mRotation ); + m.translate( mPosAgent ); + return v * m; } LLVector3 LLBBox::agentToLocal(const LLVector3& v) const { - LLMatrix4 m; - m.translate( -mPosAgent ); - m.rotate( ~mRotation ); // inverse rotation - return v * m; + LLMatrix4 m; + m.translate( -mPosAgent ); + m.rotate( ~mRotation ); // inverse rotation + return v * m; } LLVector3 LLBBox::localToAgentBasis(const LLVector3& v) const { - LLMatrix4 m( mRotation ); - return v * m; + LLMatrix4 m( mRotation ); + return v * m; } LLVector3 LLBBox::agentToLocalBasis(const LLVector3& v) const { - LLMatrix4 m( ~mRotation ); // inverse rotation - return v * m; + LLMatrix4 m( ~mRotation ); // inverse rotation + return v * m; } bool LLBBox::containsPointLocal(const LLVector3& p) const { - if ( (p.mV[VX] < mMinLocal.mV[VX]) - ||(p.mV[VX] > mMaxLocal.mV[VX]) - ||(p.mV[VY] < mMinLocal.mV[VY]) - ||(p.mV[VY] > mMaxLocal.mV[VY]) - ||(p.mV[VZ] < mMinLocal.mV[VZ]) - ||(p.mV[VZ] > mMaxLocal.mV[VZ])) - { - return false; - } - return true; + if ( (p.mV[VX] < mMinLocal.mV[VX]) + ||(p.mV[VX] > mMaxLocal.mV[VX]) + ||(p.mV[VY] < mMinLocal.mV[VY]) + ||(p.mV[VY] > mMaxLocal.mV[VY]) + ||(p.mV[VZ] < mMinLocal.mV[VZ]) + ||(p.mV[VZ] > mMaxLocal.mV[VZ])) + { + return false; + } + return true; } bool LLBBox::containsPointAgent(const LLVector3& p) const { - LLVector3 point_local = agentToLocal(p); - return containsPointLocal(point_local); + LLVector3 point_local = agentToLocal(p); + return containsPointLocal(point_local); } LLVector3 LLBBox::getMinAgent() const { - return localToAgent(mMinLocal); + return localToAgent(mMinLocal); } LLVector3 LLBBox::getMaxAgent() const { - return localToAgent(mMaxLocal); + return localToAgent(mMaxLocal); } /* LLBBox operator*(const LLBBox &a, const LLMatrix4 &b) { - return LLBBox( a.mMin * b, a.mMax * b ); + return LLBBox( a.mMin * b, a.mMax * b ); } */ diff --git a/indra/llmath/llbbox.h b/indra/llmath/llbbox.h index 8ae5f221f7..5617eaebde 100644 --- a/indra/llmath/llbbox.h +++ b/indra/llmath/llbbox.h @@ -1,25 +1,25 @@ -/** +/** * @file llbbox.h * @brief General purpose bounding box class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -31,68 +31,68 @@ #include "llquaternion.h" // Note: "local space" for an LLBBox is defined relative to agent space in terms of -// a translation followed by a rotation. There is no scale term since the LLBBox's min and +// a translation followed by a rotation. There is no scale term since the LLBBox's min and // max are not necessarily symetrical and define their own extents. class LLBBox { public: - LLBBox() {mEmpty = true;} - LLBBox( const LLVector3& pos_agent, - const LLQuaternion& rot, - const LLVector3& min_local, - const LLVector3& max_local ) - : - mMinLocal( min_local ), mMaxLocal( max_local ), mPosAgent(pos_agent), mRotation( rot), mEmpty( true ) - {} + LLBBox() {mEmpty = true;} + LLBBox( const LLVector3& pos_agent, + const LLQuaternion& rot, + const LLVector3& min_local, + const LLVector3& max_local ) + : + mMinLocal( min_local ), mMaxLocal( max_local ), mPosAgent(pos_agent), mRotation( rot), mEmpty( true ) + {} + + // Default copy constructor is OK. - // Default copy constructor is OK. + const LLVector3& getPositionAgent() const { return mPosAgent; } + const LLQuaternion& getRotation() const { return mRotation; } - const LLVector3& getPositionAgent() const { return mPosAgent; } - const LLQuaternion& getRotation() const { return mRotation; } + LLVector3 getMinAgent() const; + const LLVector3& getMinLocal() const { return mMinLocal; } + void setMinLocal( const LLVector3& min ) { mMinLocal = min; } - LLVector3 getMinAgent() const; - const LLVector3& getMinLocal() const { return mMinLocal; } - void setMinLocal( const LLVector3& min ) { mMinLocal = min; } + LLVector3 getMaxAgent() const; + const LLVector3& getMaxLocal() const { return mMaxLocal; } + void setMaxLocal( const LLVector3& max ) { mMaxLocal = max; } - LLVector3 getMaxAgent() const; - const LLVector3& getMaxLocal() const { return mMaxLocal; } - void setMaxLocal( const LLVector3& max ) { mMaxLocal = max; } + LLVector3 getCenterLocal() const { return (mMaxLocal - mMinLocal) * 0.5f + mMinLocal; } + LLVector3 getCenterAgent() const { return localToAgent( getCenterLocal() ); } - LLVector3 getCenterLocal() const { return (mMaxLocal - mMinLocal) * 0.5f + mMinLocal; } - LLVector3 getCenterAgent() const { return localToAgent( getCenterLocal() ); } + LLVector3 getExtentLocal() const { return mMaxLocal - mMinLocal; } - LLVector3 getExtentLocal() const { return mMaxLocal - mMinLocal; } + bool containsPointLocal(const LLVector3& p) const; + bool containsPointAgent(const LLVector3& p) const; - bool containsPointLocal(const LLVector3& p) const; - bool containsPointAgent(const LLVector3& p) const; + void addPointAgent(LLVector3 p); + void addBBoxAgent(const LLBBox& b); - void addPointAgent(LLVector3 p); - void addBBoxAgent(const LLBBox& b); - - void addPointLocal(const LLVector3& p); - void addBBoxLocal(const LLBBox& b) { addPointLocal( b.mMinLocal ); addPointLocal( b.mMaxLocal ); } + void addPointLocal(const LLVector3& p); + void addBBoxLocal(const LLBBox& b) { addPointLocal( b.mMinLocal ); addPointLocal( b.mMaxLocal ); } - void expand( F32 delta ); + void expand( F32 delta ); - LLVector3 localToAgent( const LLVector3& v ) const; - LLVector3 agentToLocal( const LLVector3& v ) const; + LLVector3 localToAgent( const LLVector3& v ) const; + LLVector3 agentToLocal( const LLVector3& v ) const; - // Changes rotation but not position - LLVector3 localToAgentBasis(const LLVector3& v) const; - LLVector3 agentToLocalBasis(const LLVector3& v) const; + // Changes rotation but not position + LLVector3 localToAgentBasis(const LLVector3& v) const; + LLVector3 agentToLocalBasis(const LLVector3& v) const; - // Get the smallest possible axis aligned bbox that contains this bbox - LLBBox getAxisAligned() const; + // Get the smallest possible axis aligned bbox that contains this bbox + LLBBox getAxisAligned() const; -// friend LLBBox operator*(const LLBBox& a, const LLMatrix4& b); +// friend LLBBox operator*(const LLBBox& a, const LLMatrix4& b); private: - LLVector3 mMinLocal; - LLVector3 mMaxLocal; - LLVector3 mPosAgent; // Position relative to Agent's Region - LLQuaternion mRotation; - bool mEmpty; // Nothing has been added to this bbox yet + LLVector3 mMinLocal; + LLVector3 mMaxLocal; + LLVector3 mPosAgent; // Position relative to Agent's Region + LLQuaternion mRotation; + bool mEmpty; // Nothing has been added to this bbox yet }; //LLBBox operator*(const LLBBox &a, const LLMatrix4 &b); diff --git a/indra/llmath/llbboxlocal.cpp b/indra/llmath/llbboxlocal.cpp index bf0c1a7b93..cbb7a1b481 100644 --- a/indra/llmath/llbboxlocal.cpp +++ b/indra/llmath/llbboxlocal.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llbboxlocal.cpp * @brief General purpose bounding box class (Not axis aligned). * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -31,25 +31,25 @@ void LLBBoxLocal::addPoint(const LLVector3& p) { - mMin.mV[VX] = llmin( p.mV[VX], mMin.mV[VX] ); - mMin.mV[VY] = llmin( p.mV[VY], mMin.mV[VY] ); - mMin.mV[VZ] = llmin( p.mV[VZ], mMin.mV[VZ] ); - mMax.mV[VX] = llmax( p.mV[VX], mMax.mV[VX] ); - mMax.mV[VY] = llmax( p.mV[VY], mMax.mV[VY] ); - mMax.mV[VZ] = llmax( p.mV[VZ], mMax.mV[VZ] ); + mMin.mV[VX] = llmin( p.mV[VX], mMin.mV[VX] ); + mMin.mV[VY] = llmin( p.mV[VY], mMin.mV[VY] ); + mMin.mV[VZ] = llmin( p.mV[VZ], mMin.mV[VZ] ); + mMax.mV[VX] = llmax( p.mV[VX], mMax.mV[VX] ); + mMax.mV[VY] = llmax( p.mV[VY], mMax.mV[VY] ); + mMax.mV[VZ] = llmax( p.mV[VZ], mMax.mV[VZ] ); } void LLBBoxLocal::expand( F32 delta ) { - mMin.mV[VX] -= delta; - mMin.mV[VY] -= delta; - mMin.mV[VZ] -= delta; - mMax.mV[VX] += delta; - mMax.mV[VY] += delta; - mMax.mV[VZ] += delta; + mMin.mV[VX] -= delta; + mMin.mV[VY] -= delta; + mMin.mV[VZ] -= delta; + mMax.mV[VX] += delta; + mMax.mV[VY] += delta; + mMax.mV[VZ] += delta; } LLBBoxLocal operator*(const LLBBoxLocal &a, const LLMatrix4 &b) { - return LLBBoxLocal( a.mMin * b, a.mMax * b ); + return LLBBoxLocal( a.mMin * b, a.mMax * b ); } diff --git a/indra/llmath/llbboxlocal.h b/indra/llmath/llbboxlocal.h index defb899248..e215e55460 100644 --- a/indra/llmath/llbboxlocal.h +++ b/indra/llmath/llbboxlocal.h @@ -1,25 +1,25 @@ -/** +/** * @file llbboxlocal.h * @brief General purpose bounding box class. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -34,29 +34,29 @@ class LLMatrix4; class LLBBoxLocal { public: - LLBBoxLocal() {} - LLBBoxLocal( const LLVector3& min, const LLVector3& max ) : mMin( min ), mMax( max ) {} - // Default copy constructor is OK. + LLBBoxLocal() {} + LLBBoxLocal( const LLVector3& min, const LLVector3& max ) : mMin( min ), mMax( max ) {} + // Default copy constructor is OK. - const LLVector3& getMin() const { return mMin; } - void setMin( const LLVector3& min ) { mMin = min; } + const LLVector3& getMin() const { return mMin; } + void setMin( const LLVector3& min ) { mMin = min; } - const LLVector3& getMax() const { return mMax; } - void setMax( const LLVector3& max ) { mMax = max; } + const LLVector3& getMax() const { return mMax; } + void setMax( const LLVector3& max ) { mMax = max; } - LLVector3 getCenter() const { return (mMax - mMin) * 0.5f + mMin; } - LLVector3 getExtent() const { return mMax - mMin; } + LLVector3 getCenter() const { return (mMax - mMin) * 0.5f + mMin; } + LLVector3 getExtent() const { return mMax - mMin; } - void addPoint(const LLVector3& p); - void addBBox(const LLBBoxLocal& b) { addPoint( b.mMin ); addPoint( b.mMax ); } + void addPoint(const LLVector3& p); + void addBBox(const LLBBoxLocal& b) { addPoint( b.mMin ); addPoint( b.mMax ); } - void expand( F32 delta ); + void expand( F32 delta ); - friend LLBBoxLocal operator*(const LLBBoxLocal& a, const LLMatrix4& b); + friend LLBBoxLocal operator*(const LLBBoxLocal& a, const LLMatrix4& b); private: - LLVector3 mMin; - LLVector3 mMax; + LLVector3 mMin; + LLVector3 mMax; }; LLBBoxLocal operator*(const LLBBoxLocal &a, const LLMatrix4 &b); diff --git a/indra/llmath/llcalc.cpp b/indra/llmath/llcalc.cpp index edc6986cc9..e060b5df58 100644 --- a/indra/llmath/llcalc.cpp +++ b/indra/llmath/llcalc.cpp @@ -4,21 +4,21 @@ * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2008, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ * @@ -71,16 +71,16 @@ LLCalc* LLCalc::sInstance = NULL; LLCalc::LLCalc() : mLastErrorPos(0) { - // Init table of constants - mConstants["PI"] = F_PI; - mConstants["TWO_PI"] = F_TWO_PI; - mConstants["PI_BY_TWO"] = F_PI_BY_TWO; - mConstants["SQRT_TWO_PI"] = F_SQRT_TWO_PI; - mConstants["SQRT2"] = F_SQRT2; - mConstants["SQRT3"] = F_SQRT3; - mConstants["DEG_TO_RAD"] = DEG_TO_RAD; - mConstants["RAD_TO_DEG"] = RAD_TO_DEG; - mConstants["GRAVITY"] = GRAVITY; + // Init table of constants + mConstants["PI"] = F_PI; + mConstants["TWO_PI"] = F_TWO_PI; + mConstants["PI_BY_TWO"] = F_PI_BY_TWO; + mConstants["SQRT_TWO_PI"] = F_SQRT_TWO_PI; + mConstants["SQRT2"] = F_SQRT2; + mConstants["SQRT3"] = F_SQRT3; + mConstants["DEG_TO_RAD"] = DEG_TO_RAD; + mConstants["RAD_TO_DEG"] = RAD_TO_DEG; + mConstants["GRAVITY"] = GRAVITY; } LLCalc::~LLCalc() @@ -90,73 +90,73 @@ LLCalc::~LLCalc() //static void LLCalc::cleanUp() { - delete sInstance; - sInstance = NULL; + delete sInstance; + sInstance = NULL; } //static LLCalc* LLCalc::getInstance() { - if (!sInstance) sInstance = new LLCalc(); - return sInstance; + if (!sInstance) sInstance = new LLCalc(); + return sInstance; } void LLCalc::setVar(const std::string& name, const F32& value) { - mVariables[name] = value; + mVariables[name] = value; } void LLCalc::clearVar(const std::string& name) { - mVariables.erase(name); + mVariables.erase(name); } void LLCalc::clearAllVariables() { - mVariables.clear(); + mVariables.clear(); } /* void LLCalc::updateVariables(LLSD& vars) { - LLSD::map_iterator cIt = vars.beginMap(); - for(; cIt != vars.endMap(); cIt++) - { - setVar(cIt->first, (F32)(LLSD::Real)cIt->second); - } + LLSD::map_iterator cIt = vars.beginMap(); + for(; cIt != vars.endMap(); cIt++) + { + setVar(cIt->first, (F32)(LLSD::Real)cIt->second); + } } */ bool LLCalc::evalString(const std::string& expression, F32& result) { - std::string expr_upper = expression; - LLStringUtil::toUpper(expr_upper); - - LLCalcParser calc(result, &mConstants, &mVariables); - - mLastErrorPos = 0; - std::string::iterator start = expr_upper.begin(); - parse_info<std::string::iterator> info; - - try - { - info = parse(start, expr_upper.end(), calc, space_p); - LL_DEBUGS() << "Math expression: " << expression << " = " << result << LL_ENDL; - } - catch(parser_error<std::string, std::string::iterator> &e) - { - mLastErrorPos = e.where - expr_upper.begin(); - - LL_INFOS() << "Calc parser exception: " << e.descriptor << " at " << mLastErrorPos << " in expression: " << expression << LL_ENDL; - return false; - } - - if (!info.full) - { - mLastErrorPos = info.stop - expr_upper.begin(); - LL_INFOS() << "Unhandled syntax error at " << mLastErrorPos << " in expression: " << expression << LL_ENDL; - return false; - } - - return true; + std::string expr_upper = expression; + LLStringUtil::toUpper(expr_upper); + + LLCalcParser calc(result, &mConstants, &mVariables); + + mLastErrorPos = 0; + std::string::iterator start = expr_upper.begin(); + parse_info<std::string::iterator> info; + + try + { + info = parse(start, expr_upper.end(), calc, space_p); + LL_DEBUGS() << "Math expression: " << expression << " = " << result << LL_ENDL; + } + catch(parser_error<std::string, std::string::iterator> &e) + { + mLastErrorPos = e.where - expr_upper.begin(); + + LL_INFOS() << "Calc parser exception: " << e.descriptor << " at " << mLastErrorPos << " in expression: " << expression << LL_ENDL; + return false; + } + + if (!info.full) + { + mLastErrorPos = info.stop - expr_upper.begin(); + LL_INFOS() << "Unhandled syntax error at " << mLastErrorPos << " in expression: " << expression << LL_ENDL; + return false; + } + + return true; } diff --git a/indra/llmath/llcalc.h b/indra/llmath/llcalc.h index ceb9dce585..09672eb13b 100644 --- a/indra/llmath/llcalc.h +++ b/indra/llmath/llcalc.h @@ -4,21 +4,21 @@ * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2008, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ * @@ -33,68 +33,68 @@ class LLCalc { public: - LLCalc(); - ~LLCalc(); + LLCalc(); + ~LLCalc(); + + // Variable name constants + static const char* X_POS; + static const char* Y_POS; + static const char* Z_POS; + static const char* X_SCALE; + static const char* Y_SCALE; + static const char* Z_SCALE; + static const char* X_ROT; + static const char* Y_ROT; + static const char* Z_ROT; + static const char* HOLLOW; + static const char* CUT_BEGIN; + static const char* CUT_END; + static const char* PATH_BEGIN; + static const char* PATH_END; + static const char* TWIST_BEGIN; + static const char* TWIST_END; + static const char* X_SHEAR; + static const char* Y_SHEAR; + static const char* X_TAPER; + static const char* Y_TAPER; + static const char* RADIUS_OFFSET; + static const char* REVOLUTIONS; + static const char* SKEW; + static const char* X_HOLE; + static const char* Y_HOLE; + static const char* TEX_U_SCALE; + static const char* TEX_V_SCALE; + static const char* TEX_U_OFFSET; + static const char* TEX_V_OFFSET; + static const char* TEX_ROTATION; + static const char* TEX_TRANSPARENCY; + static const char* TEX_GLOW; - // Variable name constants - static const char* X_POS; - static const char* Y_POS; - static const char* Z_POS; - static const char* X_SCALE; - static const char* Y_SCALE; - static const char* Z_SCALE; - static const char* X_ROT; - static const char* Y_ROT; - static const char* Z_ROT; - static const char* HOLLOW; - static const char* CUT_BEGIN; - static const char* CUT_END; - static const char* PATH_BEGIN; - static const char* PATH_END; - static const char* TWIST_BEGIN; - static const char* TWIST_END; - static const char* X_SHEAR; - static const char* Y_SHEAR; - static const char* X_TAPER; - static const char* Y_TAPER; - static const char* RADIUS_OFFSET; - static const char* REVOLUTIONS; - static const char* SKEW; - static const char* X_HOLE; - static const char* Y_HOLE; - static const char* TEX_U_SCALE; - static const char* TEX_V_SCALE; - static const char* TEX_U_OFFSET; - static const char* TEX_V_OFFSET; - static const char* TEX_ROTATION; - static const char* TEX_TRANSPARENCY; - static const char* TEX_GLOW; + void setVar(const std::string& name, const F32& value); + void clearVar(const std::string& name); + void clearAllVariables(); +// void updateVariables(LLSD& vars); - void setVar(const std::string& name, const F32& value); - void clearVar(const std::string& name); - void clearAllVariables(); -// void updateVariables(LLSD& vars); + bool evalString(const std::string& expression, F32& result); + std::string::size_type getLastErrorPos() { return mLastErrorPos; } - bool evalString(const std::string& expression, F32& result); - std::string::size_type getLastErrorPos() { return mLastErrorPos; } - - static LLCalc* getInstance(); - static void cleanUp(); + static LLCalc* getInstance(); + static void cleanUp(); + + typedef std::map<std::string, F32> calc_map_t; - typedef std::map<std::string, F32> calc_map_t; - private: - std::string::size_type mLastErrorPos; - - calc_map_t mConstants; - calc_map_t mVariables; - - // *TODO: Add support for storing user defined variables, and stored functions. - // Will need UI work, and a means to save them between sessions. -// calc_map_t mUserVariables; - - // "There shall be only one" - static LLCalc* sInstance; + std::string::size_type mLastErrorPos; + + calc_map_t mConstants; + calc_map_t mVariables; + + // *TODO: Add support for storing user defined variables, and stored functions. + // Will need UI work, and a means to save them between sessions. +// calc_map_t mUserVariables; + + // "There shall be only one" + static LLCalc* sInstance; }; #endif // LL_CALC_H diff --git a/indra/llmath/llcalcparser.cpp b/indra/llmath/llcalcparser.cpp index b4ca320659..7399c368f7 100644 --- a/indra/llmath/llcalcparser.cpp +++ b/indra/llmath/llcalcparser.cpp @@ -4,21 +4,21 @@ * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2008, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ * @@ -31,33 +31,33 @@ using namespace boost::spirit::classic; F32 LLCalcParser::lookup(const std::string::iterator& start, const std::string::iterator& end) const { - LLCalc::calc_map_t::iterator iter; + LLCalc::calc_map_t::iterator iter; + + std::string name(start, end); + + if (mConstants) + { + iter = mConstants->find(name); + if (iter != mConstants->end()) + { + return (*iter).second; + } + } + else + { + // This should never happen! + throw_(end, std::string("Missing constants table")); + } + + if (mVariables) + { + iter = mVariables->find(name); + if (iter != mVariables->end()) + { + return (*iter).second; + } + } - std::string name(start, end); - - if (mConstants) - { - iter = mConstants->find(name); - if (iter != mConstants->end()) - { - return (*iter).second; - } - } - else - { - // This should never happen! - throw_(end, std::string("Missing constants table")); - } - - if (mVariables) - { - iter = mVariables->find(name); - if (iter != mVariables->end()) - { - return (*iter).second; - } - } - - throw_(end, std::string("Unknown symbol " + name)); - return 0.f; + throw_(end, std::string("Unknown symbol " + name)); + return 0.f; } diff --git a/indra/llmath/llcalcparser.h b/indra/llmath/llcalcparser.h index dff5bf3af3..e8fdcc9ae3 100644 --- a/indra/llmath/llcalcparser.h +++ b/indra/llmath/llcalcparser.h @@ -4,21 +4,21 @@ * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2008, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ * @@ -40,149 +40,149 @@ using namespace boost::spirit::classic; struct LLCalcParser : grammar<LLCalcParser> { - LLCalcParser(F32& result, LLCalc::calc_map_t* constants, LLCalc::calc_map_t* vars) : - mResult(result), mConstants(constants), mVariables(vars) {}; - - struct value_closure : closure<value_closure, F32> - { - member1 value; - }; - - template <typename ScannerT> - struct definition - { - // Rule declarations - rule<ScannerT> statement, identifier; - rule<ScannerT, value_closure::context_t> expression, term, - power, - unary_expr, - factor, - unary_func, - binary_func, - group; - - // start() should return the starting symbol - rule<ScannerT> const& start() const { return statement; } - - definition(LLCalcParser const& self) - { - using namespace phoenix; - - assertion<std::string> assert_domain("Domain error"); -// assertion<std::string> assert_symbol("Unknown symbol"); - assertion<std::string> assert_syntax("Syntax error"); - - identifier = - lexeme_d[(alpha_p | '_') >> *(alnum_p | '_')] - ; - - group = - '(' >> expression[group.value = arg1] >> assert_syntax(ch_p(')')) - ; - - unary_func = - ((str_p("SIN") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_sin)(self,arg1)]) | - (str_p("COS") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_cos)(self,arg1)]) | - (str_p("TAN") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_tan)(self,arg1)]) | - (str_p("ASIN") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_asin)(self,arg1)]) | - (str_p("ACOS") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_acos)(self,arg1)]) | - (str_p("ATAN") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_atan)(self,arg1)]) | - (str_p("SQRT") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_sqrt)(self,arg1)]) | - (str_p("LOG") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_log)(self,arg1)]) | - (str_p("EXP") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_exp)(self,arg1)]) | - (str_p("ABS") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_fabs)(self,arg1)]) | - (str_p("FLR") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_floor)(self,arg1)]) | - (str_p("CEIL") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_ceil)(self,arg1)]) - ) >> assert_syntax(ch_p(')')) - ; - - binary_func = - ((str_p("ATAN2") >> '(' >> expression[binary_func.value = arg1] >> ',' >> - expression[binary_func.value = phoenix::bind(&LLCalcParser::_atan2)(self, binary_func.value, arg1)]) | - (str_p("MIN") >> '(' >> expression[binary_func.value = arg1] >> ',' >> - expression[binary_func.value = phoenix::bind(&LLCalcParser::_min)(self, binary_func.value, arg1)]) | - (str_p("MAX") >> '(' >> expression[binary_func.value = arg1] >> ',' >> - expression[binary_func.value = phoenix::bind(&LLCalcParser::_max)(self, binary_func.value, arg1)]) - ) >> assert_syntax(ch_p(')')) - ; - - // *TODO: Localisation of the decimal point? - // Problem, LLLineEditor::postvalidateFloat accepts a comma when appropriate - // for the current locale. However to do that here could clash with using - // the comma as a separator when passing arguments to functions. - factor = - (ureal_p[factor.value = arg1] | - group[factor.value = arg1] | - unary_func[factor.value = arg1] | - binary_func[factor.value = arg1] | - // Lookup throws an Unknown Symbol error if it is unknown, while this works fine, - // would be "neater" to handle symbol lookup from here with an assertive parser. -// constants_p[factor.value = arg1]| - identifier[factor.value = phoenix::bind(&LLCalcParser::lookup)(self, arg1, arg2)] - ) >> - // Detect and throw math errors. - assert_domain(eps_p(phoenix::bind(&LLCalcParser::checkNaN)(self, factor.value))) - ; - - unary_expr = - !ch_p('+') >> factor[unary_expr.value = arg1] | - '-' >> factor[unary_expr.value = -arg1] - ; - - power = - unary_expr[power.value = arg1] >> - *('^' >> assert_syntax(unary_expr[power.value = phoenix::bind(&powf)(power.value, arg1)])) - ; - - term = - power[term.value = arg1] >> - *(('*' >> assert_syntax(power[term.value *= arg1])) | - ('/' >> assert_syntax(power[term.value /= arg1])) | - ('%' >> assert_syntax(power[term.value = phoenix::bind(&fmodf)(term.value, arg1)])) - ) - ; - - expression = - assert_syntax(term[expression.value = arg1]) >> - *(('+' >> assert_syntax(term[expression.value += arg1])) | - ('-' >> assert_syntax(term[expression.value -= arg1])) - ) - ; - - statement = - !ch_p('=') >> ( expression )[var(self.mResult) = arg1] >> (end_p) - ; - } - }; - + LLCalcParser(F32& result, LLCalc::calc_map_t* constants, LLCalc::calc_map_t* vars) : + mResult(result), mConstants(constants), mVariables(vars) {}; + + struct value_closure : closure<value_closure, F32> + { + member1 value; + }; + + template <typename ScannerT> + struct definition + { + // Rule declarations + rule<ScannerT> statement, identifier; + rule<ScannerT, value_closure::context_t> expression, term, + power, + unary_expr, + factor, + unary_func, + binary_func, + group; + + // start() should return the starting symbol + rule<ScannerT> const& start() const { return statement; } + + definition(LLCalcParser const& self) + { + using namespace phoenix; + + assertion<std::string> assert_domain("Domain error"); +// assertion<std::string> assert_symbol("Unknown symbol"); + assertion<std::string> assert_syntax("Syntax error"); + + identifier = + lexeme_d[(alpha_p | '_') >> *(alnum_p | '_')] + ; + + group = + '(' >> expression[group.value = arg1] >> assert_syntax(ch_p(')')) + ; + + unary_func = + ((str_p("SIN") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_sin)(self,arg1)]) | + (str_p("COS") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_cos)(self,arg1)]) | + (str_p("TAN") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_tan)(self,arg1)]) | + (str_p("ASIN") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_asin)(self,arg1)]) | + (str_p("ACOS") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_acos)(self,arg1)]) | + (str_p("ATAN") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_atan)(self,arg1)]) | + (str_p("SQRT") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_sqrt)(self,arg1)]) | + (str_p("LOG") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_log)(self,arg1)]) | + (str_p("EXP") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_exp)(self,arg1)]) | + (str_p("ABS") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_fabs)(self,arg1)]) | + (str_p("FLR") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_floor)(self,arg1)]) | + (str_p("CEIL") >> '(' >> expression[unary_func.value = phoenix::bind(&LLCalcParser::_ceil)(self,arg1)]) + ) >> assert_syntax(ch_p(')')) + ; + + binary_func = + ((str_p("ATAN2") >> '(' >> expression[binary_func.value = arg1] >> ',' >> + expression[binary_func.value = phoenix::bind(&LLCalcParser::_atan2)(self, binary_func.value, arg1)]) | + (str_p("MIN") >> '(' >> expression[binary_func.value = arg1] >> ',' >> + expression[binary_func.value = phoenix::bind(&LLCalcParser::_min)(self, binary_func.value, arg1)]) | + (str_p("MAX") >> '(' >> expression[binary_func.value = arg1] >> ',' >> + expression[binary_func.value = phoenix::bind(&LLCalcParser::_max)(self, binary_func.value, arg1)]) + ) >> assert_syntax(ch_p(')')) + ; + + // *TODO: Localisation of the decimal point? + // Problem, LLLineEditor::postvalidateFloat accepts a comma when appropriate + // for the current locale. However to do that here could clash with using + // the comma as a separator when passing arguments to functions. + factor = + (ureal_p[factor.value = arg1] | + group[factor.value = arg1] | + unary_func[factor.value = arg1] | + binary_func[factor.value = arg1] | + // Lookup throws an Unknown Symbol error if it is unknown, while this works fine, + // would be "neater" to handle symbol lookup from here with an assertive parser. +// constants_p[factor.value = arg1]| + identifier[factor.value = phoenix::bind(&LLCalcParser::lookup)(self, arg1, arg2)] + ) >> + // Detect and throw math errors. + assert_domain(eps_p(phoenix::bind(&LLCalcParser::checkNaN)(self, factor.value))) + ; + + unary_expr = + !ch_p('+') >> factor[unary_expr.value = arg1] | + '-' >> factor[unary_expr.value = -arg1] + ; + + power = + unary_expr[power.value = arg1] >> + *('^' >> assert_syntax(unary_expr[power.value = phoenix::bind(&powf)(power.value, arg1)])) + ; + + term = + power[term.value = arg1] >> + *(('*' >> assert_syntax(power[term.value *= arg1])) | + ('/' >> assert_syntax(power[term.value /= arg1])) | + ('%' >> assert_syntax(power[term.value = phoenix::bind(&fmodf)(term.value, arg1)])) + ) + ; + + expression = + assert_syntax(term[expression.value = arg1]) >> + *(('+' >> assert_syntax(term[expression.value += arg1])) | + ('-' >> assert_syntax(term[expression.value -= arg1])) + ) + ; + + statement = + !ch_p('=') >> ( expression )[var(self.mResult) = arg1] >> (end_p) + ; + } + }; + private: - // Member functions for semantic actions - F32 lookup(const std::string::iterator&, const std::string::iterator&) const; - F32 _min(const F32& a, const F32& b) const { return llmin(a, b); } - F32 _max(const F32& a, const F32& b) const { return llmax(a, b); } - - bool checkNaN(const F32& a) const { return !llisnan(a); } - - //FIX* non ambiguous function fix making SIN() work for calc -Cryogenic Blitz - F32 _sin(const F32& a) const { return sin(DEG_TO_RAD * a); } - F32 _cos(const F32& a) const { return cos(DEG_TO_RAD * a); } - F32 _tan(const F32& a) const { return tan(DEG_TO_RAD * a); } - F32 _asin(const F32& a) const { return asin(a) * RAD_TO_DEG; } - F32 _acos(const F32& a) const { return acos(a) * RAD_TO_DEG; } - F32 _atan(const F32& a) const { return atan(a) * RAD_TO_DEG; } - F32 _sqrt(const F32& a) const { return sqrt(a); } - F32 _log(const F32& a) const { return log(a); } - F32 _exp(const F32& a) const { return exp(a); } - F32 _fabs(const F32& a) const { return fabs(a); } - F32 _floor(const F32& a) const { return (F32)llfloor(a); } - F32 _ceil(const F32& a) const { return llceil(a); } - F32 _atan2(const F32& a,const F32& b) const { return atan2(a,b); } - - LLCalc::calc_map_t* mConstants; - LLCalc::calc_map_t* mVariables; -// LLCalc::calc_map_t* mUserVariables; - - F32& mResult; + // Member functions for semantic actions + F32 lookup(const std::string::iterator&, const std::string::iterator&) const; + F32 _min(const F32& a, const F32& b) const { return llmin(a, b); } + F32 _max(const F32& a, const F32& b) const { return llmax(a, b); } + + bool checkNaN(const F32& a) const { return !llisnan(a); } + + //FIX* non ambiguous function fix making SIN() work for calc -Cryogenic Blitz + F32 _sin(const F32& a) const { return sin(DEG_TO_RAD * a); } + F32 _cos(const F32& a) const { return cos(DEG_TO_RAD * a); } + F32 _tan(const F32& a) const { return tan(DEG_TO_RAD * a); } + F32 _asin(const F32& a) const { return asin(a) * RAD_TO_DEG; } + F32 _acos(const F32& a) const { return acos(a) * RAD_TO_DEG; } + F32 _atan(const F32& a) const { return atan(a) * RAD_TO_DEG; } + F32 _sqrt(const F32& a) const { return sqrt(a); } + F32 _log(const F32& a) const { return log(a); } + F32 _exp(const F32& a) const { return exp(a); } + F32 _fabs(const F32& a) const { return fabs(a); } + F32 _floor(const F32& a) const { return (F32)llfloor(a); } + F32 _ceil(const F32& a) const { return llceil(a); } + F32 _atan2(const F32& a,const F32& b) const { return atan2(a,b); } + + LLCalc::calc_map_t* mConstants; + LLCalc::calc_map_t* mVariables; +// LLCalc::calc_map_t* mUserVariables; + + F32& mResult; }; #endif // LL_CALCPARSER_H diff --git a/indra/llmath/llcamera.cpp b/indra/llmath/llcamera.cpp index 18d704dd0f..3daed2ac31 100644 --- a/indra/llmath/llcamera.cpp +++ b/indra/llmath/llcamera.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llcamera.cpp * @brief Implementation of the LLCamera class. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -32,43 +32,43 @@ // ---------------- Constructors and destructors ---------------- LLCamera::LLCamera() : - LLCoordFrame(), - mView(DEFAULT_FIELD_OF_VIEW), - mAspect(DEFAULT_ASPECT_RATIO), - mViewHeightInPixels( -1 ), // invalid height - mNearPlane(DEFAULT_NEAR_PLANE), - mFarPlane(DEFAULT_FAR_PLANE), - mFixedDistance(-1.f), - mPlaneCount(6), - mFrustumCornerDist(0.f) -{ - for (U32 i = 0; i < PLANE_MASK_NUM; i++) - { - mPlaneMask[i] = PLANE_MASK_NONE; - } - - calculateFrustumPlanes(); -} + LLCoordFrame(), + mView(DEFAULT_FIELD_OF_VIEW), + mAspect(DEFAULT_ASPECT_RATIO), + mViewHeightInPixels( -1 ), // invalid height + mNearPlane(DEFAULT_NEAR_PLANE), + mFarPlane(DEFAULT_FAR_PLANE), + mFixedDistance(-1.f), + mPlaneCount(6), + mFrustumCornerDist(0.f) +{ + for (U32 i = 0; i < PLANE_MASK_NUM; i++) + { + mPlaneMask[i] = PLANE_MASK_NONE; + } + + calculateFrustumPlanes(); +} LLCamera::LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane) : - LLCoordFrame(), - mViewHeightInPixels(view_height_in_pixels), - mFixedDistance(-1.f), - mPlaneCount(6), - mFrustumCornerDist(0.f) -{ - for (U32 i = 0; i < PLANE_MASK_NUM; i++) - { - mPlaneMask[i] = PLANE_MASK_NONE; - } - - mAspect = llclamp(aspect_ratio, MIN_ASPECT_RATIO, MAX_ASPECT_RATIO); - mNearPlane = llclamp(near_plane, MIN_NEAR_PLANE, MAX_NEAR_PLANE); - if(far_plane < 0) far_plane = DEFAULT_FAR_PLANE; - mFarPlane = llclamp(far_plane, MIN_FAR_PLANE, MAX_FAR_PLANE); - - setView(vertical_fov_rads); -} + LLCoordFrame(), + mViewHeightInPixels(view_height_in_pixels), + mFixedDistance(-1.f), + mPlaneCount(6), + mFrustumCornerDist(0.f) +{ + for (U32 i = 0; i < PLANE_MASK_NUM; i++) + { + mPlaneMask[i] = PLANE_MASK_NONE; + } + + mAspect = llclamp(aspect_ratio, MIN_ASPECT_RATIO, MAX_ASPECT_RATIO); + mNearPlane = llclamp(near_plane, MIN_NEAR_PLANE, MAX_NEAR_PLANE); + if(far_plane < 0) far_plane = DEFAULT_FAR_PLANE; + mFarPlane = llclamp(far_plane, MIN_FAR_PLANE, MAX_FAR_PLANE); + + setView(vertical_fov_rads); +} LLCamera::~LLCamera() { @@ -77,20 +77,20 @@ LLCamera::~LLCamera() // ---------------- LLCamera::getFoo() member functions ---------------- -F32 LLCamera::getMinView() const +F32 LLCamera::getMinView() const { - // minimum vertical fov needs to be constrained in narrow windows. - return mAspect > 1 - ? MIN_FIELD_OF_VIEW // wide views - : MIN_FIELD_OF_VIEW * 1/mAspect; // clamps minimum width in narrow views + // minimum vertical fov needs to be constrained in narrow windows. + return mAspect > 1 + ? MIN_FIELD_OF_VIEW // wide views + : MIN_FIELD_OF_VIEW * 1/mAspect; // clamps minimum width in narrow views } -F32 LLCamera::getMaxView() const +F32 LLCamera::getMaxView() const { - // maximum vertical fov needs to be constrained in wide windows. - return mAspect > 1 - ? MAX_FIELD_OF_VIEW / mAspect // clamps maximum width in wide views - : MAX_FIELD_OF_VIEW; // narrow views + // maximum vertical fov needs to be constrained in wide windows. + return mAspect > 1 + ? MAX_FIELD_OF_VIEW / mAspect // clamps maximum width in wide views + : MAX_FIELD_OF_VIEW; // narrow views } LLPlane LLCamera::getUserClipPlane() @@ -102,437 +102,437 @@ LLPlane LLCamera::getUserClipPlane() void LLCamera::setUserClipPlane(LLPlane& plane) { - mPlaneCount = AGENT_PLANE_USER_CLIP_NUM; - mAgentPlanes[AGENT_PLANE_USER_CLIP] = plane; - mPlaneMask[AGENT_PLANE_USER_CLIP] = plane.calcPlaneMask(); + mPlaneCount = AGENT_PLANE_USER_CLIP_NUM; + mAgentPlanes[AGENT_PLANE_USER_CLIP] = plane; + mPlaneMask[AGENT_PLANE_USER_CLIP] = plane.calcPlaneMask(); } void LLCamera::disableUserClipPlane() { - mPlaneCount = AGENT_PLANE_NO_USER_CLIP_NUM; + mPlaneCount = AGENT_PLANE_NO_USER_CLIP_NUM; } -void LLCamera::setView(F32 vertical_fov_rads) +void LLCamera::setView(F32 vertical_fov_rads) { - mView = llclamp(vertical_fov_rads, MIN_FIELD_OF_VIEW, MAX_FIELD_OF_VIEW); - calculateFrustumPlanes(); + mView = llclamp(vertical_fov_rads, MIN_FIELD_OF_VIEW, MAX_FIELD_OF_VIEW); + calculateFrustumPlanes(); } void LLCamera::setViewHeightInPixels(S32 height) { - mViewHeightInPixels = height; + mViewHeightInPixels = height; - // Don't really need to do this, but update the pixel meter ratio with it. - calculateFrustumPlanes(); + // Don't really need to do this, but update the pixel meter ratio with it. + calculateFrustumPlanes(); } -void LLCamera::setAspect(F32 aspect_ratio) +void LLCamera::setAspect(F32 aspect_ratio) { - mAspect = llclamp(aspect_ratio, MIN_ASPECT_RATIO, MAX_ASPECT_RATIO); - calculateFrustumPlanes(); + mAspect = llclamp(aspect_ratio, MIN_ASPECT_RATIO, MAX_ASPECT_RATIO); + calculateFrustumPlanes(); } -void LLCamera::setNear(F32 near_plane) +void LLCamera::setNear(F32 near_plane) { - mNearPlane = llclamp(near_plane, MIN_NEAR_PLANE, MAX_NEAR_PLANE); - calculateFrustumPlanes(); + mNearPlane = llclamp(near_plane, MIN_NEAR_PLANE, MAX_NEAR_PLANE); + calculateFrustumPlanes(); } -void LLCamera::setFar(F32 far_plane) +void LLCamera::setFar(F32 far_plane) { - mFarPlane = llclamp(far_plane, MIN_FAR_PLANE, MAX_FAR_PLANE); - calculateFrustumPlanes(); + mFarPlane = llclamp(far_plane, MIN_FAR_PLANE, MAX_FAR_PLANE); + calculateFrustumPlanes(); } -// ---------------- read/write to buffer ---------------- +// ---------------- read/write to buffer ---------------- size_t LLCamera::writeFrustumToBuffer(char *buffer) const { - memcpy(buffer, &mView, sizeof(F32)); /* Flawfinder: ignore */ - buffer += sizeof(F32); - memcpy(buffer, &mAspect, sizeof(F32)); /* Flawfinder: ignore */ - buffer += sizeof(F32); - memcpy(buffer, &mNearPlane, sizeof(F32)); /* Flawfinder: ignore */ - buffer += sizeof(F32); - memcpy(buffer, &mFarPlane, sizeof(F32)); /* Flawfinder: ignore */ - return 4*sizeof(F32); + memcpy(buffer, &mView, sizeof(F32)); /* Flawfinder: ignore */ + buffer += sizeof(F32); + memcpy(buffer, &mAspect, sizeof(F32)); /* Flawfinder: ignore */ + buffer += sizeof(F32); + memcpy(buffer, &mNearPlane, sizeof(F32)); /* Flawfinder: ignore */ + buffer += sizeof(F32); + memcpy(buffer, &mFarPlane, sizeof(F32)); /* Flawfinder: ignore */ + return 4*sizeof(F32); } size_t LLCamera::readFrustumFromBuffer(const char *buffer) { - memcpy(&mView, buffer, sizeof(F32)); /* Flawfinder: ignore */ - buffer += sizeof(F32); - memcpy(&mAspect, buffer, sizeof(F32)); /* Flawfinder: ignore */ - buffer += sizeof(F32); - memcpy(&mNearPlane, buffer, sizeof(F32)); /* Flawfinder: ignore */ - buffer += sizeof(F32); - memcpy(&mFarPlane, buffer, sizeof(F32)); /* Flawfinder: ignore */ - return 4*sizeof(F32); + memcpy(&mView, buffer, sizeof(F32)); /* Flawfinder: ignore */ + buffer += sizeof(F32); + memcpy(&mAspect, buffer, sizeof(F32)); /* Flawfinder: ignore */ + buffer += sizeof(F32); + memcpy(&mNearPlane, buffer, sizeof(F32)); /* Flawfinder: ignore */ + buffer += sizeof(F32); + memcpy(&mFarPlane, buffer, sizeof(F32)); /* Flawfinder: ignore */ + return 4*sizeof(F32); } -// ---------------- test methods ---------------- +// ---------------- test methods ---------------- -static const LLVector4a sFrustumScaler[] = +static const LLVector4a sFrustumScaler[] = { - LLVector4a(-1,-1,-1), - LLVector4a( 1,-1,-1), - LLVector4a(-1, 1,-1), - LLVector4a( 1, 1,-1), - LLVector4a(-1,-1, 1), - LLVector4a( 1,-1, 1), - LLVector4a(-1, 1, 1), - LLVector4a( 1, 1, 1) // 8 entries + LLVector4a(-1,-1,-1), + LLVector4a( 1,-1,-1), + LLVector4a(-1, 1,-1), + LLVector4a( 1, 1,-1), + LLVector4a(-1,-1, 1), + LLVector4a( 1,-1, 1), + LLVector4a(-1, 1, 1), + LLVector4a( 1, 1, 1) // 8 entries }; bool LLCamera::isChanged() { - bool changed = false; - for (U32 i = 0; i < mPlaneCount; i++) - { - U8 mask = mPlaneMask[i]; - if (mask != 0xff && !changed) - { - changed = !mAgentPlanes[i].equal(mLastAgentPlanes[i]); - } - mLastAgentPlanes[i].set(mAgentPlanes[i]); - } - - return changed; + bool changed = false; + for (U32 i = 0; i < mPlaneCount; i++) + { + U8 mask = mPlaneMask[i]; + if (mask != 0xff && !changed) + { + changed = !mAgentPlanes[i].equal(mLastAgentPlanes[i]); + } + mLastAgentPlanes[i].set(mAgentPlanes[i]); + } + + return changed; } -S32 LLCamera::AABBInFrustum(const LLVector4a ¢er, const LLVector4a& radius, const LLPlane* planes) -{ - if(!planes) - { - //use agent space - planes = mAgentPlanes; - } - - U8 mask = 0; - bool result = false; - LLVector4a rscale, maxp, minp; - LLSimdScalar d; - U32 max_planes = llmin(mPlaneCount, (U32) AGENT_PLANE_USER_CLIP_NUM); // mAgentPlanes[] size is 7 - for (U32 i = 0; i < max_planes; i++) - { - mask = mPlaneMask[i]; - if (mask < PLANE_MASK_NUM) - { - const LLPlane& p(planes[i]); - p.getAt<3>(d); - rscale.setMul(radius, sFrustumScaler[mask]); - minp.setSub(center, rscale); - d = -d; - if (p.dot3(minp).getF32() > d) - { - return 0; - } - - if(!result) - { - maxp.setAdd(center, rscale); - result = (p.dot3(maxp).getF32() > d); - } - } - } - - return result?1:2; +S32 LLCamera::AABBInFrustum(const LLVector4a ¢er, const LLVector4a& radius, const LLPlane* planes) +{ + if(!planes) + { + //use agent space + planes = mAgentPlanes; + } + + U8 mask = 0; + bool result = false; + LLVector4a rscale, maxp, minp; + LLSimdScalar d; + U32 max_planes = llmin(mPlaneCount, (U32) AGENT_PLANE_USER_CLIP_NUM); // mAgentPlanes[] size is 7 + for (U32 i = 0; i < max_planes; i++) + { + mask = mPlaneMask[i]; + if (mask < PLANE_MASK_NUM) + { + const LLPlane& p(planes[i]); + p.getAt<3>(d); + rscale.setMul(radius, sFrustumScaler[mask]); + minp.setSub(center, rscale); + d = -d; + if (p.dot3(minp).getF32() > d) + { + return 0; + } + + if(!result) + { + maxp.setAdd(center, rscale); + result = (p.dot3(maxp).getF32() > d); + } + } + } + + return result?1:2; } //exactly same as the function AABBInFrustum(...) //except uses mRegionPlanes instead of mAgentPlanes. -S32 LLCamera::AABBInRegionFrustum(const LLVector4a& center, const LLVector4a& radius) +S32 LLCamera::AABBInRegionFrustum(const LLVector4a& center, const LLVector4a& radius) { - return AABBInFrustum(center, radius, mRegionPlanes); + return AABBInFrustum(center, radius, mRegionPlanes); } -S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius, const LLPlane* planes) -{ - if(!planes) - { - //use agent space - planes = mAgentPlanes; - } - - U8 mask = 0; - bool result = false; - LLVector4a rscale, maxp, minp; - LLSimdScalar d; - U32 max_planes = llmin(mPlaneCount, (U32) AGENT_PLANE_USER_CLIP_NUM); // mAgentPlanes[] size is 7 - for (U32 i = 0; i < max_planes; i++) - { - mask = mPlaneMask[i]; - if ((i != 5) && (mask < PLANE_MASK_NUM)) - { - const LLPlane& p(planes[i]); - p.getAt<3>(d); - rscale.setMul(radius, sFrustumScaler[mask]); - minp.setSub(center, rscale); - d = -d; - if (p.dot3(minp).getF32() > d) - { - return 0; - } - - if(!result) - { - maxp.setAdd(center, rscale); - result = (p.dot3(maxp).getF32() > d); - } - } - } - - return result?1:2; +S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius, const LLPlane* planes) +{ + if(!planes) + { + //use agent space + planes = mAgentPlanes; + } + + U8 mask = 0; + bool result = false; + LLVector4a rscale, maxp, minp; + LLSimdScalar d; + U32 max_planes = llmin(mPlaneCount, (U32) AGENT_PLANE_USER_CLIP_NUM); // mAgentPlanes[] size is 7 + for (U32 i = 0; i < max_planes; i++) + { + mask = mPlaneMask[i]; + if ((i != 5) && (mask < PLANE_MASK_NUM)) + { + const LLPlane& p(planes[i]); + p.getAt<3>(d); + rscale.setMul(radius, sFrustumScaler[mask]); + minp.setSub(center, rscale); + d = -d; + if (p.dot3(minp).getF32() > d) + { + return 0; + } + + if(!result) + { + maxp.setAdd(center, rscale); + result = (p.dot3(maxp).getF32() > d); + } + } + } + + return result?1:2; } //exactly same as the function AABBInFrustumNoFarClip(...) //except uses mRegionPlanes instead of mAgentPlanes. -S32 LLCamera::AABBInRegionFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius) +S32 LLCamera::AABBInRegionFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius) { - return AABBInFrustumNoFarClip(center, radius, mRegionPlanes); + return AABBInFrustumNoFarClip(center, radius, mRegionPlanes); } -int LLCamera::sphereInFrustumQuick(const LLVector3 &sphere_center, const F32 radius) +int LLCamera::sphereInFrustumQuick(const LLVector3 &sphere_center, const F32 radius) { - LLVector3 dist = sphere_center-mFrustCenter; - float dsq = dist * dist; - float rsq = mFarPlane*0.5f + radius; - rsq *= rsq; + LLVector3 dist = sphere_center-mFrustCenter; + float dsq = dist * dist; + float rsq = mFarPlane*0.5f + radius; + rsq *= rsq; - if (dsq < rsq) - { - return 1; - } - - return 0; + if (dsq < rsq) + { + return 1; + } + + return 0; } // Return 1 if sphere is in frustum, 2 if fully in frustum, otherwise 0. // NOTE: 'center' is in absolute frame. -int LLCamera::sphereInFrustum(const LLVector3 &sphere_center, const F32 radius) const -{ - // Returns 1 if sphere is in frustum, 0 if not. - bool res = false; - for (int i = 0; i < 6; i++) - { - if (mPlaneMask[i] != PLANE_MASK_NONE) - { - float d = mAgentPlanes[i].dist(sphere_center); - - if (d > radius) - { - return 0; - } - res = res || (d > -radius); - } - } - - return res?1:2; +int LLCamera::sphereInFrustum(const LLVector3 &sphere_center, const F32 radius) const +{ + // Returns 1 if sphere is in frustum, 0 if not. + bool res = false; + for (int i = 0; i < 6; i++) + { + if (mPlaneMask[i] != PLANE_MASK_NONE) + { + float d = mAgentPlanes[i].dist(sphere_center); + + if (d > radius) + { + return 0; + } + res = res || (d > -radius); + } + } + + return res?1:2; } // return height of a sphere of given radius, located at center, in pixels F32 LLCamera::heightInPixels(const LLVector3 ¢er, F32 radius ) const { - if (radius == 0.f) return 0.f; + if (radius == 0.f) return 0.f; - // If height initialized - if (mViewHeightInPixels > -1) - { - // Convert sphere to coord system with 0,0,0 at camera - LLVector3 vec = center - mOrigin; + // If height initialized + if (mViewHeightInPixels > -1) + { + // Convert sphere to coord system with 0,0,0 at camera + LLVector3 vec = center - mOrigin; - // Compute distance to sphere - F32 dist = vec.magVec(); + // Compute distance to sphere + F32 dist = vec.magVec(); - // Calculate angle of whole object - F32 angle = 2.0f * (F32) atan2(radius, dist); + // Calculate angle of whole object + F32 angle = 2.0f * (F32) atan2(radius, dist); - // Calculate fraction of field of view - F32 fraction_of_fov = angle / mView; + // Calculate fraction of field of view + F32 fraction_of_fov = angle / mView; - // Compute number of pixels tall, based on vertical field of view - return (fraction_of_fov * mViewHeightInPixels); - } - else - { - // return invalid height - return -1.0f; - } + // Compute number of pixels tall, based on vertical field of view + return (fraction_of_fov * mViewHeightInPixels); + } + else + { + // return invalid height + return -1.0f; + } } -// ---------------- friends and operators ---------------- +// ---------------- friends and operators ---------------- -std::ostream& operator<<(std::ostream &s, const LLCamera &C) +std::ostream& operator<<(std::ostream &s, const LLCamera &C) { - s << "{ \n"; - s << " Center = " << C.getOrigin() << "\n"; - s << " AtAxis = " << C.getXAxis() << "\n"; - s << " LeftAxis = " << C.getYAxis() << "\n"; - s << " UpAxis = " << C.getZAxis() << "\n"; - s << " View = " << C.getView() << "\n"; - s << " Aspect = " << C.getAspect() << "\n"; - s << " NearPlane = " << C.mNearPlane << "\n"; - s << " FarPlane = " << C.mFarPlane << "\n"; - s << "}"; - return s; + s << "{ \n"; + s << " Center = " << C.getOrigin() << "\n"; + s << " AtAxis = " << C.getXAxis() << "\n"; + s << " LeftAxis = " << C.getYAxis() << "\n"; + s << " UpAxis = " << C.getZAxis() << "\n"; + s << " View = " << C.getView() << "\n"; + s << " Aspect = " << C.getAspect() << "\n"; + s << " NearPlane = " << C.mNearPlane << "\n"; + s << " FarPlane = " << C.mFarPlane << "\n"; + s << "}"; + return s; } // ---------------- private member functions ---------------- -void LLCamera::calculateFrustumPlanes() +void LLCamera::calculateFrustumPlanes() { - // The planes only change when any of the frustum descriptions change. - // They are not affected by changes of the position of the Frustum - // because they are known in the view frame and the position merely - // provides information on how to get from the absolute frame to the - // view frame. + // The planes only change when any of the frustum descriptions change. + // They are not affected by changes of the position of the Frustum + // because they are known in the view frame and the position merely + // provides information on how to get from the absolute frame to the + // view frame. - F32 left,right,top,bottom; - top = mFarPlane * (F32)tanf(0.5f * mView); - bottom = -top; - left = top * mAspect; - right = -left; + F32 left,right,top,bottom; + top = mFarPlane * (F32)tanf(0.5f * mView); + bottom = -top; + left = top * mAspect; + right = -left; - calculateFrustumPlanes(left, right, top, bottom); + calculateFrustumPlanes(left, right, top, bottom); } LLPlane planeFromPoints(LLVector3 p1, LLVector3 p2, LLVector3 p3) { - LLVector3 n = ((p2-p1)%(p3-p1)); - n.normVec(); + LLVector3 n = ((p2-p1)%(p3-p1)); + n.normVec(); - return LLPlane(p1, n); + return LLPlane(p1, n); } void LLCamera::ignoreAgentFrustumPlane(S32 idx) { - if (idx < 0 || idx > (S32) mPlaneCount) - { - return; - } + if (idx < 0 || idx > (S32) mPlaneCount) + { + return; + } - mPlaneMask[idx] = PLANE_MASK_NONE; - mAgentPlanes[idx].clear(); + mPlaneMask[idx] = PLANE_MASK_NONE; + mAgentPlanes[idx].clear(); } void LLCamera::calcAgentFrustumPlanes(LLVector3* frust) { - - for (int i = 0; i < AGENT_FRUSTRUM_NUM; i++) - { - mAgentFrustum[i] = frust[i]; - } - mFrustumCornerDist = (frust[5] - getOrigin()).magVec(); + for (int i = 0; i < AGENT_FRUSTRUM_NUM; i++) + { + mAgentFrustum[i] = frust[i]; + } + + mFrustumCornerDist = (frust[5] - getOrigin()).magVec(); - //frust contains the 8 points of the frustum, calculate 6 planes + //frust contains the 8 points of the frustum, calculate 6 planes - //order of planes is important, keep most likely to fail in the front of the list + //order of planes is important, keep most likely to fail in the front of the list - //near - frust[0], frust[1], frust[2] - mAgentPlanes[AGENT_PLANE_NEAR] = planeFromPoints(frust[0], frust[1], frust[2]); + //near - frust[0], frust[1], frust[2] + mAgentPlanes[AGENT_PLANE_NEAR] = planeFromPoints(frust[0], frust[1], frust[2]); - //far - mAgentPlanes[AGENT_PLANE_FAR] = planeFromPoints(frust[5], frust[4], frust[6]); + //far + mAgentPlanes[AGENT_PLANE_FAR] = planeFromPoints(frust[5], frust[4], frust[6]); - //left - mAgentPlanes[AGENT_PLANE_LEFT] = planeFromPoints(frust[4], frust[0], frust[7]); + //left + mAgentPlanes[AGENT_PLANE_LEFT] = planeFromPoints(frust[4], frust[0], frust[7]); - //right - mAgentPlanes[AGENT_PLANE_RIGHT] = planeFromPoints(frust[1], frust[5], frust[6]); + //right + mAgentPlanes[AGENT_PLANE_RIGHT] = planeFromPoints(frust[1], frust[5], frust[6]); - //top - mAgentPlanes[AGENT_PLANE_TOP] = planeFromPoints(frust[3], frust[2], frust[6]); + //top + mAgentPlanes[AGENT_PLANE_TOP] = planeFromPoints(frust[3], frust[2], frust[6]); - //bottom - mAgentPlanes[AGENT_PLANE_BOTTOM] = planeFromPoints(frust[1], frust[0], frust[4]); + //bottom + mAgentPlanes[AGENT_PLANE_BOTTOM] = planeFromPoints(frust[1], frust[0], frust[4]); - //cache plane octant facing mask for use in AABBInFrustum - for (U32 i = 0; i < mPlaneCount; i++) - { - mPlaneMask[i] = mAgentPlanes[i].calcPlaneMask(); - } + //cache plane octant facing mask for use in AABBInFrustum + for (U32 i = 0; i < mPlaneCount; i++) + { + mPlaneMask[i] = mAgentPlanes[i].calcPlaneMask(); + } } //calculate regional planes from mAgentPlanes. //vector "shift" is the vector of the region origin in the agent space. -void LLCamera::calcRegionFrustumPlanes(const LLVector3& shift, F32 far_clip_distance) -{ - F32 far_w; - { - LLVector3 p = getOrigin(); - LLVector3 n(mAgentPlanes[5][0], mAgentPlanes[5][1], mAgentPlanes[5][2]); - F32 dd = n * p; - if(dd + mAgentPlanes[5][3] < 0) //signed distance - { - far_w = -far_clip_distance - dd; - } - else - { - far_w = far_clip_distance - dd; - } - far_w += n * shift; - } - - F32 d; - LLVector3 n; - for(S32 i = 0 ; i < 7; i++) - { - if (mPlaneMask[i] != 0xff) - { - n.setVec(mAgentPlanes[i][0], mAgentPlanes[i][1], mAgentPlanes[i][2]); - - if(i != 5) - { - d = mAgentPlanes[i][3] + n * shift; - } - else - { - d = far_w; - } - mRegionPlanes[i].setVec(n, d); - } - } +void LLCamera::calcRegionFrustumPlanes(const LLVector3& shift, F32 far_clip_distance) +{ + F32 far_w; + { + LLVector3 p = getOrigin(); + LLVector3 n(mAgentPlanes[5][0], mAgentPlanes[5][1], mAgentPlanes[5][2]); + F32 dd = n * p; + if(dd + mAgentPlanes[5][3] < 0) //signed distance + { + far_w = -far_clip_distance - dd; + } + else + { + far_w = far_clip_distance - dd; + } + far_w += n * shift; + } + + F32 d; + LLVector3 n; + for(S32 i = 0 ; i < 7; i++) + { + if (mPlaneMask[i] != 0xff) + { + n.setVec(mAgentPlanes[i][0], mAgentPlanes[i][1], mAgentPlanes[i][2]); + + if(i != 5) + { + d = mAgentPlanes[i][3] + n * shift; + } + else + { + d = far_w; + } + mRegionPlanes[i].setVec(n, d); + } + } } void LLCamera::calculateFrustumPlanes(F32 left, F32 right, F32 top, F32 bottom) { - //calculate center and radius squared of frustum in world absolute coordinates - static LLVector3 const X_AXIS(1.f, 0.f, 0.f); - mFrustCenter = X_AXIS*mFarPlane*0.5f; - mFrustCenter = transformToAbsolute(mFrustCenter); - mFrustRadiusSquared = mFarPlane*0.5f; - mFrustRadiusSquared *= mFrustRadiusSquared * 1.05f; //pad radius squared by 5% + //calculate center and radius squared of frustum in world absolute coordinates + static LLVector3 const X_AXIS(1.f, 0.f, 0.f); + mFrustCenter = X_AXIS*mFarPlane*0.5f; + mFrustCenter = transformToAbsolute(mFrustCenter); + mFrustRadiusSquared = mFarPlane*0.5f; + mFrustRadiusSquared *= mFrustRadiusSquared * 1.05f; //pad radius squared by 5% } // x and y are in WINDOW space, so x = Y-Axis (left/right), y= Z-Axis(Up/Down) void LLCamera::calculateFrustumPlanesFromWindow(F32 x1, F32 y1, F32 x2, F32 y2) { - F32 bottom, top, left, right; - F32 view_height = (F32)tanf(0.5f * mView) * mFarPlane; - F32 view_width = view_height * mAspect; - - left = x1 * -2.f * view_width; - right = x2 * -2.f * view_width; - bottom = y1 * 2.f * view_height; - top = y2 * 2.f * view_height; + F32 bottom, top, left, right; + F32 view_height = (F32)tanf(0.5f * mView) * mFarPlane; + F32 view_width = view_height * mAspect; + + left = x1 * -2.f * view_width; + right = x2 * -2.f * view_width; + bottom = y1 * 2.f * view_height; + top = y2 * 2.f * view_height; - calculateFrustumPlanes(left, right, top, bottom); + calculateFrustumPlanes(left, right, top, bottom); } -// NOTE: this is the OpenGL matrix that will transform the default OpenGL view +// NOTE: this is the OpenGL matrix that will transform the default OpenGL view // (-Z=at, Y=up) to the default view of the LLCamera class (X=at, Z=up): -// +// // F32 cfr_transform = { 0.f, 0.f, -1.f, 0.f, // -Z becomes X -// -1.f, 0.f, 0.f, 0.f, // -X becomes Y -// 0.f, 1.f, 0.f, 0.f, // Y becomes Z -// 0.f, 0.f, 0.f, 1.f }; +// -1.f, 0.f, 0.f, 0.f, // -X becomes Y +// 0.f, 1.f, 0.f, 0.f, // Y becomes Z +// 0.f, 0.f, 0.f, 1.f }; diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h index e1d3536f66..b6e0e4a2be 100644 --- a/indra/llmath/llcamera.h +++ b/indra/llmath/llcamera.h @@ -1,25 +1,25 @@ -/** +/** * @file llcamera.h * @brief Header file for the LLCamera class. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -33,26 +33,26 @@ #include "llplane.h" #include "llvector4a.h" -const F32 DEFAULT_FIELD_OF_VIEW = 60.f * DEG_TO_RAD; -const F32 DEFAULT_ASPECT_RATIO = 640.f / 480.f; -const F32 DEFAULT_NEAR_PLANE = 0.25f; -const F32 DEFAULT_FAR_PLANE = 64.f; // far reaches across two horizontal, not diagonal, regions +const F32 DEFAULT_FIELD_OF_VIEW = 60.f * DEG_TO_RAD; +const F32 DEFAULT_ASPECT_RATIO = 640.f / 480.f; +const F32 DEFAULT_NEAR_PLANE = 0.25f; +const F32 DEFAULT_FAR_PLANE = 64.f; // far reaches across two horizontal, not diagonal, regions -const F32 MAX_ASPECT_RATIO = 50.0f; -const F32 MAX_NEAR_PLANE = 1023.9f; // Clamp the near plane just before the skybox ends -const F32 MAX_FAR_PLANE = 100000.0f; //1000000.0f; // Max allowed. Not good Z precision though. -const F32 MAX_FAR_CLIP = 512.0f; +const F32 MAX_ASPECT_RATIO = 50.0f; +const F32 MAX_NEAR_PLANE = 1023.9f; // Clamp the near plane just before the skybox ends +const F32 MAX_FAR_PLANE = 100000.0f; //1000000.0f; // Max allowed. Not good Z precision though. +const F32 MAX_FAR_CLIP = 512.0f; -const F32 MIN_ASPECT_RATIO = 0.02f; -const F32 MIN_NEAR_PLANE = 0.1f; -const F32 MIN_FAR_PLANE = 0.2f; +const F32 MIN_ASPECT_RATIO = 0.02f; +const F32 MIN_NEAR_PLANE = 0.1f; +const F32 MIN_FAR_PLANE = 0.2f; // Min/Max FOV values for square views. Call getMin/MaxView to get extremes based on current aspect ratio. static const F32 MIN_FIELD_OF_VIEW = 5.0f * DEG_TO_RAD; static const F32 MAX_FIELD_OF_VIEW = 175.f * DEG_TO_RAD; // An LLCamera is an LLCoorFrame with a view frustum. -// This means that it has several methods for moving it around +// This means that it has several methods for moving it around // that are inherited from the LLCoordFrame() class : // // setOrigin(), setAxes() @@ -62,162 +62,162 @@ static const F32 MAX_FIELD_OF_VIEW = 175.f * DEG_TO_RAD; LL_ALIGN_PREFIX(16) class LLCamera -: public LLCoordFrame +: public LLCoordFrame { public: - LLCamera(const LLCamera& rhs) - { - *this = rhs; - } - - enum { - PLANE_LEFT = 0, - PLANE_RIGHT = 1, - PLANE_BOTTOM = 2, - PLANE_TOP = 3, - PLANE_NUM = 4, - PLANE_MASK_NONE = 0xff // Disable this plane - }; - enum { - PLANE_LEFT_MASK = (1<<PLANE_LEFT), - PLANE_RIGHT_MASK = (1<<PLANE_RIGHT), - PLANE_BOTTOM_MASK = (1<<PLANE_BOTTOM), - PLANE_TOP_MASK = (1<<PLANE_TOP), - PLANE_ALL_MASK = 0xf, - }; - - enum - { // Indexes to mAgentPlanes[] and mPlaneMask[] - AGENT_PLANE_LEFT = 0, - AGENT_PLANE_RIGHT = 1, - AGENT_PLANE_NEAR = 2, - AGENT_PLANE_BOTTOM = 3, - AGENT_PLANE_TOP = 4, - AGENT_PLANE_FAR = 5, - AGENT_PLANE_USER_CLIP = 6 - }; - enum - { // Sizes for mAgentPlanes[]. 7th entry is special case for user clip - AGENT_PLANE_NO_USER_CLIP_NUM = 6, - AGENT_PLANE_USER_CLIP_NUM = 7, - PLANE_MASK_NUM = 8 // 7 actually used, 8 is for alignment - }; - - enum - { - AGENT_FRUSTRUM_NUM = 8 - }; - - enum { - HORIZ_PLANE_LEFT = 0, - HORIZ_PLANE_RIGHT = 1, - HORIZ_PLANE_NUM = 2 - }; - enum { - HORIZ_PLANE_LEFT_MASK = (1<<HORIZ_PLANE_LEFT), - HORIZ_PLANE_RIGHT_MASK = (1<<HORIZ_PLANE_RIGHT), - HORIZ_PLANE_ALL_MASK = 0x3 - }; + LLCamera(const LLCamera& rhs) + { + *this = rhs; + } + + enum { + PLANE_LEFT = 0, + PLANE_RIGHT = 1, + PLANE_BOTTOM = 2, + PLANE_TOP = 3, + PLANE_NUM = 4, + PLANE_MASK_NONE = 0xff // Disable this plane + }; + enum { + PLANE_LEFT_MASK = (1<<PLANE_LEFT), + PLANE_RIGHT_MASK = (1<<PLANE_RIGHT), + PLANE_BOTTOM_MASK = (1<<PLANE_BOTTOM), + PLANE_TOP_MASK = (1<<PLANE_TOP), + PLANE_ALL_MASK = 0xf, + }; + + enum + { // Indexes to mAgentPlanes[] and mPlaneMask[] + AGENT_PLANE_LEFT = 0, + AGENT_PLANE_RIGHT = 1, + AGENT_PLANE_NEAR = 2, + AGENT_PLANE_BOTTOM = 3, + AGENT_PLANE_TOP = 4, + AGENT_PLANE_FAR = 5, + AGENT_PLANE_USER_CLIP = 6 + }; + enum + { // Sizes for mAgentPlanes[]. 7th entry is special case for user clip + AGENT_PLANE_NO_USER_CLIP_NUM = 6, + AGENT_PLANE_USER_CLIP_NUM = 7, + PLANE_MASK_NUM = 8 // 7 actually used, 8 is for alignment + }; + + enum + { + AGENT_FRUSTRUM_NUM = 8 + }; + + enum { + HORIZ_PLANE_LEFT = 0, + HORIZ_PLANE_RIGHT = 1, + HORIZ_PLANE_NUM = 2 + }; + enum { + HORIZ_PLANE_LEFT_MASK = (1<<HORIZ_PLANE_LEFT), + HORIZ_PLANE_RIGHT_MASK = (1<<HORIZ_PLANE_RIGHT), + HORIZ_PLANE_ALL_MASK = 0x3 + }; private: - LL_ALIGN_16(LLPlane mAgentPlanes[AGENT_PLANE_USER_CLIP_NUM]); //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP - LL_ALIGN_16(LLPlane mRegionPlanes[AGENT_PLANE_USER_CLIP_NUM]); //frustum planes in a local region space, derived from mAgentPlanes - LL_ALIGN_16(LLPlane mLastAgentPlanes[AGENT_PLANE_USER_CLIP_NUM]); - U8 mPlaneMask[PLANE_MASK_NUM]; // 8 for alignment - - F32 mView; // angle between top and bottom frustum planes in radians. - F32 mAspect; // width/height - S32 mViewHeightInPixels; // for ViewHeightInPixels() only - F32 mNearPlane; - F32 mFarPlane; - F32 mFixedDistance; // Always return this distance, unless < 0 - LLVector3 mFrustCenter; // center of frustum and radius squared for ultra-quick exclusion test - F32 mFrustRadiusSquared; - - U32 mPlaneCount; //defaults to 6, if setUserClipPlane is called, uses user supplied clip plane in - - LLVector3 mWorldPlanePos; // Position of World Planes (may be offset from camera) + LL_ALIGN_16(LLPlane mAgentPlanes[AGENT_PLANE_USER_CLIP_NUM]); //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP + LL_ALIGN_16(LLPlane mRegionPlanes[AGENT_PLANE_USER_CLIP_NUM]); //frustum planes in a local region space, derived from mAgentPlanes + LL_ALIGN_16(LLPlane mLastAgentPlanes[AGENT_PLANE_USER_CLIP_NUM]); + U8 mPlaneMask[PLANE_MASK_NUM]; // 8 for alignment + + F32 mView; // angle between top and bottom frustum planes in radians. + F32 mAspect; // width/height + S32 mViewHeightInPixels; // for ViewHeightInPixels() only + F32 mNearPlane; + F32 mFarPlane; + F32 mFixedDistance; // Always return this distance, unless < 0 + LLVector3 mFrustCenter; // center of frustum and radius squared for ultra-quick exclusion test + F32 mFrustRadiusSquared; + + U32 mPlaneCount; //defaults to 6, if setUserClipPlane is called, uses user supplied clip plane in + + LLVector3 mWorldPlanePos; // Position of World Planes (may be offset from camera) public: - LLVector3 mAgentFrustum[AGENT_FRUSTRUM_NUM]; //8 corners of 6-plane frustum - F32 mFrustumCornerDist; //distance to corner of frustum against far clip plane - LLPlane& getAgentPlane(U32 idx) { return mAgentPlanes[idx]; } + LLVector3 mAgentFrustum[AGENT_FRUSTRUM_NUM]; //8 corners of 6-plane frustum + F32 mFrustumCornerDist; //distance to corner of frustum against far clip plane + LLPlane& getAgentPlane(U32 idx) { return mAgentPlanes[idx]; } public: - LLCamera(); - LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane); - virtual ~LLCamera(); - - bool isChanged(); //check if mAgentPlanes changed since last frame. + LLCamera(); + LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane); + virtual ~LLCamera(); + + bool isChanged(); //check if mAgentPlanes changed since last frame. LLPlane getUserClipPlane(); - void setUserClipPlane(LLPlane& plane); - void disableUserClipPlane(); - virtual void setView(F32 vertical_fov_rads); - void setViewHeightInPixels(S32 height); - void setAspect(F32 new_aspect); - void setNear(F32 new_near); - void setFar(F32 new_far); - - F32 getView() const { return mView; } // vertical FOV in radians - S32 getViewHeightInPixels() const { return mViewHeightInPixels; } - F32 getAspect() const { return mAspect; } // width / height - F32 getNear() const { return mNearPlane; } // meters - F32 getFar() const { return mFarPlane; } // meters - - // The values returned by the min/max view getters depend upon the aspect ratio - // at the time they are called and therefore should not be cached. - F32 getMinView() const; - F32 getMaxView() const; - - F32 getYaw() const - { - return atan2f(mXAxis[VY], mXAxis[VX]); - } - F32 getPitch() const - { - F32 xylen = sqrtf(mXAxis[VX]*mXAxis[VX] + mXAxis[VY]*mXAxis[VY]); - return atan2f(mXAxis[VZ], xylen); - } - - const LLVector3& getWorldPlanePos() const { return mWorldPlanePos; } - - // Copy mView, mAspect, mNearPlane, and mFarPlane to buffer. - // Return number of bytes copied. - size_t writeFrustumToBuffer(char *buffer) const; - - // Copy mView, mAspect, mNearPlane, and mFarPlane from buffer. - // Return number of bytes copied. - size_t readFrustumFromBuffer(const char *buffer); - void calcAgentFrustumPlanes(LLVector3* frust); - void calcRegionFrustumPlanes(const LLVector3& shift, F32 far_clip_distance); //calculate regional planes from mAgentPlanes. - void ignoreAgentFrustumPlane(S32 idx); - - // Returns 1 if partly in, 2 if fully in. - // NOTE: 'center' is in absolute frame. - S32 sphereInFrustum(const LLVector3 ¢er, const F32 radius) const; - S32 pointInFrustum(const LLVector3 &point) const { return sphereInFrustum(point, 0.0f); } - S32 sphereInFrustumFull(const LLVector3 ¢er, const F32 radius) const { return sphereInFrustum(center, radius); } - S32 AABBInFrustum(const LLVector4a& center, const LLVector4a& radius, const LLPlane* planes = NULL); - S32 AABBInRegionFrustum(const LLVector4a& center, const LLVector4a& radius); - S32 AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius, const LLPlane* planes = NULL); - S32 AABBInRegionFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius); - - //does a quick 'n dirty sphere-sphere check - S32 sphereInFrustumQuick(const LLVector3 &sphere_center, const F32 radius); - - // Returns height of object in pixels (must be height because field of view - // is based on window height). - F32 heightInPixels(const LLVector3 ¢er, F32 radius ) const; - - // return the distance from pos to camera if visible (-distance if not visible) - void setFixedDistance(F32 distance) { mFixedDistance = distance; } - - friend std::ostream& operator<<(std::ostream &s, const LLCamera &C); + void setUserClipPlane(LLPlane& plane); + void disableUserClipPlane(); + virtual void setView(F32 vertical_fov_rads); + void setViewHeightInPixels(S32 height); + void setAspect(F32 new_aspect); + void setNear(F32 new_near); + void setFar(F32 new_far); + + F32 getView() const { return mView; } // vertical FOV in radians + S32 getViewHeightInPixels() const { return mViewHeightInPixels; } + F32 getAspect() const { return mAspect; } // width / height + F32 getNear() const { return mNearPlane; } // meters + F32 getFar() const { return mFarPlane; } // meters + + // The values returned by the min/max view getters depend upon the aspect ratio + // at the time they are called and therefore should not be cached. + F32 getMinView() const; + F32 getMaxView() const; + + F32 getYaw() const + { + return atan2f(mXAxis[VY], mXAxis[VX]); + } + F32 getPitch() const + { + F32 xylen = sqrtf(mXAxis[VX]*mXAxis[VX] + mXAxis[VY]*mXAxis[VY]); + return atan2f(mXAxis[VZ], xylen); + } + + const LLVector3& getWorldPlanePos() const { return mWorldPlanePos; } + + // Copy mView, mAspect, mNearPlane, and mFarPlane to buffer. + // Return number of bytes copied. + size_t writeFrustumToBuffer(char *buffer) const; + + // Copy mView, mAspect, mNearPlane, and mFarPlane from buffer. + // Return number of bytes copied. + size_t readFrustumFromBuffer(const char *buffer); + void calcAgentFrustumPlanes(LLVector3* frust); + void calcRegionFrustumPlanes(const LLVector3& shift, F32 far_clip_distance); //calculate regional planes from mAgentPlanes. + void ignoreAgentFrustumPlane(S32 idx); + + // Returns 1 if partly in, 2 if fully in. + // NOTE: 'center' is in absolute frame. + S32 sphereInFrustum(const LLVector3 ¢er, const F32 radius) const; + S32 pointInFrustum(const LLVector3 &point) const { return sphereInFrustum(point, 0.0f); } + S32 sphereInFrustumFull(const LLVector3 ¢er, const F32 radius) const { return sphereInFrustum(center, radius); } + S32 AABBInFrustum(const LLVector4a& center, const LLVector4a& radius, const LLPlane* planes = NULL); + S32 AABBInRegionFrustum(const LLVector4a& center, const LLVector4a& radius); + S32 AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius, const LLPlane* planes = NULL); + S32 AABBInRegionFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius); + + //does a quick 'n dirty sphere-sphere check + S32 sphereInFrustumQuick(const LLVector3 &sphere_center, const F32 radius); + + // Returns height of object in pixels (must be height because field of view + // is based on window height). + F32 heightInPixels(const LLVector3 ¢er, F32 radius ) const; + + // return the distance from pos to camera if visible (-distance if not visible) + void setFixedDistance(F32 distance) { mFixedDistance = distance; } + + friend std::ostream& operator<<(std::ostream &s, const LLCamera &C); protected: - void calculateFrustumPlanes(); - void calculateFrustumPlanes(F32 left, F32 right, F32 top, F32 bottom); - void calculateFrustumPlanesFromWindow(F32 x1, F32 y1, F32 x2, F32 y2); + void calculateFrustumPlanes(); + void calculateFrustumPlanes(F32 left, F32 right, F32 top, F32 bottom); + void calculateFrustumPlanesFromWindow(F32 x1, F32 y1, F32 x2, F32 y2); } LL_ALIGN_POSTFIX(16); diff --git a/indra/llmath/llcoord.h b/indra/llmath/llcoord.h index 9b76268afd..120556c9fe 100644 --- a/indra/llmath/llcoord.h +++ b/indra/llmath/llcoord.h @@ -1,24 +1,24 @@ -/** +/** * @file llcoord.h * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -37,10 +37,10 @@ typedef LLCoord<LL_COORD_TYPE_SCREEN> LLCoordScreen; struct LLCoordCommon { - LLCoordCommon(S32 x, S32 y) : mX(x), mY(y) {} - LLCoordCommon() : mX(0), mY(0) {} - S32 mX; - S32 mY; + LLCoordCommon(S32 x, S32 y) : mX(x), mY(y) {} + LLCoordCommon() : mX(0), mY(0) {} + S32 mX; + S32 mY; }; // A two-dimensional pixel value @@ -48,65 +48,65 @@ template<typename COORD_FRAME> class LLCoord : protected COORD_FRAME { public: - typedef LLCoord<COORD_FRAME> self_t; - typename COORD_FRAME::value_t mX; - typename COORD_FRAME::value_t mY; - - LLCoord(): mX(0), mY(0) - {} - LLCoord(typename COORD_FRAME::value_t x, typename COORD_FRAME::value_t y): mX(x), mY(y) - {} - - LLCoord(const LLCoordCommon& other) - { - COORD_FRAME::convertFromCommon(other); - } - - LLCoordCommon convert() const - { - return COORD_FRAME::convertToCommon(); - } - - void set(typename COORD_FRAME::value_t x, typename COORD_FRAME::value_t y) { mX = x; mY = y;} - bool operator==(const self_t& other) const { return mX == other.mX && mY == other.mY; } - bool operator!=(const self_t& other) const { return !(*this == other); } - - static const self_t& getTypedCoords(const COORD_FRAME& self) { return static_cast<const self_t&>(self); } - static self_t& getTypedCoords(COORD_FRAME& self) { return static_cast<self_t&>(self); } + typedef LLCoord<COORD_FRAME> self_t; + typename COORD_FRAME::value_t mX; + typename COORD_FRAME::value_t mY; + + LLCoord(): mX(0), mY(0) + {} + LLCoord(typename COORD_FRAME::value_t x, typename COORD_FRAME::value_t y): mX(x), mY(y) + {} + + LLCoord(const LLCoordCommon& other) + { + COORD_FRAME::convertFromCommon(other); + } + + LLCoordCommon convert() const + { + return COORD_FRAME::convertToCommon(); + } + + void set(typename COORD_FRAME::value_t x, typename COORD_FRAME::value_t y) { mX = x; mY = y;} + bool operator==(const self_t& other) const { return mX == other.mX && mY == other.mY; } + bool operator!=(const self_t& other) const { return !(*this == other); } + + static const self_t& getTypedCoords(const COORD_FRAME& self) { return static_cast<const self_t&>(self); } + static self_t& getTypedCoords(COORD_FRAME& self) { return static_cast<self_t&>(self); } }; -struct LL_COORD_TYPE_GL +struct LL_COORD_TYPE_GL { - typedef S32 value_t; - - LLCoordCommon convertToCommon() const - { - const LLCoordGL& self = LLCoordGL::getTypedCoords(*this); - return LLCoordCommon(self.mX, self.mY); - } - - void convertFromCommon(const LLCoordCommon& from) - { - LLCoordGL& self = LLCoordGL::getTypedCoords(*this); - self.mX = from.mX; - self.mY = from.mY; - } + typedef S32 value_t; + + LLCoordCommon convertToCommon() const + { + const LLCoordGL& self = LLCoordGL::getTypedCoords(*this); + return LLCoordCommon(self.mX, self.mY); + } + + void convertFromCommon(const LLCoordCommon& from) + { + LLCoordGL& self = LLCoordGL::getTypedCoords(*this); + self.mX = from.mX; + self.mY = from.mY; + } }; -struct LL_COORD_TYPE_WINDOW +struct LL_COORD_TYPE_WINDOW { - typedef S32 value_t; + typedef S32 value_t; - LLCoordCommon convertToCommon() const; - void convertFromCommon(const LLCoordCommon& from); + LLCoordCommon convertToCommon() const; + void convertFromCommon(const LLCoordCommon& from); }; -struct LL_COORD_TYPE_SCREEN +struct LL_COORD_TYPE_SCREEN { - typedef S32 value_t; + typedef S32 value_t; - LLCoordCommon convertToCommon() const; - void convertFromCommon(const LLCoordCommon& from); + LLCoordCommon convertToCommon() const; + void convertFromCommon(const LLCoordCommon& from); }; #endif diff --git a/indra/llmath/llcoordframe.cpp b/indra/llmath/llcoordframe.cpp index b25fd948f5..4d6276b2cd 100644 --- a/indra/llmath/llcoordframe.cpp +++ b/indra/llmath/llcoordframe.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llcoordframe.cpp * @brief LLCoordFrame class implementation. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -49,168 +49,168 @@ } #ifndef X_AXIS - #define X_AXIS 1.0f,0.0f,0.0f - #define Y_AXIS 0.0f,1.0f,0.0f - #define Z_AXIS 0.0f,0.0f,1.0f + #define X_AXIS 1.0f,0.0f,0.0f + #define Y_AXIS 0.0f,1.0f,0.0f + #define Z_AXIS 0.0f,0.0f,1.0f #endif // Constructors LLCoordFrame::LLCoordFrame() : - mOrigin(0.f, 0.f, 0.f), - mXAxis(X_AXIS), - mYAxis(Y_AXIS), - mZAxis(Z_AXIS) + mOrigin(0.f, 0.f, 0.f), + mXAxis(X_AXIS), + mYAxis(Y_AXIS), + mZAxis(Z_AXIS) { } LLCoordFrame::LLCoordFrame(const LLVector3 &origin) : - mOrigin(origin), - mXAxis(X_AXIS), - mYAxis(Y_AXIS), - mZAxis(Z_AXIS) + mOrigin(origin), + mXAxis(X_AXIS), + mYAxis(Y_AXIS), + mZAxis(Z_AXIS) { CHECK_FINITE(mOrigin); } LLCoordFrame::LLCoordFrame(const LLVector3 &origin, const LLVector3 &direction) : - mOrigin(origin) + mOrigin(origin) { - lookDir(direction); - + lookDir(direction); + CHECK_FINITE_OBJ(); } LLCoordFrame::LLCoordFrame(const LLVector3 &x_axis, - const LLVector3 &y_axis, - const LLVector3 &z_axis) : - mOrigin(0.f, 0.f, 0.f), - mXAxis(x_axis), - mYAxis(y_axis), - mZAxis(z_axis) + const LLVector3 &y_axis, + const LLVector3 &z_axis) : + mOrigin(0.f, 0.f, 0.f), + mXAxis(x_axis), + mYAxis(y_axis), + mZAxis(z_axis) { - CHECK_FINITE_OBJ(); + CHECK_FINITE_OBJ(); } LLCoordFrame::LLCoordFrame(const LLVector3 &origin, - const LLVector3 &x_axis, - const LLVector3 &y_axis, - const LLVector3 &z_axis) : - mOrigin(origin), - mXAxis(x_axis), - mYAxis(y_axis), - mZAxis(z_axis) + const LLVector3 &x_axis, + const LLVector3 &y_axis, + const LLVector3 &z_axis) : + mOrigin(origin), + mXAxis(x_axis), + mYAxis(y_axis), + mZAxis(z_axis) { - CHECK_FINITE_OBJ(); + CHECK_FINITE_OBJ(); } -LLCoordFrame::LLCoordFrame(const LLVector3 &origin, - const LLMatrix3 &rotation) : - mOrigin(origin), - mXAxis(rotation.mMatrix[VX]), - mYAxis(rotation.mMatrix[VY]), - mZAxis(rotation.mMatrix[VZ]) +LLCoordFrame::LLCoordFrame(const LLVector3 &origin, + const LLMatrix3 &rotation) : + mOrigin(origin), + mXAxis(rotation.mMatrix[VX]), + mYAxis(rotation.mMatrix[VY]), + mZAxis(rotation.mMatrix[VZ]) { - CHECK_FINITE_OBJ(); + CHECK_FINITE_OBJ(); } LLCoordFrame::LLCoordFrame(const LLQuaternion &q) : - mOrigin(0.f, 0.f, 0.f) + mOrigin(0.f, 0.f, 0.f) { - LLMatrix3 rotation_matrix(q); - mXAxis.setVec(rotation_matrix.mMatrix[VX]); - mYAxis.setVec(rotation_matrix.mMatrix[VY]); - mZAxis.setVec(rotation_matrix.mMatrix[VZ]); + LLMatrix3 rotation_matrix(q); + mXAxis.setVec(rotation_matrix.mMatrix[VX]); + mYAxis.setVec(rotation_matrix.mMatrix[VY]); + mZAxis.setVec(rotation_matrix.mMatrix[VZ]); - CHECK_FINITE_OBJ(); + CHECK_FINITE_OBJ(); } LLCoordFrame::LLCoordFrame(const LLVector3 &origin, const LLQuaternion &q) : - mOrigin(origin) + mOrigin(origin) { - LLMatrix3 rotation_matrix(q); - mXAxis.setVec(rotation_matrix.mMatrix[VX]); - mYAxis.setVec(rotation_matrix.mMatrix[VY]); - mZAxis.setVec(rotation_matrix.mMatrix[VZ]); + LLMatrix3 rotation_matrix(q); + mXAxis.setVec(rotation_matrix.mMatrix[VX]); + mYAxis.setVec(rotation_matrix.mMatrix[VY]); + mZAxis.setVec(rotation_matrix.mMatrix[VZ]); - CHECK_FINITE_OBJ(); + CHECK_FINITE_OBJ(); } LLCoordFrame::LLCoordFrame(const LLMatrix4 &mat) : - mOrigin(mat.mMatrix[VW]), - mXAxis(mat.mMatrix[VX]), - mYAxis(mat.mMatrix[VY]), - mZAxis(mat.mMatrix[VZ]) + mOrigin(mat.mMatrix[VW]), + mXAxis(mat.mMatrix[VX]), + mYAxis(mat.mMatrix[VY]), + mZAxis(mat.mMatrix[VZ]) { - CHECK_FINITE_OBJ(); + CHECK_FINITE_OBJ(); } // The folowing two constructors are dangerous due to implicit casting and have been disabled - SJB /* LLCoordFrame::LLCoordFrame(const F32 *origin, const F32 *rotation) : - mOrigin(origin), - mXAxis(rotation+3*VX), - mYAxis(rotation+3*VY), - mZAxis(rotation+3*VZ) + mOrigin(origin), + mXAxis(rotation+3*VX), + mYAxis(rotation+3*VY), + mZAxis(rotation+3*VZ) { - CHECK_FINITE_OBJ(); + CHECK_FINITE_OBJ(); } */ /* LLCoordFrame::LLCoordFrame(const F32 *origin_and_rotation) : - mOrigin(origin_and_rotation), - mXAxis(origin_and_rotation + 3*(VX+1)), - mYAxis(origin_and_rotation + 3*(VY+1)), - mZAxis(origin_and_rotation + 3*(VZ+1)) + mOrigin(origin_and_rotation), + mXAxis(origin_and_rotation + 3*(VX+1)), + mYAxis(origin_and_rotation + 3*(VY+1)), + mZAxis(origin_and_rotation + 3*(VZ+1)) { - CHECK_FINITE_OBJ(); + CHECK_FINITE_OBJ(); } */ -void LLCoordFrame::reset() +void LLCoordFrame::reset() { - mOrigin.setVec(0.0f, 0.0f, 0.0f); - resetAxes(); + mOrigin.setVec(0.0f, 0.0f, 0.0f); + resetAxes(); } void LLCoordFrame::resetAxes() { - mXAxis.setVec(1.0f, 0.0f, 0.0f); - mYAxis.setVec(0.0f, 1.0f, 0.0f); - mZAxis.setVec(0.0f, 0.0f, 1.0f); + mXAxis.setVec(1.0f, 0.0f, 0.0f); + mYAxis.setVec(0.0f, 1.0f, 0.0f); + mZAxis.setVec(0.0f, 0.0f, 1.0f); } // setOrigin() member functions set mOrigin -void LLCoordFrame::setOrigin(F32 x, F32 y, F32 z) +void LLCoordFrame::setOrigin(F32 x, F32 y, F32 z) { - mOrigin.setVec(x, y, z); + mOrigin.setVec(x, y, z); CHECK_FINITE(mOrigin); } void LLCoordFrame::setOrigin(const LLVector3 &new_origin) { - mOrigin = new_origin; - CHECK_FINITE(mOrigin); + mOrigin = new_origin; + CHECK_FINITE(mOrigin); } void LLCoordFrame::setOrigin(const F32 *origin) { - mOrigin.mV[VX] = *(origin + VX); - mOrigin.mV[VY] = *(origin + VY); - mOrigin.mV[VZ] = *(origin + VZ); + mOrigin.mV[VX] = *(origin + VX); + mOrigin.mV[VY] = *(origin + VY); + mOrigin.mV[VZ] = *(origin + VZ); CHECK_FINITE(mOrigin); } void LLCoordFrame::setOrigin(const LLCoordFrame &frame) { - mOrigin = frame.getOrigin(); + mOrigin = frame.getOrigin(); CHECK_FINITE(mOrigin); } @@ -218,79 +218,79 @@ void LLCoordFrame::setOrigin(const LLCoordFrame &frame) // the arguments are orthogonal and normalized. void LLCoordFrame::setAxes(const LLVector3 &x_axis, - const LLVector3 &y_axis, - const LLVector3 &z_axis) + const LLVector3 &y_axis, + const LLVector3 &z_axis) { - mXAxis = x_axis; - mYAxis = y_axis; - mZAxis = z_axis; - CHECK_FINITE_OBJ(); + mXAxis = x_axis; + mYAxis = y_axis; + mZAxis = z_axis; + CHECK_FINITE_OBJ(); } void LLCoordFrame::setAxes(const LLMatrix3 &rotation_matrix) { - mXAxis.setVec(rotation_matrix.mMatrix[VX]); - mYAxis.setVec(rotation_matrix.mMatrix[VY]); - mZAxis.setVec(rotation_matrix.mMatrix[VZ]); - CHECK_FINITE_OBJ(); + mXAxis.setVec(rotation_matrix.mMatrix[VX]); + mYAxis.setVec(rotation_matrix.mMatrix[VY]); + mZAxis.setVec(rotation_matrix.mMatrix[VZ]); + CHECK_FINITE_OBJ(); } void LLCoordFrame::setAxes(const LLQuaternion &q ) { - LLMatrix3 rotation_matrix(q); - setAxes(rotation_matrix); - CHECK_FINITE_OBJ(); + LLMatrix3 rotation_matrix(q); + setAxes(rotation_matrix); + CHECK_FINITE_OBJ(); } -void LLCoordFrame::setAxes( const F32 *rotation_matrix ) +void LLCoordFrame::setAxes( const F32 *rotation_matrix ) { - mXAxis.mV[VX] = *(rotation_matrix + 3*VX + VX); - mXAxis.mV[VY] = *(rotation_matrix + 3*VX + VY); - mXAxis.mV[VZ] = *(rotation_matrix + 3*VX + VZ); - mYAxis.mV[VX] = *(rotation_matrix + 3*VY + VX); - mYAxis.mV[VY] = *(rotation_matrix + 3*VY + VY); - mYAxis.mV[VZ] = *(rotation_matrix + 3*VY + VZ); - mZAxis.mV[VX] = *(rotation_matrix + 3*VZ + VX); - mZAxis.mV[VY] = *(rotation_matrix + 3*VZ + VY); - mZAxis.mV[VZ] = *(rotation_matrix + 3*VZ + VZ); + mXAxis.mV[VX] = *(rotation_matrix + 3*VX + VX); + mXAxis.mV[VY] = *(rotation_matrix + 3*VX + VY); + mXAxis.mV[VZ] = *(rotation_matrix + 3*VX + VZ); + mYAxis.mV[VX] = *(rotation_matrix + 3*VY + VX); + mYAxis.mV[VY] = *(rotation_matrix + 3*VY + VY); + mYAxis.mV[VZ] = *(rotation_matrix + 3*VY + VZ); + mZAxis.mV[VX] = *(rotation_matrix + 3*VZ + VX); + mZAxis.mV[VY] = *(rotation_matrix + 3*VZ + VY); + mZAxis.mV[VZ] = *(rotation_matrix + 3*VZ + VZ); - CHECK_FINITE_OBJ(); + CHECK_FINITE_OBJ(); } void LLCoordFrame::setAxes(const LLCoordFrame &frame) { - mXAxis = frame.getXAxis(); - mYAxis = frame.getYAxis(); - mZAxis = frame.getZAxis(); - CHECK_FINITE_OBJ(); + mXAxis = frame.getXAxis(); + mYAxis = frame.getYAxis(); + mZAxis = frame.getZAxis(); + CHECK_FINITE_OBJ(); } // translate() member functions move mOrigin to a relative position void LLCoordFrame::translate(F32 x, F32 y, F32 z) { - mOrigin.mV[VX] += x; - mOrigin.mV[VY] += y; - mOrigin.mV[VZ] += z; + mOrigin.mV[VX] += x; + mOrigin.mV[VY] += y; + mOrigin.mV[VZ] += z; CHECK_FINITE(mOrigin); } void LLCoordFrame::translate(const LLVector3 &v) { - mOrigin += v; + mOrigin += v; CHECK_FINITE(mOrigin); } void LLCoordFrame::translate(const F32 *origin) { - mOrigin.mV[VX] += *(origin + VX); - mOrigin.mV[VY] += *(origin + VY); - mOrigin.mV[VZ] += *(origin + VZ); - CHECK_FINITE(mOrigin); + mOrigin.mV[VX] += *(origin + VX); + mOrigin.mV[VY] += *(origin + VY); + mOrigin.mV[VZ] += *(origin + VZ); + CHECK_FINITE(mOrigin); } @@ -298,58 +298,58 @@ void LLCoordFrame::translate(const F32 *origin) void LLCoordFrame::rotate(F32 angle, F32 x, F32 y, F32 z) { - LLQuaternion q(angle, LLVector3(x,y,z)); - rotate(q); + LLQuaternion q(angle, LLVector3(x,y,z)); + rotate(q); CHECK_FINITE_OBJ(); } void LLCoordFrame::rotate(F32 angle, const LLVector3 &rotation_axis) { - LLQuaternion q(angle, rotation_axis); - rotate(q); + LLQuaternion q(angle, rotation_axis); + rotate(q); CHECK_FINITE_OBJ(); } void LLCoordFrame::rotate(const LLQuaternion &q) { - LLMatrix3 rotation_matrix(q); - rotate(rotation_matrix); + LLMatrix3 rotation_matrix(q); + rotate(rotation_matrix); CHECK_FINITE_OBJ(); } void LLCoordFrame::rotate(const LLMatrix3 &rotation_matrix) { - mXAxis.rotVec(rotation_matrix); - mYAxis.rotVec(rotation_matrix); - orthonormalize(); + mXAxis.rotVec(rotation_matrix); + mYAxis.rotVec(rotation_matrix); + orthonormalize(); CHECK_FINITE_OBJ(); } void LLCoordFrame::roll(F32 angle) { - LLQuaternion q(angle, mXAxis); - LLMatrix3 rotation_matrix(q); - rotate(rotation_matrix); + LLQuaternion q(angle, mXAxis); + LLMatrix3 rotation_matrix(q); + rotate(rotation_matrix); CHECK_FINITE_OBJ(); } void LLCoordFrame::pitch(F32 angle) { - LLQuaternion q(angle, mYAxis); - LLMatrix3 rotation_matrix(q); - rotate(rotation_matrix); - CHECK_FINITE_OBJ(); + LLQuaternion q(angle, mYAxis); + LLMatrix3 rotation_matrix(q); + rotate(rotation_matrix); + CHECK_FINITE_OBJ(); } void LLCoordFrame::yaw(F32 angle) { - LLQuaternion q(angle, mZAxis); - LLMatrix3 rotation_matrix(q); - rotate(rotation_matrix); + LLQuaternion q(angle, mZAxis); + LLMatrix3 rotation_matrix(q); + rotate(rotation_matrix); CHECK_FINITE_OBJ(); } @@ -358,61 +358,61 @@ void LLCoordFrame::yaw(F32 angle) LLQuaternion LLCoordFrame::getQuaternion() const { - LLQuaternion quat(mXAxis, mYAxis, mZAxis); - return quat; + LLQuaternion quat(mXAxis, mYAxis, mZAxis); + return quat; } void LLCoordFrame::getMatrixToLocal(LLMatrix4& mat) const { - mat.setFwdCol(mXAxis); - mat.setLeftCol(mYAxis); - mat.setUpCol(mZAxis); + mat.setFwdCol(mXAxis); + mat.setLeftCol(mYAxis); + mat.setUpCol(mZAxis); - mat.mMatrix[3][0] = -(mOrigin * LLVector3(mat.mMatrix[0][0], mat.mMatrix[1][0], mat.mMatrix[2][0])); - mat.mMatrix[3][1] = -(mOrigin * LLVector3(mat.mMatrix[0][1], mat.mMatrix[1][1], mat.mMatrix[2][1])); - mat.mMatrix[3][2] = -(mOrigin * LLVector3(mat.mMatrix[0][2], mat.mMatrix[1][2], mat.mMatrix[2][2])); + mat.mMatrix[3][0] = -(mOrigin * LLVector3(mat.mMatrix[0][0], mat.mMatrix[1][0], mat.mMatrix[2][0])); + mat.mMatrix[3][1] = -(mOrigin * LLVector3(mat.mMatrix[0][1], mat.mMatrix[1][1], mat.mMatrix[2][1])); + mat.mMatrix[3][2] = -(mOrigin * LLVector3(mat.mMatrix[0][2], mat.mMatrix[1][2], mat.mMatrix[2][2])); } void LLCoordFrame::getRotMatrixToParent(LLMatrix4& mat) const { - // Note: moves into CFR - mat.setFwdRow( -mYAxis ); - mat.setLeftRow( mZAxis ); - mat.setUpRow( -mXAxis ); + // Note: moves into CFR + mat.setFwdRow( -mYAxis ); + mat.setLeftRow( mZAxis ); + mat.setUpRow( -mXAxis ); } size_t LLCoordFrame::writeOrientation(char *buffer) const { - memcpy(buffer, mOrigin.mV, 3*sizeof(F32)); /*Flawfinder: ignore */ - buffer += 3*sizeof(F32); - memcpy(buffer, mXAxis.mV, 3*sizeof(F32)); /*Flawfinder: ignore */ - buffer += 3*sizeof(F32); - memcpy(buffer, mYAxis.mV, 3*sizeof(F32));/*Flawfinder: ignore */ - buffer += 3*sizeof(F32); - memcpy(buffer, mZAxis.mV, 3*sizeof(F32)); /*Flawfinder: ignore */ - return 12*sizeof(F32); + memcpy(buffer, mOrigin.mV, 3*sizeof(F32)); /*Flawfinder: ignore */ + buffer += 3*sizeof(F32); + memcpy(buffer, mXAxis.mV, 3*sizeof(F32)); /*Flawfinder: ignore */ + buffer += 3*sizeof(F32); + memcpy(buffer, mYAxis.mV, 3*sizeof(F32));/*Flawfinder: ignore */ + buffer += 3*sizeof(F32); + memcpy(buffer, mZAxis.mV, 3*sizeof(F32)); /*Flawfinder: ignore */ + return 12*sizeof(F32); } size_t LLCoordFrame::readOrientation(const char *buffer) { - memcpy(mOrigin.mV, buffer, 3*sizeof(F32)); /*Flawfinder: ignore */ - buffer += 3*sizeof(F32); - memcpy(mXAxis.mV, buffer, 3*sizeof(F32)); /*Flawfinder: ignore */ - buffer += 3*sizeof(F32); - memcpy(mYAxis.mV, buffer, 3*sizeof(F32)); /*Flawfinder: ignore */ - buffer += 3*sizeof(F32); - memcpy(mZAxis.mV, buffer, 3*sizeof(F32)); /*Flawfinder: ignore */ - - if( !isFinite() ) - { - reset(); - LL_WARNS() << "Non Finite in LLCoordFrame::readOrientation()" << LL_ENDL; - } + memcpy(mOrigin.mV, buffer, 3*sizeof(F32)); /*Flawfinder: ignore */ + buffer += 3*sizeof(F32); + memcpy(mXAxis.mV, buffer, 3*sizeof(F32)); /*Flawfinder: ignore */ + buffer += 3*sizeof(F32); + memcpy(mYAxis.mV, buffer, 3*sizeof(F32)); /*Flawfinder: ignore */ + buffer += 3*sizeof(F32); + memcpy(mZAxis.mV, buffer, 3*sizeof(F32)); /*Flawfinder: ignore */ + + if( !isFinite() ) + { + reset(); + LL_WARNS() << "Non Finite in LLCoordFrame::readOrientation()" << LL_ENDL; + } - return 12*sizeof(F32); + return 12*sizeof(F32); } @@ -420,107 +420,107 @@ size_t LLCoordFrame::readOrientation(const char *buffer) LLVector3 LLCoordFrame::rotateToLocal(const LLVector3 &absolute_vector) const { - LLVector3 local_vector(mXAxis * absolute_vector, - mYAxis * absolute_vector, - mZAxis * absolute_vector); - return local_vector; + LLVector3 local_vector(mXAxis * absolute_vector, + mYAxis * absolute_vector, + mZAxis * absolute_vector); + return local_vector; } LLVector4 LLCoordFrame::rotateToLocal(const LLVector4 &absolute_vector) const { - LLVector4 local_vector; - local_vector.mV[VX] = mXAxis.mV[VX] * absolute_vector.mV[VX] + - mXAxis.mV[VY] * absolute_vector.mV[VY] + - mXAxis.mV[VZ] * absolute_vector.mV[VZ]; - local_vector.mV[VY] = mYAxis.mV[VX] * absolute_vector.mV[VX] + - mYAxis.mV[VY] * absolute_vector.mV[VY] + - mYAxis.mV[VZ] * absolute_vector.mV[VZ]; - local_vector.mV[VZ] = mZAxis.mV[VX] * absolute_vector.mV[VX] + - mZAxis.mV[VY] * absolute_vector.mV[VY] + - mZAxis.mV[VZ] * absolute_vector.mV[VZ]; - local_vector.mV[VW] = absolute_vector.mV[VW]; - return local_vector; + LLVector4 local_vector; + local_vector.mV[VX] = mXAxis.mV[VX] * absolute_vector.mV[VX] + + mXAxis.mV[VY] * absolute_vector.mV[VY] + + mXAxis.mV[VZ] * absolute_vector.mV[VZ]; + local_vector.mV[VY] = mYAxis.mV[VX] * absolute_vector.mV[VX] + + mYAxis.mV[VY] * absolute_vector.mV[VY] + + mYAxis.mV[VZ] * absolute_vector.mV[VZ]; + local_vector.mV[VZ] = mZAxis.mV[VX] * absolute_vector.mV[VX] + + mZAxis.mV[VY] * absolute_vector.mV[VY] + + mZAxis.mV[VZ] * absolute_vector.mV[VZ]; + local_vector.mV[VW] = absolute_vector.mV[VW]; + return local_vector; } LLVector3 LLCoordFrame::rotateToAbsolute(const LLVector3 &local_vector) const { - LLVector3 absolute_vector; - absolute_vector.mV[VX] = mXAxis.mV[VX] * local_vector.mV[VX] + - mYAxis.mV[VX] * local_vector.mV[VY] + - mZAxis.mV[VX] * local_vector.mV[VZ]; - absolute_vector.mV[VY] = mXAxis.mV[VY] * local_vector.mV[VX] + - mYAxis.mV[VY] * local_vector.mV[VY] + - mZAxis.mV[VY] * local_vector.mV[VZ]; - absolute_vector.mV[VZ] = mXAxis.mV[VZ] * local_vector.mV[VX] + - mYAxis.mV[VZ] * local_vector.mV[VY] + - mZAxis.mV[VZ] * local_vector.mV[VZ]; - return absolute_vector; + LLVector3 absolute_vector; + absolute_vector.mV[VX] = mXAxis.mV[VX] * local_vector.mV[VX] + + mYAxis.mV[VX] * local_vector.mV[VY] + + mZAxis.mV[VX] * local_vector.mV[VZ]; + absolute_vector.mV[VY] = mXAxis.mV[VY] * local_vector.mV[VX] + + mYAxis.mV[VY] * local_vector.mV[VY] + + mZAxis.mV[VY] * local_vector.mV[VZ]; + absolute_vector.mV[VZ] = mXAxis.mV[VZ] * local_vector.mV[VX] + + mYAxis.mV[VZ] * local_vector.mV[VY] + + mZAxis.mV[VZ] * local_vector.mV[VZ]; + return absolute_vector; } LLVector4 LLCoordFrame::rotateToAbsolute(const LLVector4 &local_vector) const { - LLVector4 absolute_vector; - absolute_vector.mV[VX] = mXAxis.mV[VX] * local_vector.mV[VX] + - mYAxis.mV[VX] * local_vector.mV[VY] + - mZAxis.mV[VX] * local_vector.mV[VZ]; - absolute_vector.mV[VY] = mXAxis.mV[VY] * local_vector.mV[VX] + - mYAxis.mV[VY] * local_vector.mV[VY] + - mZAxis.mV[VY] * local_vector.mV[VZ]; - absolute_vector.mV[VZ] = mXAxis.mV[VZ] * local_vector.mV[VX] + - mYAxis.mV[VZ] * local_vector.mV[VY] + - mZAxis.mV[VZ] * local_vector.mV[VZ]; - absolute_vector.mV[VW] = local_vector[VW]; - return absolute_vector; + LLVector4 absolute_vector; + absolute_vector.mV[VX] = mXAxis.mV[VX] * local_vector.mV[VX] + + mYAxis.mV[VX] * local_vector.mV[VY] + + mZAxis.mV[VX] * local_vector.mV[VZ]; + absolute_vector.mV[VY] = mXAxis.mV[VY] * local_vector.mV[VX] + + mYAxis.mV[VY] * local_vector.mV[VY] + + mZAxis.mV[VY] * local_vector.mV[VZ]; + absolute_vector.mV[VZ] = mXAxis.mV[VZ] * local_vector.mV[VX] + + mYAxis.mV[VZ] * local_vector.mV[VY] + + mZAxis.mV[VZ] * local_vector.mV[VZ]; + absolute_vector.mV[VW] = local_vector[VW]; + return absolute_vector; } void LLCoordFrame::orthonormalize() // Makes sure the axes are orthogonal and normalized. { - mXAxis.normVec(); // X is renormalized - mYAxis -= mXAxis * (mXAxis * mYAxis); // Y remains in X-Y plane - mYAxis.normVec(); // Y is normalized - mZAxis = mXAxis % mYAxis; // Z = X cross Y + mXAxis.normVec(); // X is renormalized + mYAxis -= mXAxis * (mXAxis * mYAxis); // Y remains in X-Y plane + mYAxis.normVec(); // Y is normalized + mZAxis = mXAxis % mYAxis; // Z = X cross Y } LLVector3 LLCoordFrame::transformToLocal(const LLVector3 &absolute_vector) const { - return rotateToLocal(absolute_vector - mOrigin); + return rotateToLocal(absolute_vector - mOrigin); } LLVector4 LLCoordFrame::transformToLocal(const LLVector4 &absolute_vector) const { - LLVector4 local_vector(absolute_vector); - local_vector.mV[VX] -= mOrigin.mV[VX]; - local_vector.mV[VY] -= mOrigin.mV[VY]; - local_vector.mV[VZ] -= mOrigin.mV[VZ]; - return rotateToLocal(local_vector); + LLVector4 local_vector(absolute_vector); + local_vector.mV[VX] -= mOrigin.mV[VX]; + local_vector.mV[VY] -= mOrigin.mV[VY]; + local_vector.mV[VZ] -= mOrigin.mV[VZ]; + return rotateToLocal(local_vector); } LLVector3 LLCoordFrame::transformToAbsolute(const LLVector3 &local_vector) const { - return (rotateToAbsolute(local_vector) + mOrigin); + return (rotateToAbsolute(local_vector) + mOrigin); } LLVector4 LLCoordFrame::transformToAbsolute(const LLVector4 &local_vector) const { - LLVector4 absolute_vector; - absolute_vector = rotateToAbsolute(local_vector); - absolute_vector.mV[VX] += mOrigin.mV[VX]; - absolute_vector.mV[VY] += mOrigin.mV[VY]; - absolute_vector.mV[VZ] += mOrigin.mV[VZ]; - return absolute_vector; + LLVector4 absolute_vector; + absolute_vector = rotateToAbsolute(local_vector); + absolute_vector.mV[VX] += mOrigin.mV[VX]; + absolute_vector.mV[VY] += mOrigin.mV[VY]; + absolute_vector.mV[VZ] += mOrigin.mV[VZ]; + return absolute_vector; } -// This is how you combine a translation and rotation of a +// This is how you combine a translation and rotation of a // coordinate frame to get an OpenGL transformation matrix: // // translation * rotation = transformation matrix @@ -531,129 +531,129 @@ LLVector4 LLCoordFrame::transformToAbsolute(const LLVector4 &local_vector) const // V | 0 0 1 0 | | c f i 0 | | c f i 0 | // |-x -y -z 1 | | 0 0 0 1 | |-(ax+by+cz) -(dx+ey+fz) -(gx+hy+iz) 1 | // -// where {a,b,c} = x-axis -// {d,e,f} = y-axis -// {g,h,i} = z-axis +// where {a,b,c} = x-axis +// {d,e,f} = y-axis +// {g,h,i} = z-axis // {x,y,z} = origin void LLCoordFrame::getOpenGLTranslation(F32 *ogl_matrix) const { - *(ogl_matrix + 0) = 1.0f; - *(ogl_matrix + 1) = 0.0f; - *(ogl_matrix + 2) = 0.0f; - *(ogl_matrix + 3) = 0.0f; + *(ogl_matrix + 0) = 1.0f; + *(ogl_matrix + 1) = 0.0f; + *(ogl_matrix + 2) = 0.0f; + *(ogl_matrix + 3) = 0.0f; - *(ogl_matrix + 4) = 0.0f; - *(ogl_matrix + 5) = 1.0f; - *(ogl_matrix + 6) = 0.0f; - *(ogl_matrix + 7) = 0.0f; + *(ogl_matrix + 4) = 0.0f; + *(ogl_matrix + 5) = 1.0f; + *(ogl_matrix + 6) = 0.0f; + *(ogl_matrix + 7) = 0.0f; - *(ogl_matrix + 8) = 0.0f; - *(ogl_matrix + 9) = 0.0f; - *(ogl_matrix + 10) = 1.0f; - *(ogl_matrix + 11) = 0.0f; + *(ogl_matrix + 8) = 0.0f; + *(ogl_matrix + 9) = 0.0f; + *(ogl_matrix + 10) = 1.0f; + *(ogl_matrix + 11) = 0.0f; - *(ogl_matrix + 12) = -mOrigin.mV[VX]; - *(ogl_matrix + 13) = -mOrigin.mV[VY]; - *(ogl_matrix + 14) = -mOrigin.mV[VZ]; - *(ogl_matrix + 15) = 1.0f; + *(ogl_matrix + 12) = -mOrigin.mV[VX]; + *(ogl_matrix + 13) = -mOrigin.mV[VY]; + *(ogl_matrix + 14) = -mOrigin.mV[VZ]; + *(ogl_matrix + 15) = 1.0f; } void LLCoordFrame::getOpenGLRotation(F32 *ogl_matrix) const { - *(ogl_matrix + 0) = mXAxis.mV[VX]; - *(ogl_matrix + 4) = mXAxis.mV[VY]; - *(ogl_matrix + 8) = mXAxis.mV[VZ]; + *(ogl_matrix + 0) = mXAxis.mV[VX]; + *(ogl_matrix + 4) = mXAxis.mV[VY]; + *(ogl_matrix + 8) = mXAxis.mV[VZ]; - *(ogl_matrix + 1) = mYAxis.mV[VX]; - *(ogl_matrix + 5) = mYAxis.mV[VY]; - *(ogl_matrix + 9) = mYAxis.mV[VZ]; + *(ogl_matrix + 1) = mYAxis.mV[VX]; + *(ogl_matrix + 5) = mYAxis.mV[VY]; + *(ogl_matrix + 9) = mYAxis.mV[VZ]; - *(ogl_matrix + 2) = mZAxis.mV[VX]; - *(ogl_matrix + 6) = mZAxis.mV[VY]; - *(ogl_matrix + 10) = mZAxis.mV[VZ]; + *(ogl_matrix + 2) = mZAxis.mV[VX]; + *(ogl_matrix + 6) = mZAxis.mV[VY]; + *(ogl_matrix + 10) = mZAxis.mV[VZ]; - *(ogl_matrix + 3) = 0.0f; - *(ogl_matrix + 7) = 0.0f; - *(ogl_matrix + 11) = 0.0f; + *(ogl_matrix + 3) = 0.0f; + *(ogl_matrix + 7) = 0.0f; + *(ogl_matrix + 11) = 0.0f; - *(ogl_matrix + 12) = 0.0f; - *(ogl_matrix + 13) = 0.0f; - *(ogl_matrix + 14) = 0.0f; - *(ogl_matrix + 15) = 1.0f; + *(ogl_matrix + 12) = 0.0f; + *(ogl_matrix + 13) = 0.0f; + *(ogl_matrix + 14) = 0.0f; + *(ogl_matrix + 15) = 1.0f; } void LLCoordFrame::getOpenGLTransform(F32 *ogl_matrix) const { - *(ogl_matrix + 0) = mXAxis.mV[VX]; - *(ogl_matrix + 4) = mXAxis.mV[VY]; - *(ogl_matrix + 8) = mXAxis.mV[VZ]; - *(ogl_matrix + 12) = -mOrigin * mXAxis; + *(ogl_matrix + 0) = mXAxis.mV[VX]; + *(ogl_matrix + 4) = mXAxis.mV[VY]; + *(ogl_matrix + 8) = mXAxis.mV[VZ]; + *(ogl_matrix + 12) = -mOrigin * mXAxis; - *(ogl_matrix + 1) = mYAxis.mV[VX]; - *(ogl_matrix + 5) = mYAxis.mV[VY]; - *(ogl_matrix + 9) = mYAxis.mV[VZ]; - *(ogl_matrix + 13) = -mOrigin * mYAxis; + *(ogl_matrix + 1) = mYAxis.mV[VX]; + *(ogl_matrix + 5) = mYAxis.mV[VY]; + *(ogl_matrix + 9) = mYAxis.mV[VZ]; + *(ogl_matrix + 13) = -mOrigin * mYAxis; - *(ogl_matrix + 2) = mZAxis.mV[VX]; - *(ogl_matrix + 6) = mZAxis.mV[VY]; - *(ogl_matrix + 10) = mZAxis.mV[VZ]; - *(ogl_matrix + 14) = -mOrigin * mZAxis; + *(ogl_matrix + 2) = mZAxis.mV[VX]; + *(ogl_matrix + 6) = mZAxis.mV[VY]; + *(ogl_matrix + 10) = mZAxis.mV[VZ]; + *(ogl_matrix + 14) = -mOrigin * mZAxis; - *(ogl_matrix + 3) = 0.0f; - *(ogl_matrix + 7) = 0.0f; - *(ogl_matrix + 11) = 0.0f; - *(ogl_matrix + 15) = 1.0f; + *(ogl_matrix + 3) = 0.0f; + *(ogl_matrix + 7) = 0.0f; + *(ogl_matrix + 11) = 0.0f; + *(ogl_matrix + 15) = 1.0f; } // at and up_direction are presumed to be normalized void LLCoordFrame::lookDir(const LLVector3 &at, const LLVector3 &up_direction) { - // Make sure 'at' and 'up_direction' are not parallel - // and that neither are zero-length vectors - LLVector3 left(up_direction % at); - if (left.isNull()) - { - //tweak lookat pos so we don't get a degenerate matrix - LLVector3 tempat(at[VX] + 0.01f, at[VY], at[VZ]); - tempat.normVec(); - left = (up_direction % tempat); - } - left.normVec(); + // Make sure 'at' and 'up_direction' are not parallel + // and that neither are zero-length vectors + LLVector3 left(up_direction % at); + if (left.isNull()) + { + //tweak lookat pos so we don't get a degenerate matrix + LLVector3 tempat(at[VX] + 0.01f, at[VY], at[VZ]); + tempat.normVec(); + left = (up_direction % tempat); + } + left.normVec(); - LLVector3 up = at % left; + LLVector3 up = at % left; - if (at.isFinite() && left.isFinite() && up.isFinite()) - { - setAxes(at, left, up); - } + if (at.isFinite() && left.isFinite() && up.isFinite()) + { + setAxes(at, left, up); + } } void LLCoordFrame::lookDir(const LLVector3 &xuv) { - static LLVector3 up_direction(0.0f, 0.0f, 1.0f); - lookDir(xuv, up_direction); + static LLVector3 up_direction(0.0f, 0.0f, 1.0f); + lookDir(xuv, up_direction); } void LLCoordFrame::lookAt(const LLVector3 &origin, const LLVector3 &point_of_interest, const LLVector3 &up_direction) { - setOrigin(origin); - LLVector3 at(point_of_interest - origin); - at.normVec(); - lookDir(at, up_direction); + setOrigin(origin); + LLVector3 at(point_of_interest - origin); + at.normVec(); + lookDir(at, up_direction); } void LLCoordFrame::lookAt(const LLVector3 &origin, const LLVector3 &point_of_interest) { - static LLVector3 up_direction(0.0f, 0.0f, 1.0f); + static LLVector3 up_direction(0.0f, 0.0f, 1.0f); - setOrigin(origin); - LLVector3 at(point_of_interest - origin); - at.normVec(); - lookDir(at, up_direction); + setOrigin(origin); + LLVector3 at(point_of_interest - origin); + at.normVec(); + lookDir(at, up_direction); } @@ -661,13 +661,13 @@ void LLCoordFrame::lookAt(const LLVector3 &origin, const LLVector3 &point_of_int std::ostream& operator<<(std::ostream &s, const LLCoordFrame &C) { - s << "{ " - << " origin = " << C.mOrigin - << " x_axis = " << C.mXAxis - << " y_axis = " << C.mYAxis - << " z_axis = " << C.mZAxis - << " }"; - return s; + s << "{ " + << " origin = " << C.mOrigin + << " x_axis = " << C.mXAxis + << " y_axis = " << C.mYAxis + << " z_axis = " << C.mZAxis + << " }"; + return s; } diff --git a/indra/llmath/llcoordframe.h b/indra/llmath/llcoordframe.h index 1d3f4f7e3e..aaa701f792 100644 --- a/indra/llmath/llcoordframe.h +++ b/indra/llmath/llcoordframe.h @@ -1,25 +1,25 @@ -/** +/** * @file llcoordframe.h * @brief LLCoordFrame class header file. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -32,141 +32,141 @@ #include "llerror.h" // XXX : The constructors of the LLCoordFrame class assume that all vectors -// and quaternion being passed as arguments are normalized, and all matrix -// arguments are unitary. VERY BAD things will happen if these assumptions fail. -// Also, segfault hazzards exist in methods that accept F32* arguments. +// and quaternion being passed as arguments are normalized, and all matrix +// arguments are unitary. VERY BAD things will happen if these assumptions fail. +// Also, segfault hazzards exist in methods that accept F32* arguments. -class LLCoordFrame +class LLCoordFrame { public: - LLCoordFrame(); // Inits at zero with identity rotation - explicit LLCoordFrame(const LLVector3 &origin); // Sets origin, and inits rotation = Identity - LLCoordFrame(const LLVector3 &x_axis, - const LLVector3 &y_axis, - const LLVector3 &z_axis); // Sets coordinate axes and inits origin at zero - LLCoordFrame(const LLVector3 &origin, - const LLVector3 &x_axis, - const LLVector3 &y_axis, - const LLVector3 &z_axis); // Sets the origin and coordinate axes - LLCoordFrame(const LLVector3 &origin, - const LLMatrix3 &rotation); // Sets axes to 3x3 matrix - LLCoordFrame(const LLVector3 &origin, - const LLVector3 &direction); // Sets origin and calls lookDir(direction) - explicit LLCoordFrame(const LLQuaternion &q); // Sets axes using q and inits mOrigin to zero - LLCoordFrame(const LLVector3 &origin, - const LLQuaternion &q); // Uses quaternion to init axes - explicit LLCoordFrame(const LLMatrix4 &mat); // Extracts frame from a 4x4 matrix - // The folowing two constructors are dangerous due to implicit casting and have been disabled - SJB - //LLCoordFrame(const F32 *origin, const F32 *rotation); // Assumes "origin" is 1x3 and "rotation" is 1x9 array - //LLCoordFrame(const F32 *origin_and_rotation); // Assumes "origin_and_rotation" is 1x12 array - - bool isFinite() { return mOrigin.isFinite() && mXAxis.isFinite() && mYAxis.isFinite() && mZAxis.isFinite(); } - - void reset(); - void resetAxes(); - - void setOrigin(F32 x, F32 y, F32 z); // Set mOrigin - void setOrigin(const LLVector3 &origin); - void setOrigin(const F32 *origin); - void setOrigin(const LLCoordFrame &frame); - - inline void setOriginX(F32 x) { mOrigin.mV[VX] = x; } - inline void setOriginY(F32 y) { mOrigin.mV[VY] = y; } - inline void setOriginZ(F32 z) { mOrigin.mV[VZ] = z; } - - void setAxes(const LLVector3 &x_axis, // Set axes - const LLVector3 &y_axis, - const LLVector3 &z_axis); - void setAxes(const LLMatrix3 &rotation_matrix); - void setAxes(const LLQuaternion &q); - void setAxes(const F32 *rotation_matrix); - void setAxes(const LLCoordFrame &frame); - - void translate(F32 x, F32 y, F32 z); // Move mOrgin - void translate(const LLVector3 &v); - void translate(const F32 *origin); - - void rotate(F32 angle, F32 x, F32 y, F32 z); // Move axes - void rotate(F32 angle, const LLVector3 &rotation_axis); - void rotate(const LLQuaternion &q); - void rotate(const LLMatrix3 &m); - - void orthonormalize(); // Makes sure axes are unitary and orthogonal. - - // These methods allow rotations in the LLCoordFrame's frame - void roll(F32 angle); // RH rotation about mXAxis, radians - void pitch(F32 angle); // RH rotation about mYAxis, radians - void yaw(F32 angle); // RH rotation about mZAxis, radians - - inline const LLVector3 &getOrigin() const { return mOrigin; } - - inline const LLVector3 &getXAxis() const { return mXAxis; } - inline const LLVector3 &getYAxis() const { return mYAxis; } - inline const LLVector3 &getZAxis() const { return mZAxis; } - - inline const LLVector3 &getAtAxis() const { return mXAxis; } - inline const LLVector3 &getLeftAxis() const { return mYAxis; } - inline const LLVector3 &getUpAxis() const { return mZAxis; } - - // These return representations of the rotation or orientation of the LLFrame - // it its absolute frame. That is, these rotations acting on the X-axis {1,0,0} - // will produce the mXAxis. - // LLMatrix3 getMatrix3() const; // Returns axes in 3x3 matrix - LLQuaternion getQuaternion() const; // Returns axes in quaternion form - - // Same as above, except it also includes the translation of the LLFrame - // LLMatrix4 getMatrix4() const; // Returns position and axes in 4x4 matrix - - // Returns matrix which expresses point in local frame in the parent frame - void getMatrixToParent(LLMatrix4 &mat) const; - // Returns matrix which expresses point in parent frame in the local frame - void getMatrixToLocal(LLMatrix4 &mat) const; // Returns matrix which expresses point in parent frame in the local frame - - void getRotMatrixToParent(LLMatrix4 &mat) const; - - // Copies mOrigin, then the three axes to buffer, returns number of bytes copied. - size_t writeOrientation(char *buffer) const; - - // Copies mOrigin, then the three axes from buffer, returns the number of bytes copied. - // Assumes the data in buffer is correct. - size_t readOrientation(const char *buffer); - - LLVector3 rotateToLocal(const LLVector3 &v) const; // Returns v' rotated to local - LLVector4 rotateToLocal(const LLVector4 &v) const; // Returns v' rotated to local - LLVector3 rotateToAbsolute(const LLVector3 &v) const; // Returns v' rotated to absolute - LLVector4 rotateToAbsolute(const LLVector4 &v) const; // Returns v' rotated to absolute - - LLVector3 transformToLocal(const LLVector3 &v) const; // Returns v' in local coord - LLVector4 transformToLocal(const LLVector4 &v) const; // Returns v' in local coord - LLVector3 transformToAbsolute(const LLVector3 &v) const; // Returns v' in absolute coord - LLVector4 transformToAbsolute(const LLVector4 &v) const; // Returns v' in absolute coord - - // Write coord frame orientation into provided array in OpenGL matrix format. - void getOpenGLTranslation(F32 *ogl_matrix) const; - void getOpenGLRotation(F32 *ogl_matrix) const; - void getOpenGLTransform(F32 *ogl_matrix) const; - - // lookDir orients to (xuv, presumed normalized) and does not affect origin - void lookDir(const LLVector3 &xuv, const LLVector3 &up); - void lookDir(const LLVector3 &xuv); // up = 0,0,1 - // lookAt orients to (point_of_interest - origin) and sets origin - void lookAt(const LLVector3 &origin, const LLVector3 &point_of_interest, const LLVector3 &up); - void lookAt(const LLVector3 &origin, const LLVector3 &point_of_interest); // up = 0,0,1 - - // deprecated - void setOriginAndLookAt(const LLVector3 &origin, const LLVector3 &up, const LLVector3 &point_of_interest) - { - lookAt(origin, point_of_interest, up); - } - - friend std::ostream& operator<<(std::ostream &s, const LLCoordFrame &C); - - // These vectors are in absolute frame - LLVector3 mOrigin; - LLVector3 mXAxis; - LLVector3 mYAxis; - LLVector3 mZAxis; + LLCoordFrame(); // Inits at zero with identity rotation + explicit LLCoordFrame(const LLVector3 &origin); // Sets origin, and inits rotation = Identity + LLCoordFrame(const LLVector3 &x_axis, + const LLVector3 &y_axis, + const LLVector3 &z_axis); // Sets coordinate axes and inits origin at zero + LLCoordFrame(const LLVector3 &origin, + const LLVector3 &x_axis, + const LLVector3 &y_axis, + const LLVector3 &z_axis); // Sets the origin and coordinate axes + LLCoordFrame(const LLVector3 &origin, + const LLMatrix3 &rotation); // Sets axes to 3x3 matrix + LLCoordFrame(const LLVector3 &origin, + const LLVector3 &direction); // Sets origin and calls lookDir(direction) + explicit LLCoordFrame(const LLQuaternion &q); // Sets axes using q and inits mOrigin to zero + LLCoordFrame(const LLVector3 &origin, + const LLQuaternion &q); // Uses quaternion to init axes + explicit LLCoordFrame(const LLMatrix4 &mat); // Extracts frame from a 4x4 matrix + // The folowing two constructors are dangerous due to implicit casting and have been disabled - SJB + //LLCoordFrame(const F32 *origin, const F32 *rotation); // Assumes "origin" is 1x3 and "rotation" is 1x9 array + //LLCoordFrame(const F32 *origin_and_rotation); // Assumes "origin_and_rotation" is 1x12 array + + bool isFinite() { return mOrigin.isFinite() && mXAxis.isFinite() && mYAxis.isFinite() && mZAxis.isFinite(); } + + void reset(); + void resetAxes(); + + void setOrigin(F32 x, F32 y, F32 z); // Set mOrigin + void setOrigin(const LLVector3 &origin); + void setOrigin(const F32 *origin); + void setOrigin(const LLCoordFrame &frame); + + inline void setOriginX(F32 x) { mOrigin.mV[VX] = x; } + inline void setOriginY(F32 y) { mOrigin.mV[VY] = y; } + inline void setOriginZ(F32 z) { mOrigin.mV[VZ] = z; } + + void setAxes(const LLVector3 &x_axis, // Set axes + const LLVector3 &y_axis, + const LLVector3 &z_axis); + void setAxes(const LLMatrix3 &rotation_matrix); + void setAxes(const LLQuaternion &q); + void setAxes(const F32 *rotation_matrix); + void setAxes(const LLCoordFrame &frame); + + void translate(F32 x, F32 y, F32 z); // Move mOrgin + void translate(const LLVector3 &v); + void translate(const F32 *origin); + + void rotate(F32 angle, F32 x, F32 y, F32 z); // Move axes + void rotate(F32 angle, const LLVector3 &rotation_axis); + void rotate(const LLQuaternion &q); + void rotate(const LLMatrix3 &m); + + void orthonormalize(); // Makes sure axes are unitary and orthogonal. + + // These methods allow rotations in the LLCoordFrame's frame + void roll(F32 angle); // RH rotation about mXAxis, radians + void pitch(F32 angle); // RH rotation about mYAxis, radians + void yaw(F32 angle); // RH rotation about mZAxis, radians + + inline const LLVector3 &getOrigin() const { return mOrigin; } + + inline const LLVector3 &getXAxis() const { return mXAxis; } + inline const LLVector3 &getYAxis() const { return mYAxis; } + inline const LLVector3 &getZAxis() const { return mZAxis; } + + inline const LLVector3 &getAtAxis() const { return mXAxis; } + inline const LLVector3 &getLeftAxis() const { return mYAxis; } + inline const LLVector3 &getUpAxis() const { return mZAxis; } + + // These return representations of the rotation or orientation of the LLFrame + // it its absolute frame. That is, these rotations acting on the X-axis {1,0,0} + // will produce the mXAxis. + // LLMatrix3 getMatrix3() const; // Returns axes in 3x3 matrix + LLQuaternion getQuaternion() const; // Returns axes in quaternion form + + // Same as above, except it also includes the translation of the LLFrame + // LLMatrix4 getMatrix4() const; // Returns position and axes in 4x4 matrix + + // Returns matrix which expresses point in local frame in the parent frame + void getMatrixToParent(LLMatrix4 &mat) const; + // Returns matrix which expresses point in parent frame in the local frame + void getMatrixToLocal(LLMatrix4 &mat) const; // Returns matrix which expresses point in parent frame in the local frame + + void getRotMatrixToParent(LLMatrix4 &mat) const; + + // Copies mOrigin, then the three axes to buffer, returns number of bytes copied. + size_t writeOrientation(char *buffer) const; + + // Copies mOrigin, then the three axes from buffer, returns the number of bytes copied. + // Assumes the data in buffer is correct. + size_t readOrientation(const char *buffer); + + LLVector3 rotateToLocal(const LLVector3 &v) const; // Returns v' rotated to local + LLVector4 rotateToLocal(const LLVector4 &v) const; // Returns v' rotated to local + LLVector3 rotateToAbsolute(const LLVector3 &v) const; // Returns v' rotated to absolute + LLVector4 rotateToAbsolute(const LLVector4 &v) const; // Returns v' rotated to absolute + + LLVector3 transformToLocal(const LLVector3 &v) const; // Returns v' in local coord + LLVector4 transformToLocal(const LLVector4 &v) const; // Returns v' in local coord + LLVector3 transformToAbsolute(const LLVector3 &v) const; // Returns v' in absolute coord + LLVector4 transformToAbsolute(const LLVector4 &v) const; // Returns v' in absolute coord + + // Write coord frame orientation into provided array in OpenGL matrix format. + void getOpenGLTranslation(F32 *ogl_matrix) const; + void getOpenGLRotation(F32 *ogl_matrix) const; + void getOpenGLTransform(F32 *ogl_matrix) const; + + // lookDir orients to (xuv, presumed normalized) and does not affect origin + void lookDir(const LLVector3 &xuv, const LLVector3 &up); + void lookDir(const LLVector3 &xuv); // up = 0,0,1 + // lookAt orients to (point_of_interest - origin) and sets origin + void lookAt(const LLVector3 &origin, const LLVector3 &point_of_interest, const LLVector3 &up); + void lookAt(const LLVector3 &origin, const LLVector3 &point_of_interest); // up = 0,0,1 + + // deprecated + void setOriginAndLookAt(const LLVector3 &origin, const LLVector3 &up, const LLVector3 &point_of_interest) + { + lookAt(origin, point_of_interest, up); + } + + friend std::ostream& operator<<(std::ostream &s, const LLCoordFrame &C); + + // These vectors are in absolute frame + LLVector3 mOrigin; + LLVector3 mXAxis; + LLVector3 mYAxis; + LLVector3 mZAxis; }; diff --git a/indra/llmath/llinterp.h b/indra/llmath/llinterp.h index a107d301d8..f4faa82a82 100644 --- a/indra/llmath/llinterp.h +++ b/indra/llmath/llinterp.h @@ -1,24 +1,24 @@ -/** +/** * @file llinterp.h * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -30,7 +30,7 @@ // macro definitions for common math constants (e.g. M_PI) are declared under the _USE_MATH_DEFINES // on Windows system. // So, let's define _USE_MATH_DEFINES before including math.h - #define _USE_MATH_DEFINES + #define _USE_MATH_DEFINES #endif #include "math.h" @@ -40,7 +40,7 @@ class LLInterpVal { public: - virtual ~LLInterpVal() {} + virtual ~LLInterpVal() {} }; template <typename Type> @@ -48,57 +48,57 @@ class LLInterp { public: LLInterp(); - virtual ~LLInterp() {} + virtual ~LLInterp() {} + + virtual void start(); + virtual void update(const F32 time) = 0; + const Type &getCurVal() const; - virtual void start(); - virtual void update(const F32 time) = 0; - const Type &getCurVal() const; + void setStartVal(const Type &start_val); + const Type &getStartVal() const; - void setStartVal(const Type &start_val); - const Type &getStartVal() const; + void setEndVal(const Type &target_val); + const Type &getEndVal() const; - void setEndVal(const Type &target_val); - const Type &getEndVal() const; + void setStartTime(const F32 time); + F32 getStartTime() const; - void setStartTime(const F32 time); - F32 getStartTime() const; + void setEndTime(const F32 time); + F32 getEndTime() const; - void setEndTime(const F32 time); - F32 getEndTime() const; + bool isActive() const; + bool isDone() const; - bool isActive() const; - bool isDone() const; - protected: - F32 mStartTime; - F32 mEndTime; - F32 mDuration; - bool mActive; - bool mDone; + F32 mStartTime; + F32 mEndTime; + F32 mDuration; + bool mActive; + bool mDone; - Type mStartVal; - Type mEndVal; + Type mStartVal; + Type mEndVal; - F32 mCurTime; - Type mCurVal; + F32 mCurTime; + Type mCurVal; }; template <typename Type> class LLInterpLinear : public LLInterp<Type> { public: - void start() override; - void update(const F32 time) override; - F32 getCurFrac() const; + void start() override; + void update(const F32 time) override; + F32 getCurFrac() const; protected: - F32 mCurFrac; + F32 mCurFrac; }; template <typename Type> class LLInterpExp : public LLInterpLinear<Type> { public: - void update(const F32 time); + void update(const F32 time); protected: }; @@ -106,28 +106,28 @@ template <typename Type> class LLInterpAttractor : public LLInterp<Type> { public: - LLInterpAttractor(); - void start() override; - void setStartVel(const Type &vel); - void setForce(const F32 force); - void update(const F32 time) override; + LLInterpAttractor(); + void start() override; + void setStartVel(const Type &vel); + void setForce(const F32 force); + void update(const F32 time) override; protected: - F32 mForce; - Type mStartVel; - Type mVelocity; + F32 mForce; + Type mStartVel; + Type mVelocity; }; template <typename Type> class LLInterpFunc : public LLInterp<Type> { public: - LLInterpFunc(); - void update(const F32 time) override; + LLInterpFunc(); + void update(const F32 time) override; - void setFunc(Type (*)(const F32, void *data), void *data); + void setFunc(Type (*)(const F32, void *data), void *data); protected: - Type (*mFunc)(const F32 time, void *data); - void *mData; + Type (*mFunc)(const F32 time, void *data); + void *mData; }; @@ -146,93 +146,93 @@ template <typename Type> LLInterp<Type>::LLInterp() : mStartVal(Type()), mEndVal(Type()), mCurVal(Type()) { - mStartTime = 0.f; - mEndTime = 1.f; - mDuration = 1.f; - mCurTime = 0.f; - mDone = false; - mActive = false; + mStartTime = 0.f; + mEndTime = 1.f; + mDuration = 1.f; + mCurTime = 0.f; + mDone = false; + mActive = false; } template <class Type> void LLInterp<Type>::setStartVal(const Type &start_val) { - mStartVal = start_val; + mStartVal = start_val; } template <class Type> void LLInterp<Type>::start() { - mCurVal = mStartVal; - mCurTime = mStartTime; - mDone = false; - mActive = false; + mCurVal = mStartVal; + mCurTime = mStartTime; + mDone = false; + mActive = false; } template <class Type> const Type &LLInterp<Type>::getStartVal() const { - return mStartVal; + return mStartVal; } template <class Type> void LLInterp<Type>::setEndVal(const Type &end_val) { - mEndVal = end_val; + mEndVal = end_val; } template <class Type> const Type &LLInterp<Type>::getEndVal() const { - return mEndVal; + return mEndVal; } template <class Type> const Type &LLInterp<Type>::getCurVal() const { - return mCurVal; + return mCurVal; } template <class Type> void LLInterp<Type>::setStartTime(const F32 start_time) { - mStartTime = start_time; - mDuration = mEndTime - mStartTime; + mStartTime = start_time; + mDuration = mEndTime - mStartTime; } template <class Type> F32 LLInterp<Type>::getStartTime() const { - return mStartTime; + return mStartTime; } template <class Type> void LLInterp<Type>::setEndTime(const F32 end_time) { - mEndTime = end_time; - mDuration = mEndTime - mStartTime; + mEndTime = end_time; + mDuration = mEndTime - mStartTime; } template <class Type> F32 LLInterp<Type>::getEndTime() const { - return mEndTime; + return mEndTime; } template <class Type> bool LLInterp<Type>::isDone() const { - return mDone; + return mDone; } template <class Type> bool LLInterp<Type>::isActive() const { - return mActive; + return mActive; } ////////////////////////////// @@ -242,53 +242,53 @@ bool LLInterp<Type>::isActive() const template <typename Type> void LLInterpLinear<Type>::start() { - LLInterp<Type>::start(); - mCurFrac = 0.f; + LLInterp<Type>::start(); + mCurFrac = 0.f; } template <typename Type> void LLInterpLinear<Type>::update(const F32 time) { - F32 target_frac = (time - this->mStartTime) / this->mDuration; - F32 dfrac = target_frac - this->mCurFrac; - if (target_frac >= 0.f) - { - this->mActive = true; - } - - if (target_frac > 1.f) - { - this->mCurVal = this->mEndVal; - this->mCurFrac = 1.f; - this->mCurTime = time; - this->mDone = true; - return; - } - - target_frac = llmin(1.f, target_frac); - target_frac = llmax(0.f, target_frac); - - if (dfrac >= 0.f) - { - F32 total_frac = 1.f - this->mCurFrac; - F32 inc_frac = dfrac / total_frac; - this->mCurVal = inc_frac * this->mEndVal + (1.f - inc_frac) * this->mCurVal; - this->mCurTime = time; - } - else - { - F32 total_frac = this->mCurFrac - 1.f; - F32 inc_frac = dfrac / total_frac; - this->mCurVal = inc_frac * this->mStartVal + (1.f - inc_frac) * this->mCurVal; - this->mCurTime = time; - } - mCurFrac = target_frac; + F32 target_frac = (time - this->mStartTime) / this->mDuration; + F32 dfrac = target_frac - this->mCurFrac; + if (target_frac >= 0.f) + { + this->mActive = true; + } + + if (target_frac > 1.f) + { + this->mCurVal = this->mEndVal; + this->mCurFrac = 1.f; + this->mCurTime = time; + this->mDone = true; + return; + } + + target_frac = llmin(1.f, target_frac); + target_frac = llmax(0.f, target_frac); + + if (dfrac >= 0.f) + { + F32 total_frac = 1.f - this->mCurFrac; + F32 inc_frac = dfrac / total_frac; + this->mCurVal = inc_frac * this->mEndVal + (1.f - inc_frac) * this->mCurVal; + this->mCurTime = time; + } + else + { + F32 total_frac = this->mCurFrac - 1.f; + F32 inc_frac = dfrac / total_frac; + this->mCurVal = inc_frac * this->mStartVal + (1.f - inc_frac) * this->mCurVal; + this->mCurTime = time; + } + mCurFrac = target_frac; } template <class Type> F32 LLInterpLinear<Type>::getCurFrac() const { - return mCurFrac; + return mCurFrac; } @@ -301,54 +301,54 @@ F32 LLInterpLinear<Type>::getCurFrac() const template <class Type> LLInterpAttractor<Type>::LLInterpAttractor() : LLInterp<Type>() { - mForce = 0.1f; - mVelocity *= 0.f; - mStartVel *= 0.f; + mForce = 0.1f; + mVelocity *= 0.f; + mStartVel *= 0.f; } template <class Type> void LLInterpAttractor<Type>::start() { - LLInterp<Type>::start(); - mVelocity = mStartVel; + LLInterp<Type>::start(); + mVelocity = mStartVel; } template <class Type> void LLInterpAttractor<Type>::setStartVel(const Type &vel) { - mStartVel = vel; + mStartVel = vel; } template <class Type> void LLInterpAttractor<Type>::setForce(const F32 force) { - mForce = force; + mForce = force; } template <class Type> void LLInterpAttractor<Type>::update(const F32 time) { - if (time > this->mStartTime) - { - this->mActive = true; - } - else - { - return; - } - if (time > this->mEndTime) - { - this->mDone = true; - return; - } - - F32 dt = time - this->mCurTime; - Type dist_val = this->mEndVal - this->mCurVal; - Type dv = 0.5*dt*dt*this->mForce*dist_val; - this->mVelocity += dv; - this->mCurVal += this->mVelocity * dt; - this->mCurTime = time; + if (time > this->mStartTime) + { + this->mActive = true; + } + else + { + return; + } + if (time > this->mEndTime) + { + this->mDone = true; + return; + } + + F32 dt = time - this->mCurTime; + Type dist_val = this->mEndVal - this->mCurVal; + Type dv = 0.5*dt*dt*this->mForce*dist_val; + this->mVelocity += dv; + this->mCurVal += this->mVelocity * dt; + this->mCurTime = time; } @@ -361,36 +361,36 @@ void LLInterpAttractor<Type>::update(const F32 time) template <class Type> LLInterpFunc<Type>::LLInterpFunc() : LLInterp<Type>() { - mFunc = nullptr; - mData = nullptr; + mFunc = nullptr; + mData = nullptr; } template <class Type> void LLInterpFunc<Type>::setFunc(Type (*func)(const F32, void *data), void *data) { - mFunc = func; - mData = data; + mFunc = func; + mData = data; } template <class Type> void LLInterpFunc<Type>::update(const F32 time) { - if (time > this->mStartTime) - { - this->mActive = true; - } - else - { - return; - } - if (time > this->mEndTime) - { - this->mDone = true; - return; - } - - this->mCurVal = (*mFunc)(time - this->mStartTime, mData); - this->mCurTime = time; + if (time > this->mStartTime) + { + this->mActive = true; + } + else + { + return; + } + if (time > this->mEndTime) + { + this->mDone = true; + return; + } + + this->mCurVal = (*mFunc)(time - this->mStartTime, mData); + this->mCurTime = time; } ////////////////////////////// @@ -401,24 +401,24 @@ void LLInterpFunc<Type>::update(const F32 time) template <class Type> void LLInterpExp<Type>::update(const F32 time) { - F32 target_frac = (time - this->mStartTime) / this->mDuration; - if (target_frac >= 0.f) - { - this->mActive = true; - } - - if (target_frac > 1.f) - { - this->mCurVal = this->mEndVal; - this->mCurFrac = 1.f; - this->mCurTime = time; - this->mDone = true; - return; - } - - this->mCurFrac = 1.f - (F32)(exp(-2.f*target_frac)); - this->mCurVal = this->mStartVal + this->mCurFrac * (this->mEndVal - this->mStartVal); - this->mCurTime = time; + F32 target_frac = (time - this->mStartTime) / this->mDuration; + if (target_frac >= 0.f) + { + this->mActive = true; + } + + if (target_frac > 1.f) + { + this->mCurVal = this->mEndVal; + this->mCurFrac = 1.f; + this->mCurTime = time; + this->mDone = true; + return; + } + + this->mCurFrac = 1.f - (F32)(exp(-2.f*target_frac)); + this->mCurVal = this->mStartVal + this->mCurFrac * (this->mEndVal - this->mStartVal); + this->mCurTime = time; } #endif // LL_LLINTERP_H diff --git a/indra/llmath/llline.cpp b/indra/llmath/llline.cpp index cfee315b55..70c68dd42f 100644 --- a/indra/llmath/llline.cpp +++ b/indra/llmath/llline.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llline.cpp * @author Andrew Meadows * @brief Simple line class that can compute nearest approach between two lines @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -33,87 +33,87 @@ const F32 SOME_VERY_SMALL_NUMBER = 1.0e-8f; LLLine::LLLine() -: mPoint(0.f, 0.f, 0.f), - mDirection(1.f, 0.f, 0.f) +: mPoint(0.f, 0.f, 0.f), + mDirection(1.f, 0.f, 0.f) { } LLLine::LLLine( const LLVector3& first_point, const LLVector3& second_point ) { - setPoints(first_point, second_point); + setPoints(first_point, second_point); } void LLLine::setPoints( const LLVector3& first_point, const LLVector3& second_point ) { - mPoint = first_point; - mDirection = second_point - first_point; - mDirection.normalize(); + mPoint = first_point; + mDirection = second_point - first_point; + mDirection.normalize(); } void LLLine::setPointDirection( const LLVector3& first_point, const LLVector3& second_point ) { - setPoints(first_point, first_point + second_point); + setPoints(first_point, first_point + second_point); } bool LLLine::intersects( const LLVector3& point, F32 radius ) const { - LLVector3 other_direction = point - mPoint; - LLVector3 nearest_point = mPoint + mDirection * (other_direction * mDirection); - F32 nearest_approach = (nearest_point - point).length(); - return (nearest_approach <= radius); + LLVector3 other_direction = point - mPoint; + LLVector3 nearest_point = mPoint + mDirection * (other_direction * mDirection); + F32 nearest_approach = (nearest_point - point).length(); + return (nearest_approach <= radius); } // returns the point on this line that is closest to some_point LLVector3 LLLine::nearestApproach( const LLVector3& some_point ) const { - return (mPoint + mDirection * ((some_point - mPoint) * mDirection)); + return (mPoint + mDirection * ((some_point - mPoint) * mDirection)); } // the accuracy of this method sucks when you give it two nearly // parallel lines, so you should probably check for parallelism // before you call this -// +// // returns the point on this line that is closest to other_line LLVector3 LLLine::nearestApproach( const LLLine& other_line ) const { - LLVector3 between_points = other_line.mPoint - mPoint; - F32 dir_dot_dir = mDirection * other_line.mDirection; - F32 one_minus_dir_dot_dir = 1.0f - fabs(dir_dot_dir); - if ( one_minus_dir_dot_dir < SOME_VERY_SMALL_NUMBER ) - { + LLVector3 between_points = other_line.mPoint - mPoint; + F32 dir_dot_dir = mDirection * other_line.mDirection; + F32 one_minus_dir_dot_dir = 1.0f - fabs(dir_dot_dir); + if ( one_minus_dir_dot_dir < SOME_VERY_SMALL_NUMBER ) + { #ifdef LL_DEBUG - LL_WARNS() << "LLLine::nearestApproach() was given two very " - << "nearly parallel lines dir1 = " << mDirection - << " dir2 = " << other_line.mDirection << " with 1-dot_product = " - << one_minus_dir_dot_dir << LL_ENDL; + LL_WARNS() << "LLLine::nearestApproach() was given two very " + << "nearly parallel lines dir1 = " << mDirection + << " dir2 = " << other_line.mDirection << " with 1-dot_product = " + << one_minus_dir_dot_dir << LL_ENDL; #endif - // the lines are approximately parallel - // We shouldn't fall in here because this check should have been made - // BEFORE this function was called. We dare not continue with the - // computations for fear of division by zero, but we have to return - // something so we return a bogus point -- caller beware. - return 0.5f * (mPoint + other_line.mPoint); - } - - F32 odir_dot_bp = other_line.mDirection * between_points; - - F32 numerator = 0; - F32 denominator = 0; - for (S32 i=0; i<3; i++) - { - F32 factor = dir_dot_dir * other_line.mDirection.mV[i] - mDirection.mV[i]; - numerator += ( between_points.mV[i] - odir_dot_bp * other_line.mDirection.mV[i] ) * factor; - denominator -= factor * factor; - } - - F32 length_to_nearest_approach = numerator / denominator; - - return mPoint + length_to_nearest_approach * mDirection; + // the lines are approximately parallel + // We shouldn't fall in here because this check should have been made + // BEFORE this function was called. We dare not continue with the + // computations for fear of division by zero, but we have to return + // something so we return a bogus point -- caller beware. + return 0.5f * (mPoint + other_line.mPoint); + } + + F32 odir_dot_bp = other_line.mDirection * between_points; + + F32 numerator = 0; + F32 denominator = 0; + for (S32 i=0; i<3; i++) + { + F32 factor = dir_dot_dir * other_line.mDirection.mV[i] - mDirection.mV[i]; + numerator += ( between_points.mV[i] - odir_dot_bp * other_line.mDirection.mV[i] ) * factor; + denominator -= factor * factor; + } + + F32 length_to_nearest_approach = numerator / denominator; + + return mPoint + length_to_nearest_approach * mDirection; } std::ostream& operator<<( std::ostream& output_stream, const LLLine& line ) { - output_stream << "{point=" << line.mPoint << "," << "dir=" << line.mDirection << "}"; - return output_stream; + output_stream << "{point=" << line.mPoint << "," << "dir=" << line.mDirection << "}"; + return output_stream; } @@ -124,72 +124,72 @@ F32 TOO_SMALL_FOR_DIVISION = 0.0001f; // on success stores the intersection point in 'result' bool LLLine::intersectsPlane( LLVector3& result, const LLLine& plane ) const { - // p = P + l * d equation for a line - // - // N * p = D equation for a point - // - // N * (P + l * d) = D - // N*P + l * (N*d) = D - // l * (N*d) = D - N*P - // l = ( D - N*P ) / ( N*d ) - // - - F32 dot = plane.mDirection * mDirection; - if (fabs(dot) < TOO_SMALL_FOR_DIVISION) - { - return false; - } - - F32 plane_dot = plane.mDirection * plane.mPoint; - F32 length = ( plane_dot - (plane.mDirection * mPoint) ) / dot; - result = mPoint + length * mDirection; - return true; + // p = P + l * d equation for a line + // + // N * p = D equation for a point + // + // N * (P + l * d) = D + // N*P + l * (N*d) = D + // l * (N*d) = D - N*P + // l = ( D - N*P ) / ( N*d ) + // + + F32 dot = plane.mDirection * mDirection; + if (fabs(dot) < TOO_SMALL_FOR_DIVISION) + { + return false; + } + + F32 plane_dot = plane.mDirection * plane.mPoint; + F32 length = ( plane_dot - (plane.mDirection * mPoint) ) / dot; + result = mPoint + length * mDirection; + return true; } -//static -// returns 'true' if planes intersect, and stores the result +//static +// returns 'true' if planes intersect, and stores the result // the second and third arguments are treated as planes // where mPoint is on the plane and mDirection is the normal -// result.mPoint will be the intersection line's closest approach +// result.mPoint will be the intersection line's closest approach // to first_plane.mPoint bool LLLine::getIntersectionBetweenTwoPlanes( LLLine& result, const LLLine& first_plane, const LLLine& second_plane ) { - // TODO -- if we ever get some generic matrix solving code in our libs - // then we should just use that, since this problem is really just - // linear algebra. - - F32 dot = fabs(first_plane.mDirection * second_plane.mDirection); - if (dot > ALMOST_PARALLEL) - { - // the planes are nearly parallel - return false; - } - - LLVector3 direction = first_plane.mDirection % second_plane.mDirection; - direction.normalize(); - - LLVector3 first_intersection; - { - LLLine intersection_line(first_plane); - intersection_line.mDirection = direction % first_plane.mDirection; - intersection_line.mDirection.normalize(); - intersection_line.intersectsPlane(first_intersection, second_plane); - } - - /* - LLVector3 second_intersection; - { - LLLine intersection_line(second_plane); - intersection_line.mDirection = direction % second_plane.mDirection; - intersection_line.mDirection.normalize(); - intersection_line.intersectsPlane(second_intersection, first_plane); - } - */ - - result.mPoint = first_intersection; - result.mDirection = direction; - - return true; + // TODO -- if we ever get some generic matrix solving code in our libs + // then we should just use that, since this problem is really just + // linear algebra. + + F32 dot = fabs(first_plane.mDirection * second_plane.mDirection); + if (dot > ALMOST_PARALLEL) + { + // the planes are nearly parallel + return false; + } + + LLVector3 direction = first_plane.mDirection % second_plane.mDirection; + direction.normalize(); + + LLVector3 first_intersection; + { + LLLine intersection_line(first_plane); + intersection_line.mDirection = direction % first_plane.mDirection; + intersection_line.mDirection.normalize(); + intersection_line.intersectsPlane(first_intersection, second_plane); + } + + /* + LLVector3 second_intersection; + { + LLLine intersection_line(second_plane); + intersection_line.mDirection = direction % second_plane.mDirection; + intersection_line.mDirection.normalize(); + intersection_line.intersectsPlane(second_intersection, first_plane); + } + */ + + result.mPoint = first_intersection; + result.mDirection = direction; + + return true; } diff --git a/indra/llmath/llline.h b/indra/llmath/llline.h index e1cbc1323e..33c1eb61a4 100644 --- a/indra/llmath/llline.h +++ b/indra/llmath/llline.h @@ -7,21 +7,21 @@ * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,42 +38,42 @@ const F32 DEFAULT_INTERSECTION_ERROR = 0.000001f; class LLLine { public: - LLLine(); - LLLine( const LLVector3& first_point, const LLVector3& second_point ); - virtual ~LLLine() {}; + LLLine(); + LLLine( const LLVector3& first_point, const LLVector3& second_point ); + virtual ~LLLine() {}; - void setPointDirection( const LLVector3& first_point, const LLVector3& second_point ); - void setPoints( const LLVector3& first_point, const LLVector3& second_point ); + void setPointDirection( const LLVector3& first_point, const LLVector3& second_point ); + void setPoints( const LLVector3& first_point, const LLVector3& second_point ); - bool intersects( const LLVector3& point, F32 radius = DEFAULT_INTERSECTION_ERROR ) const; + bool intersects( const LLVector3& point, F32 radius = DEFAULT_INTERSECTION_ERROR ) const; - // returns the point on this line that is closest to some_point - LLVector3 nearestApproach( const LLVector3& some_point ) const; + // returns the point on this line that is closest to some_point + LLVector3 nearestApproach( const LLVector3& some_point ) const; - // returns the point on this line that is closest to other_line - LLVector3 nearestApproach( const LLLine& other_line ) const; + // returns the point on this line that is closest to other_line + LLVector3 nearestApproach( const LLLine& other_line ) const; - friend std::ostream& operator<<( std::ostream& output_stream, const LLLine& line ); + friend std::ostream& operator<<( std::ostream& output_stream, const LLLine& line ); - // returns 'true' if this line intersects the plane - // on success stores the intersection point in 'result' - bool intersectsPlane( LLVector3& result, const LLLine& plane ) const; + // returns 'true' if this line intersects the plane + // on success stores the intersection point in 'result' + bool intersectsPlane( LLVector3& result, const LLLine& plane ) const; - // returns 'true' if planes intersect, and stores the result - // the second and third arguments are treated as planes - // where mPoint is on the plane and mDirection is the normal - // result.mPoint will be the intersection line's closest approach - // to first_plane.mPoint - static bool getIntersectionBetweenTwoPlanes( LLLine& result, const LLLine& first_plane, const LLLine& second_plane ); + // returns 'true' if planes intersect, and stores the result + // the second and third arguments are treated as planes + // where mPoint is on the plane and mDirection is the normal + // result.mPoint will be the intersection line's closest approach + // to first_plane.mPoint + static bool getIntersectionBetweenTwoPlanes( LLLine& result, const LLLine& first_plane, const LLLine& second_plane ); - const LLVector3& getPoint() const { return mPoint; } - const LLVector3& getDirection() const { return mDirection; } + const LLVector3& getPoint() const { return mPoint; } + const LLVector3& getDirection() const { return mDirection; } protected: - // these are protected because some code assumes that the normal is - // always correct and properly normalized. - LLVector3 mPoint; - LLVector3 mDirection; + // these are protected because some code assumes that the normal is + // always correct and properly normalized. + LLVector3 mPoint; + LLVector3 mDirection; }; diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h index efcc3882fc..4e8fc56de0 100644 --- a/indra/llmath/llmath.h +++ b/indra/llmath/llmath.h @@ -5,21 +5,21 @@ * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -42,47 +42,47 @@ // work around for Windows & older gcc non-standard function names. #if LL_WINDOWS #include <float.h> -#define llisnan(val) _isnan(val) -#define llfinite(val) _finite(val) +#define llisnan(val) _isnan(val) +#define llfinite(val) _finite(val) #elif (LL_LINUX && __GNUC__ <= 2) -#define llisnan(val) isnan(val) -#define llfinite(val) isfinite(val) +#define llisnan(val) isnan(val) +#define llfinite(val) isfinite(val) #else -#define llisnan(val) std::isnan(val) -#define llfinite(val) std::isfinite(val) +#define llisnan(val) std::isnan(val) +#define llfinite(val) std::isfinite(val) #endif // Single Precision Floating Point Routines -// (There used to be more defined here, but they appeared to be redundant and +// (There used to be more defined here, but they appeared to be redundant and // were breaking some other includes. Removed by Falcon, reviewed by Andrew, 11/25/09) /*#ifndef tanf -#define tanf(x) ((F32)tan((F64)(x))) +#define tanf(x) ((F32)tan((F64)(x))) #endif*/ -constexpr F32 GRAVITY = -9.8f; +constexpr F32 GRAVITY = -9.8f; // mathematical constants -constexpr F32 F_PI = 3.1415926535897932384626433832795f; -constexpr F32 F_TWO_PI = 6.283185307179586476925286766559f; -constexpr F32 F_PI_BY_TWO = 1.5707963267948966192313216916398f; -constexpr F32 F_SQRT_TWO_PI = 2.506628274631000502415765284811f; -constexpr F32 F_E = 2.71828182845904523536f; -constexpr F32 F_SQRT2 = 1.4142135623730950488016887242097f; -constexpr F32 F_SQRT3 = 1.73205080756888288657986402541f; -constexpr F32 OO_SQRT2 = 0.7071067811865475244008443621049f; -constexpr F32 OO_SQRT3 = 0.577350269189625764509f; -constexpr F32 DEG_TO_RAD = 0.017453292519943295769236907684886f; -constexpr F32 RAD_TO_DEG = 57.295779513082320876798154814105f; -constexpr F32 F_APPROXIMATELY_ZERO = 0.00001f; -constexpr F32 F_LN10 = 2.3025850929940456840179914546844f; -constexpr F32 OO_LN10 = 0.43429448190325182765112891891661; -constexpr F32 F_LN2 = 0.69314718056f; -constexpr F32 OO_LN2 = 1.4426950408889634073599246810019f; - -constexpr F32 F_ALMOST_ZERO = 0.0001f; -constexpr F32 F_ALMOST_ONE = 1.0f - F_ALMOST_ZERO; - -constexpr F32 GIMBAL_THRESHOLD = 0.000436f; // sets the gimballock threshold 0.025 away from +/-90 degrees +constexpr F32 F_PI = 3.1415926535897932384626433832795f; +constexpr F32 F_TWO_PI = 6.283185307179586476925286766559f; +constexpr F32 F_PI_BY_TWO = 1.5707963267948966192313216916398f; +constexpr F32 F_SQRT_TWO_PI = 2.506628274631000502415765284811f; +constexpr F32 F_E = 2.71828182845904523536f; +constexpr F32 F_SQRT2 = 1.4142135623730950488016887242097f; +constexpr F32 F_SQRT3 = 1.73205080756888288657986402541f; +constexpr F32 OO_SQRT2 = 0.7071067811865475244008443621049f; +constexpr F32 OO_SQRT3 = 0.577350269189625764509f; +constexpr F32 DEG_TO_RAD = 0.017453292519943295769236907684886f; +constexpr F32 RAD_TO_DEG = 57.295779513082320876798154814105f; +constexpr F32 F_APPROXIMATELY_ZERO = 0.00001f; +constexpr F32 F_LN10 = 2.3025850929940456840179914546844f; +constexpr F32 OO_LN10 = 0.43429448190325182765112891891661; +constexpr F32 F_LN2 = 0.69314718056f; +constexpr F32 OO_LN2 = 1.4426950408889634073599246810019f; + +constexpr F32 F_ALMOST_ZERO = 0.0001f; +constexpr F32 F_ALMOST_ONE = 1.0f - F_ALMOST_ZERO; + +constexpr F32 GIMBAL_THRESHOLD = 0.000436f; // sets the gimballock threshold 0.025 away from +/-90 degrees // formula: GIMBAL_THRESHOLD = sin(DEG_TO_RAD * gimbal_threshold_angle); // BUG: Eliminate in favor of F_APPROXIMATELY_ZERO above? @@ -97,7 +97,7 @@ inline bool is_approx_zero( F32 f ) { return (-F_APPROXIMATELY_ZERO < f) && (f < // x = <sign>1 <exponent>00000010 <mantissa>00000000000000000000000 // y = <sign>1 <exponent>00000001 <mantissa>11111111111111111111111 // -// interpreted as ints = +// interpreted as ints = // x = 10000001000000000000000000000000 // y = 10000000111111111111111111111111 // which is clearly a different of 1 in the least significant bit @@ -112,92 +112,92 @@ inline bool is_approx_zero( F32 f ) { return (-F_APPROXIMATELY_ZERO < f) && (f < // WARNING: NaNs can compare equal // There is no special treatment of exceptional values like NaNs // -// WARNING: Infinity is comparable with F32_MAX and negative +// WARNING: Infinity is comparable with F32_MAX and negative // infinity is comparable with F32_MIN // handles negative and positive zeros inline bool is_zero(F32 x) { - return (*(U32*)(&x) & 0x7fffffff) == 0; + return (*(U32*)(&x) & 0x7fffffff) == 0; } inline bool is_approx_equal(F32 x, F32 y) { - constexpr S32 COMPARE_MANTISSA_UP_TO_BIT = 0x02; - return (std::abs((S32) ((U32&)x - (U32&)y) ) < COMPARE_MANTISSA_UP_TO_BIT); + constexpr S32 COMPARE_MANTISSA_UP_TO_BIT = 0x02; + return (std::abs((S32) ((U32&)x - (U32&)y) ) < COMPARE_MANTISSA_UP_TO_BIT); } inline bool is_approx_equal(F64 x, F64 y) { - constexpr S64 COMPARE_MANTISSA_UP_TO_BIT = 0x02; - return (std::abs((S32) ((U64&)x - (U64&)y) ) < COMPARE_MANTISSA_UP_TO_BIT); + constexpr S64 COMPARE_MANTISSA_UP_TO_BIT = 0x02; + return (std::abs((S32) ((U64&)x - (U64&)y) ) < COMPARE_MANTISSA_UP_TO_BIT); } inline S32 llabs(const S32 a) { - return S32(std::labs(a)); + return S32(std::labs(a)); } inline F32 llabs(const F32 a) { - return F32(std::fabs(a)); + return F32(std::fabs(a)); } inline F64 llabs(const F64 a) { - return F64(std::fabs(a)); + return F64(std::fabs(a)); } inline S32 lltrunc( F32 f ) { #if LL_WINDOWS && !defined( __INTEL_COMPILER ) && (ADDRESS_SIZE == 32) - // Avoids changing the floating point control word. - // Add or subtract 0.5 - epsilon and then round - const static U32 zpfp[] = { 0xBEFFFFFF, 0x3EFFFFFF }; - S32 result; - __asm { - fld f - mov eax, f - shr eax, 29 - and eax, 4 - fadd dword ptr [zpfp + eax] - fistp result - } - return result; + // Avoids changing the floating point control word. + // Add or subtract 0.5 - epsilon and then round + const static U32 zpfp[] = { 0xBEFFFFFF, 0x3EFFFFFF }; + S32 result; + __asm { + fld f + mov eax, f + shr eax, 29 + and eax, 4 + fadd dword ptr [zpfp + eax] + fistp result + } + return result; #else - return (S32)f; + return (S32)f; #endif } inline S32 lltrunc( F64 f ) { - return (S32)f; + return (S32)f; } inline S32 llfloor( F32 f ) { #if LL_WINDOWS && !defined( __INTEL_COMPILER ) && (ADDRESS_SIZE == 32) - // Avoids changing the floating point control word. - // Accurate (unlike Stereopsis version) for all values between S32_MIN and S32_MAX and slightly faster than Stereopsis version. - // Add -(0.5 - epsilon) and then round - const U32 zpfp = 0xBEFFFFFF; - S32 result; - __asm { - fld f - fadd dword ptr [zpfp] - fistp result - } - return result; + // Avoids changing the floating point control word. + // Accurate (unlike Stereopsis version) for all values between S32_MIN and S32_MAX and slightly faster than Stereopsis version. + // Add -(0.5 - epsilon) and then round + const U32 zpfp = 0xBEFFFFFF; + S32 result; + __asm { + fld f + fadd dword ptr [zpfp] + fistp result + } + return result; #else - return (S32)floor(f); + return (S32)floor(f); #endif } inline S32 llceil( F32 f ) { - // This could probably be optimized, but this works. - return (S32)ceil(f); + // This could probably be optimized, but this works. + return (S32)ceil(f); } @@ -205,7 +205,7 @@ inline S32 llceil( F32 f ) // Use this round. Does an arithmetic round (0.5 always rounds up) inline S32 ll_round(const F32 val) { - return llfloor(val + 0.5f); + return llfloor(val + 0.5f); } #else // BOGUS_ROUND @@ -214,61 +214,61 @@ inline S32 ll_round(const F32 val) // llfloor(val + 0.5f), which is consistent on all platforms. inline S32 ll_round(const F32 val) { - #if LL_WINDOWS - // Note: assumes that the floating point control word is set to rounding mode (the default) - S32 ret_val; - _asm fld val - _asm fistp ret_val; - return ret_val; - #elif LL_LINUX - // Note: assumes that the floating point control word is set - // to rounding mode (the default) - S32 ret_val; - __asm__ __volatile__( "flds %1 \n\t" - "fistpl %0 \n\t" - : "=m" (ret_val) - : "m" (val) ); - return ret_val; - #else - return llfloor(val + 0.5f); - #endif + #if LL_WINDOWS + // Note: assumes that the floating point control word is set to rounding mode (the default) + S32 ret_val; + _asm fld val + _asm fistp ret_val; + return ret_val; + #elif LL_LINUX + // Note: assumes that the floating point control word is set + // to rounding mode (the default) + S32 ret_val; + __asm__ __volatile__( "flds %1 \n\t" + "fistpl %0 \n\t" + : "=m" (ret_val) + : "m" (val) ); + return ret_val; + #else + return llfloor(val + 0.5f); + #endif } // A fast arithmentic round on intel, from Laurent de Soras http://ldesoras.free.fr inline int round_int(double x) { - const float round_to_nearest = 0.5f; - int i; - __asm - { - fld x - fadd st, st (0) - fadd round_to_nearest - fistp i - sar i, 1 - } - return (i); + const float round_to_nearest = 0.5f; + int i; + __asm + { + fld x + fadd st, st (0) + fadd round_to_nearest + fistp i + sar i, 1 + } + return (i); } #endif // BOGUS_ROUND inline F64 ll_round(const F64 val) { - return F64(floor(val + 0.5f)); + return F64(floor(val + 0.5f)); } inline F32 ll_round( F32 val, F32 nearest ) { - return F32(floor(val * (1.0f / nearest) + 0.5f)) * nearest; + return F32(floor(val * (1.0f / nearest) + 0.5f)) * nearest; } inline F64 ll_round( F64 val, F64 nearest ) { - return F64(floor(val * (1.0 / nearest) + 0.5)) * nearest; + return F64(floor(val * (1.0 / nearest) + 0.5)) * nearest; } // these provide minimum peak error // -// avg error = -0.013049 +// avg error = -0.013049 // peak error = -31.4 dB // RMS error = -28.1 dB @@ -277,7 +277,7 @@ constexpr F32 FAST_MAG_BETA = 0.397824734759f; // these provide minimum RMS error // -// avg error = 0.000003 +// avg error = 0.000003 // peak error = -32.6 dB // RMS error = -25.7 dB // @@ -285,10 +285,10 @@ constexpr F32 FAST_MAG_BETA = 0.397824734759f; //constexpr F32 FAST_MAG_BETA = 0.392699081699f; inline F32 fastMagnitude(F32 a, F32 b) -{ - a = (a > 0) ? a : -a; - b = (b > 0) ? b : -b; - return(FAST_MAG_ALPHA * llmax(a,b) + FAST_MAG_BETA * llmin(a,b)); +{ + a = (a > 0) ? a : -a; + b = (b > 0) ? b : -b; + return(FAST_MAG_ALPHA * llmax(a,b) + FAST_MAG_BETA * llmin(a,b)); } @@ -299,16 +299,16 @@ inline F32 fastMagnitude(F32 a, F32 b) // // Culled from www.stereopsis.com/FPU.html -constexpr F64 LL_DOUBLE_TO_FIX_MAGIC = 68719476736.0*1.5; //2^36 * 1.5, (52-_shiftamt=36) uses limited precisicion to floor -constexpr S32 LL_SHIFT_AMOUNT = 16; //16.16 fixed point representation, +constexpr F64 LL_DOUBLE_TO_FIX_MAGIC = 68719476736.0*1.5; //2^36 * 1.5, (52-_shiftamt=36) uses limited precisicion to floor +constexpr S32 LL_SHIFT_AMOUNT = 16; //16.16 fixed point representation, // Endian dependent code #ifdef LL_LITTLE_ENDIAN - #define LL_EXP_INDEX 1 - #define LL_MAN_INDEX 0 + #define LL_EXP_INDEX 1 + #define LL_MAN_INDEX 0 #else - #define LL_EXP_INDEX 0 - #define LL_MAN_INDEX 1 + #define LL_EXP_INDEX 0 + #define LL_MAN_INDEX 1 #endif //////////////////////////////////////////////// @@ -320,138 +320,138 @@ constexpr S32 LL_SHIFT_AMOUNT = 16; //16.16 fixed point rep // http://www.inf.ethz.ch/~schraudo/pubs/exp.pdf static union { - double d; - struct - { + double d; + struct + { #ifdef LL_LITTLE_ENDIAN - S32 j, i; + S32 j, i; #else - S32 i, j; + S32 i, j; #endif - } n; + } n; } LLECO; // not sure what the name means #define LL_EXP_A (1048576 * OO_LN2) // use 1512775 for integer -#define LL_EXP_C (60801) // this value of C good for -4 < y < 4 +#define LL_EXP_C (60801) // this value of C good for -4 < y < 4 #define LL_FAST_EXP(y) (LLECO.n.i = ll_round(F32(LL_EXP_A*(y))) + (1072693248 - LL_EXP_C), LLECO.d) inline F32 llfastpow(const F32 x, const F32 y) { - return (F32)(LL_FAST_EXP(y * log(x))); + return (F32)(LL_FAST_EXP(y * log(x))); } inline F32 snap_to_sig_figs(F32 foo, S32 sig_figs) { - // compute the power of ten - F32 bar = 1.f; - for (S32 i = 0; i < sig_figs; i++) - { - bar *= 10.f; - } + // compute the power of ten + F32 bar = 1.f; + for (S32 i = 0; i < sig_figs; i++) + { + bar *= 10.f; + } - F32 sign = (foo > 0.f) ? 1.f : -1.f; - F32 new_foo = F32( S64(foo * bar + sign * 0.5f)); - new_foo /= bar; + F32 sign = (foo > 0.f) ? 1.f : -1.f; + F32 new_foo = F32( S64(foo * bar + sign * 0.5f)); + new_foo /= bar; - return new_foo; + return new_foo; } -inline F32 lerp(F32 a, F32 b, F32 u) +inline F32 lerp(F32 a, F32 b, F32 u) { - return a + ((b - a) * u); + return a + ((b - a) * u); } inline F32 lerp2d(F32 x00, F32 x01, F32 x10, F32 x11, F32 u, F32 v) { - F32 a = x00 + (x01-x00)*u; - F32 b = x10 + (x11-x10)*u; - F32 r = a + (b-a)*v; - return r; + F32 a = x00 + (x01-x00)*u; + F32 b = x10 + (x11-x10)*u; + F32 r = a + (b-a)*v; + return r; } inline F32 ramp(F32 x, F32 a, F32 b) { - return (a == b) ? 0.0f : ((a - x) / (a - b)); + return (a == b) ? 0.0f : ((a - x) / (a - b)); } inline F32 rescale(F32 x, F32 x1, F32 x2, F32 y1, F32 y2) { - return lerp(y1, y2, ramp(x, x1, x2)); + return lerp(y1, y2, ramp(x, x1, x2)); } inline F32 clamp_rescale(F32 x, F32 x1, F32 x2, F32 y1, F32 y2) { - if (y1 < y2) - { - return llclamp(rescale(x,x1,x2,y1,y2),y1,y2); - } - else - { - return llclamp(rescale(x,x1,x2,y1,y2),y2,y1); - } + if (y1 < y2) + { + return llclamp(rescale(x,x1,x2,y1,y2),y1,y2); + } + else + { + return llclamp(rescale(x,x1,x2,y1,y2),y2,y1); + } } inline F32 cubic_step( F32 x, F32 x0, F32 x1, F32 s0, F32 s1 ) { - if (x <= x0) - return s0; + if (x <= x0) + return s0; - if (x >= x1) - return s1; + if (x >= x1) + return s1; - F32 f = (x - x0) / (x1 - x0); + F32 f = (x - x0) / (x1 - x0); - return s0 + (s1 - s0) * (f * f) * (3.0f - 2.0f * f); + return s0 + (s1 - s0) * (f * f) * (3.0f - 2.0f * f); } inline F32 cubic_step( F32 x ) { - x = llclampf(x); + x = llclampf(x); - return (x * x) * (3.0f - 2.0f * x); + return (x * x) * (3.0f - 2.0f * x); } inline F32 quadratic_step( F32 x, F32 x0, F32 x1, F32 s0, F32 s1 ) { - if (x <= x0) - return s0; + if (x <= x0) + return s0; - if (x >= x1) - return s1; + if (x >= x1) + return s1; - F32 f = (x - x0) / (x1 - x0); - F32 f_squared = f * f; + F32 f = (x - x0) / (x1 - x0); + F32 f_squared = f * f; - return (s0 * (1.f - f_squared)) + ((s1 - s0) * f_squared); + return (s0 * (1.f - f_squared)) + ((s1 - s0) * f_squared); } inline F32 llsimple_angle(F32 angle) { - while(angle <= -F_PI) - angle += F_TWO_PI; - while(angle > F_PI) - angle -= F_TWO_PI; - return angle; + while(angle <= -F_PI) + angle += F_TWO_PI; + while(angle > F_PI) + angle -= F_TWO_PI; + return angle; } //SDK - Renamed this to get_lower_power_two, since this is what this actually does. inline U32 get_lower_power_two(U32 val, U32 max_power_two) { - if(!max_power_two) - { - max_power_two = 1 << 31 ; - } - if(max_power_two & (max_power_two - 1)) - { - return 0 ; - } + if(!max_power_two) + { + max_power_two = 1 << 31 ; + } + if(max_power_two & (max_power_two - 1)) + { + return 0 ; + } + + for(; val < max_power_two ; max_power_two >>= 1) ; - for(; val < max_power_two ; max_power_two >>= 1) ; - - return max_power_two ; + return max_power_two ; } // calculate next highest power of two, limited by max_power_two @@ -462,76 +462,76 @@ inline U32 get_lower_power_two(U32 val, U32 max_power_two) // WARNING: this only works with 32 bit ints. inline U32 get_next_power_two(U32 val, U32 max_power_two) { - if(!max_power_two) - { - max_power_two = 1 << 31 ; - } + if(!max_power_two) + { + max_power_two = 1 << 31 ; + } - if(val >= max_power_two) - { - return max_power_two; - } + if(val >= max_power_two) + { + return max_power_two; + } - val--; - val = (val >> 1) | val; - val = (val >> 2) | val; - val = (val >> 4) | val; - val = (val >> 8) | val; - val = (val >> 16) | val; - val++; + val--; + val = (val >> 1) | val; + val = (val >> 2) | val; + val = (val >> 4) | val; + val = (val >> 8) | val; + val = (val >> 16) | val; + val++; - return val; + return val; } //get the gaussian value given the linear distance from axis x and guassian value o inline F32 llgaussian(F32 x, F32 o) { - return 1.f/(F_SQRT_TWO_PI*o)*powf(F_E, -(x*x)/(2*o*o)); + return 1.f/(F_SQRT_TWO_PI*o)*powf(F_E, -(x*x)/(2*o*o)); } //helper function for removing outliers template <class VEC_TYPE> inline void ll_remove_outliers(std::vector<VEC_TYPE>& data, F32 k) { - if (data.size() < 100) - { //not enough samples - return; - } + if (data.size() < 100) + { //not enough samples + return; + } - VEC_TYPE Q1 = data[data.size()/4]; - VEC_TYPE Q3 = data[data.size()-data.size()/4-1]; + VEC_TYPE Q1 = data[data.size()/4]; + VEC_TYPE Q3 = data[data.size()-data.size()/4-1]; - if ((F32)(Q3-Q1) < 1.f) - { - // not enough variation to detect outliers - return; - } + if ((F32)(Q3-Q1) < 1.f) + { + // not enough variation to detect outliers + return; + } - VEC_TYPE min = (VEC_TYPE) ((F32) Q1-k * (F32) (Q3-Q1)); - VEC_TYPE max = (VEC_TYPE) ((F32) Q3+k * (F32) (Q3-Q1)); + VEC_TYPE min = (VEC_TYPE) ((F32) Q1-k * (F32) (Q3-Q1)); + VEC_TYPE max = (VEC_TYPE) ((F32) Q3+k * (F32) (Q3-Q1)); - U32 i = 0; - while (i < data.size() && data[i] < min) - { - i++; - } + U32 i = 0; + while (i < data.size() && data[i] < min) + { + i++; + } - S32 j = data.size()-1; - while (j > 0 && data[j] > max) - { - j--; - } + S32 j = data.size()-1; + while (j > 0 && data[j] > max) + { + j--; + } - if (j < data.size()-1) - { - data.erase(data.begin()+j, data.end()); - } + if (j < data.size()-1) + { + data.erase(data.begin()+j, data.end()); + } - if (i > 0) - { - data.erase(data.begin(), data.begin()+i); - } + if (i > 0) + { + data.erase(data.begin(), data.begin()+i); + } } // Converts given value from a linear RGB floating point value (0..1) to a gamma corrected (sRGB) value. @@ -551,7 +551,7 @@ inline float linearTosRGB(const float val) { // Converts given value from a gamma corrected (sRGB) floating point value (0..1) to a linear color value. // Some shaders require color values in linear space, while others require color values in gamma corrected (sRGB) space. // Note: In our code, values labeled as sRGB are gamma corrected linear values, NOT linear values with monitor gamma applied -// Note: Stored color values should generally be gamma corrected sRGB. +// Note: Stored color values should generally be gamma corrected sRGB. // If you're serializing the return value of this function, you're probably doing it wrong. // Note: DO NOT cache the conversion. This leads to error prone synchronization and is actually slower in the typical case due to cache misses. inline float sRGBtoLinear(const float val) { diff --git a/indra/llmath/llmatrix3a.cpp b/indra/llmath/llmatrix3a.cpp index ab077abcb0..48a72e71e1 100644 --- a/indra/llmath/llmatrix3a.cpp +++ b/indra/llmath/llmatrix3a.cpp @@ -1,134 +1,134 @@ -/** +/** * @file llvector4a.cpp * @brief SIMD vector implementation * * $LicenseInfo:firstyear=2010&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #include "llmath.h" -static LL_ALIGN_16(const F32 M_IDENT_3A[12]) = - { 1.f, 0.f, 0.f, 0.f, // Column 1 - 0.f, 1.f, 0.f, 0.f, // Column 2 - 0.f, 0.f, 1.f, 0.f }; // Column 3 +static LL_ALIGN_16(const F32 M_IDENT_3A[12]) = + { 1.f, 0.f, 0.f, 0.f, // Column 1 + 0.f, 1.f, 0.f, 0.f, // Column 2 + 0.f, 0.f, 1.f, 0.f }; // Column 3 extern const LLMatrix3a LL_M3A_IDENTITY = *reinterpret_cast<const LLMatrix3a*> (M_IDENT_3A); void LLMatrix3a::setMul( const LLMatrix3a& lhs, const LLMatrix3a& rhs ) { - const LLVector4a col0 = lhs.getColumn(0); - const LLVector4a col1 = lhs.getColumn(1); - const LLVector4a col2 = lhs.getColumn(2); - - for ( int i = 0; i < 3; i++ ) - { - LLVector4a xxxx = _mm_load_ss( rhs.mColumns[i].getF32ptr() ); - xxxx.splat<0>( xxxx ); - xxxx.mul( col0 ); - - { - LLVector4a yyyy = _mm_load_ss( rhs.mColumns[i].getF32ptr() + 1 ); - yyyy.splat<0>( yyyy ); - yyyy.mul( col1 ); - xxxx.add( yyyy ); - } - - { - LLVector4a zzzz = _mm_load_ss( rhs.mColumns[i].getF32ptr() + 2 ); - zzzz.splat<0>( zzzz ); - zzzz.mul( col2 ); - xxxx.add( zzzz ); - } - - xxxx.store4a( mColumns[i].getF32ptr() ); - } - + const LLVector4a col0 = lhs.getColumn(0); + const LLVector4a col1 = lhs.getColumn(1); + const LLVector4a col2 = lhs.getColumn(2); + + for ( int i = 0; i < 3; i++ ) + { + LLVector4a xxxx = _mm_load_ss( rhs.mColumns[i].getF32ptr() ); + xxxx.splat<0>( xxxx ); + xxxx.mul( col0 ); + + { + LLVector4a yyyy = _mm_load_ss( rhs.mColumns[i].getF32ptr() + 1 ); + yyyy.splat<0>( yyyy ); + yyyy.mul( col1 ); + xxxx.add( yyyy ); + } + + { + LLVector4a zzzz = _mm_load_ss( rhs.mColumns[i].getF32ptr() + 2 ); + zzzz.splat<0>( zzzz ); + zzzz.mul( col2 ); + xxxx.add( zzzz ); + } + + xxxx.store4a( mColumns[i].getF32ptr() ); + } + } /*static */void LLMatrix3a::batchTransform( const LLMatrix3a& xform, const LLVector4a* src, int numVectors, LLVector4a* dst ) { - const LLVector4a col0 = xform.getColumn(0); - const LLVector4a col1 = xform.getColumn(1); - const LLVector4a col2 = xform.getColumn(2); - const LLVector4a* maxAddr = src + numVectors; - - if ( numVectors & 0x1 ) - { - LLVector4a xxxx = _mm_load_ss( (const F32*)src ); - LLVector4a yyyy = _mm_load_ss( (const F32*)src + 1 ); - LLVector4a zzzz = _mm_load_ss( (const F32*)src + 2 ); - xxxx.splat<0>( xxxx ); - yyyy.splat<0>( yyyy ); - zzzz.splat<0>( zzzz ); - xxxx.mul( col0 ); - yyyy.mul( col1 ); - zzzz.mul( col2 ); - xxxx.add( yyyy ); - xxxx.add( zzzz ); - xxxx.store4a( (F32*)dst ); - src++; - dst++; - } - - - numVectors >>= 1; - while ( src < maxAddr ) - { - _mm_prefetch( (const char*)(src + 32 ), _MM_HINT_NTA ); - _mm_prefetch( (const char*)(dst + 32), _MM_HINT_NTA ); - LLVector4a xxxx = _mm_load_ss( (const F32*)src ); - LLVector4a xxxx1= _mm_load_ss( (const F32*)(src + 1) ); - - xxxx.splat<0>( xxxx ); - xxxx1.splat<0>( xxxx1 ); - xxxx.mul( col0 ); - xxxx1.mul( col0 ); - - { - LLVector4a yyyy = _mm_load_ss( (const F32*)src + 1 ); - LLVector4a yyyy1 = _mm_load_ss( (const F32*)(src + 1) + 1); - yyyy.splat<0>( yyyy ); - yyyy1.splat<0>( yyyy1 ); - yyyy.mul( col1 ); - yyyy1.mul( col1 ); - xxxx.add( yyyy ); - xxxx1.add( yyyy1 ); - } - - { - LLVector4a zzzz = _mm_load_ss( (const F32*)(src) + 2 ); - LLVector4a zzzz1 = _mm_load_ss( (const F32*)(++src) + 2 ); - zzzz.splat<0>( zzzz ); - zzzz1.splat<0>( zzzz1 ); - zzzz.mul( col2 ); - zzzz1.mul( col2 ); - xxxx.add( zzzz ); - xxxx1.add( zzzz1 ); - } - - xxxx.store4a(dst->getF32ptr()); - src++; - dst++; - - xxxx1.store4a((F32*)dst++); - } + const LLVector4a col0 = xform.getColumn(0); + const LLVector4a col1 = xform.getColumn(1); + const LLVector4a col2 = xform.getColumn(2); + const LLVector4a* maxAddr = src + numVectors; + + if ( numVectors & 0x1 ) + { + LLVector4a xxxx = _mm_load_ss( (const F32*)src ); + LLVector4a yyyy = _mm_load_ss( (const F32*)src + 1 ); + LLVector4a zzzz = _mm_load_ss( (const F32*)src + 2 ); + xxxx.splat<0>( xxxx ); + yyyy.splat<0>( yyyy ); + zzzz.splat<0>( zzzz ); + xxxx.mul( col0 ); + yyyy.mul( col1 ); + zzzz.mul( col2 ); + xxxx.add( yyyy ); + xxxx.add( zzzz ); + xxxx.store4a( (F32*)dst ); + src++; + dst++; + } + + + numVectors >>= 1; + while ( src < maxAddr ) + { + _mm_prefetch( (const char*)(src + 32 ), _MM_HINT_NTA ); + _mm_prefetch( (const char*)(dst + 32), _MM_HINT_NTA ); + LLVector4a xxxx = _mm_load_ss( (const F32*)src ); + LLVector4a xxxx1= _mm_load_ss( (const F32*)(src + 1) ); + + xxxx.splat<0>( xxxx ); + xxxx1.splat<0>( xxxx1 ); + xxxx.mul( col0 ); + xxxx1.mul( col0 ); + + { + LLVector4a yyyy = _mm_load_ss( (const F32*)src + 1 ); + LLVector4a yyyy1 = _mm_load_ss( (const F32*)(src + 1) + 1); + yyyy.splat<0>( yyyy ); + yyyy1.splat<0>( yyyy1 ); + yyyy.mul( col1 ); + yyyy1.mul( col1 ); + xxxx.add( yyyy ); + xxxx1.add( yyyy1 ); + } + + { + LLVector4a zzzz = _mm_load_ss( (const F32*)(src) + 2 ); + LLVector4a zzzz1 = _mm_load_ss( (const F32*)(++src) + 2 ); + zzzz.splat<0>( zzzz ); + zzzz1.splat<0>( zzzz1 ); + zzzz.mul( col2 ); + zzzz1.mul( col2 ); + xxxx.add( zzzz ); + xxxx1.add( zzzz1 ); + } + + xxxx.store4a(dst->getF32ptr()); + src++; + dst++; + + xxxx1.store4a((F32*)dst++); + } } diff --git a/indra/llmath/llmatrix3a.h b/indra/llmath/llmatrix3a.h index 9916cfd2da..dff6604ae5 100644 --- a/indra/llmath/llmatrix3a.h +++ b/indra/llmath/llmatrix3a.h @@ -1,31 +1,31 @@ -/** +/** * @file llmatrix3a.h * @brief LLMatrix3a class header file - memory aligned and vectorized 3x3 matrix * * $LicenseInfo:firstyear=2010&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ -#ifndef LL_LLMATRIX3A_H -#define LL_LLMATRIX3A_H +#ifndef LL_LLMATRIX3A_H +#define LL_LLMATRIX3A_H ///////////////////////////// // LLMatrix3a, LLRotation @@ -38,91 +38,91 @@ // Huseby). ///////////////////////////// -// LLMatrix3a is the base class for LLRotation, which should be used instead any time you're dealing with a +// LLMatrix3a is the base class for LLRotation, which should be used instead any time you're dealing with a // rotation matrix. class LLMatrix3a { public: - // Utility function for quickly transforming an array of LLVector4a's - // For transforming a single LLVector4a, see LLVector4a::setRotated - static void batchTransform( const LLMatrix3a& xform, const LLVector4a* src, int numVectors, LLVector4a* dst ); + // Utility function for quickly transforming an array of LLVector4a's + // For transforming a single LLVector4a, see LLVector4a::setRotated + static void batchTransform( const LLMatrix3a& xform, const LLVector4a* src, int numVectors, LLVector4a* dst ); + + // Utility function to obtain the identity matrix + static inline const LLMatrix3a& getIdentity(); - // Utility function to obtain the identity matrix - static inline const LLMatrix3a& getIdentity(); + ////////////////////////// + // Ctors + ////////////////////////// - ////////////////////////// - // Ctors - ////////////////////////// - - // Ctor - LLMatrix3a() {} + // Ctor + LLMatrix3a() {} - // Ctor for setting by columns - inline LLMatrix3a( const LLVector4a& c0, const LLVector4a& c1, const LLVector4a& c2 ); + // Ctor for setting by columns + inline LLMatrix3a( const LLVector4a& c0, const LLVector4a& c1, const LLVector4a& c2 ); - ////////////////////////// - // Get/Set - ////////////////////////// + ////////////////////////// + // Get/Set + ////////////////////////// - // Loads from an LLMatrix3 - inline void loadu(const LLMatrix3& src); - - // Set rows - inline void setRows(const LLVector4a& r0, const LLVector4a& r1, const LLVector4a& r2); - - // Set columns - inline void setColumns(const LLVector4a& c0, const LLVector4a& c1, const LLVector4a& c2); + // Loads from an LLMatrix3 + inline void loadu(const LLMatrix3& src); - // Get the read-only access to a specified column. Valid columns are 0-2, but the - // function is unchecked. You've been warned. - inline const LLVector4a& getColumn(const U32 column) const; + // Set rows + inline void setRows(const LLVector4a& r0, const LLVector4a& r1, const LLVector4a& r2); - ///////////////////////// - // Matrix modification - ///////////////////////// - - // Set this matrix to the product of lhs and rhs ( this = lhs * rhs ) - void setMul( const LLMatrix3a& lhs, const LLMatrix3a& rhs ); + // Set columns + inline void setColumns(const LLVector4a& c0, const LLVector4a& c1, const LLVector4a& c2); - // Set this matrix to the transpose of src - inline void setTranspose(const LLMatrix3a& src); + // Get the read-only access to a specified column. Valid columns are 0-2, but the + // function is unchecked. You've been warned. + inline const LLVector4a& getColumn(const U32 column) const; - // Set this matrix to a*w + b*(1-w) - inline void setLerp(const LLMatrix3a& a, const LLMatrix3a& b, F32 w); + ///////////////////////// + // Matrix modification + ///////////////////////// - ///////////////////////// - // Matrix inspection - ///////////////////////// + // Set this matrix to the product of lhs and rhs ( this = lhs * rhs ) + void setMul( const LLMatrix3a& lhs, const LLMatrix3a& rhs ); - // Sets all 4 elements in 'dest' to the determinant of this matrix. - // If you will be using the determinant in subsequent ops with LLVector4a, use this version - inline void getDeterminant( LLVector4a& dest ) const; + // Set this matrix to the transpose of src + inline void setTranspose(const LLMatrix3a& src); - // Returns the determinant as an LLSimdScalar. Use this if you will be using the determinant - // primary for scalar operations. - inline LLSimdScalar getDeterminant() const; + // Set this matrix to a*w + b*(1-w) + inline void setLerp(const LLMatrix3a& a, const LLMatrix3a& b, F32 w); - // Returns nonzero if rows 0-2 and colums 0-2 contain no NaN or INF values. Row 3 is ignored - inline LLBool32 isFinite() const; + ///////////////////////// + // Matrix inspection + ///////////////////////// - // Returns true if this matrix is equal to 'rhs' up to 'tolerance' - inline bool isApproximatelyEqual( const LLMatrix3a& rhs, F32 tolerance = F_APPROXIMATELY_ZERO ) const; + // Sets all 4 elements in 'dest' to the determinant of this matrix. + // If you will be using the determinant in subsequent ops with LLVector4a, use this version + inline void getDeterminant( LLVector4a& dest ) const; + + // Returns the determinant as an LLSimdScalar. Use this if you will be using the determinant + // primary for scalar operations. + inline LLSimdScalar getDeterminant() const; + + // Returns nonzero if rows 0-2 and colums 0-2 contain no NaN or INF values. Row 3 is ignored + inline LLBool32 isFinite() const; + + // Returns true if this matrix is equal to 'rhs' up to 'tolerance' + inline bool isApproximatelyEqual( const LLMatrix3a& rhs, F32 tolerance = F_APPROXIMATELY_ZERO ) const; protected: - LL_ALIGN_16(LLVector4a mColumns[3]); + LL_ALIGN_16(LLVector4a mColumns[3]); }; class LLRotation : public LLMatrix3a { public: - - LLRotation() {} - - // Returns true if this rotation is orthonormal with det ~= 1 - inline bool isOkRotation() const; + + LLRotation() {} + + // Returns true if this rotation is orthonormal with det ~= 1 + inline bool isOkRotation() const; }; #endif diff --git a/indra/llmath/llmatrix3a.inl b/indra/llmath/llmatrix3a.inl index 37819fea3c..262810746e 100644 --- a/indra/llmath/llmatrix3a.inl +++ b/indra/llmath/llmatrix3a.inl @@ -1,25 +1,25 @@ -/** +/** * @file llmatrix3a.inl * @brief LLMatrix3a inline definitions * * $LicenseInfo:firstyear=2010&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -29,91 +29,91 @@ inline LLMatrix3a::LLMatrix3a( const LLVector4a& c0, const LLVector4a& c1, const LLVector4a& c2 ) { - setColumns( c0, c1, c2 ); + setColumns( c0, c1, c2 ); } inline void LLMatrix3a::loadu(const LLMatrix3& src) { - mColumns[0].load3(src.mMatrix[0]); - mColumns[1].load3(src.mMatrix[1]); - mColumns[2].load3(src.mMatrix[2]); + mColumns[0].load3(src.mMatrix[0]); + mColumns[1].load3(src.mMatrix[1]); + mColumns[2].load3(src.mMatrix[2]); } inline void LLMatrix3a::setRows(const LLVector4a& r0, const LLVector4a& r1, const LLVector4a& r2) { - mColumns[0] = r0; - mColumns[1] = r1; - mColumns[2] = r2; - setTranspose( *this ); + mColumns[0] = r0; + mColumns[1] = r1; + mColumns[2] = r2; + setTranspose( *this ); } inline void LLMatrix3a::setColumns(const LLVector4a& c0, const LLVector4a& c1, const LLVector4a& c2) { - mColumns[0] = c0; - mColumns[1] = c1; - mColumns[2] = c2; + mColumns[0] = c0; + mColumns[1] = c1; + mColumns[2] = c2; } inline void LLMatrix3a::setTranspose(const LLMatrix3a& src) { - const LLQuad srcCol0 = src.mColumns[0]; - const LLQuad srcCol1 = src.mColumns[1]; - const LLQuad unpacklo = _mm_unpacklo_ps( srcCol0, srcCol1 ); - mColumns[0] = _mm_movelh_ps( unpacklo, src.mColumns[2] ); - mColumns[1] = _mm_shuffle_ps( _mm_movehl_ps( srcCol0, unpacklo ), src.mColumns[2], _MM_SHUFFLE(0, 1, 1, 0) ); - mColumns[2] = _mm_shuffle_ps( _mm_unpackhi_ps( srcCol0, srcCol1 ), src.mColumns[2], _MM_SHUFFLE(0, 2, 1, 0) ); + const LLQuad srcCol0 = src.mColumns[0]; + const LLQuad srcCol1 = src.mColumns[1]; + const LLQuad unpacklo = _mm_unpacklo_ps( srcCol0, srcCol1 ); + mColumns[0] = _mm_movelh_ps( unpacklo, src.mColumns[2] ); + mColumns[1] = _mm_shuffle_ps( _mm_movehl_ps( srcCol0, unpacklo ), src.mColumns[2], _MM_SHUFFLE(0, 1, 1, 0) ); + mColumns[2] = _mm_shuffle_ps( _mm_unpackhi_ps( srcCol0, srcCol1 ), src.mColumns[2], _MM_SHUFFLE(0, 2, 1, 0) ); } inline const LLVector4a& LLMatrix3a::getColumn(const U32 column) const { - llassert( column < 3 ); - return mColumns[column]; + llassert( column < 3 ); + return mColumns[column]; } inline void LLMatrix3a::setLerp(const LLMatrix3a& a, const LLMatrix3a& b, F32 w) { - mColumns[0].setLerp( a.mColumns[0], b.mColumns[0], w ); - mColumns[1].setLerp( a.mColumns[1], b.mColumns[1], w ); - mColumns[2].setLerp( a.mColumns[2], b.mColumns[2], w ); + mColumns[0].setLerp( a.mColumns[0], b.mColumns[0], w ); + mColumns[1].setLerp( a.mColumns[1], b.mColumns[1], w ); + mColumns[2].setLerp( a.mColumns[2], b.mColumns[2], w ); } inline LLBool32 LLMatrix3a::isFinite() const { - return mColumns[0].isFinite3() && mColumns[1].isFinite3() && mColumns[2].isFinite3(); + return mColumns[0].isFinite3() && mColumns[1].isFinite3() && mColumns[2].isFinite3(); } inline void LLMatrix3a::getDeterminant( LLVector4a& dest ) const { - LLVector4a col1xcol2; col1xcol2.setCross3( mColumns[1], mColumns[2] ); - dest.setAllDot3( col1xcol2, mColumns[0] ); + LLVector4a col1xcol2; col1xcol2.setCross3( mColumns[1], mColumns[2] ); + dest.setAllDot3( col1xcol2, mColumns[0] ); } inline LLSimdScalar LLMatrix3a::getDeterminant() const { - LLVector4a col1xcol2; col1xcol2.setCross3( mColumns[1], mColumns[2] ); - return col1xcol2.dot3( mColumns[0] ); + LLVector4a col1xcol2; col1xcol2.setCross3( mColumns[1], mColumns[2] ); + return col1xcol2.dot3( mColumns[0] ); } inline bool LLMatrix3a::isApproximatelyEqual( const LLMatrix3a& rhs, F32 tolerance /*= F_APPROXIMATELY_ZERO*/ ) const { - return rhs.getColumn(0).equals3(mColumns[0], tolerance) - && rhs.getColumn(1).equals3(mColumns[1], tolerance) - && rhs.getColumn(2).equals3(mColumns[2], tolerance); + return rhs.getColumn(0).equals3(mColumns[0], tolerance) + && rhs.getColumn(1).equals3(mColumns[1], tolerance) + && rhs.getColumn(2).equals3(mColumns[2], tolerance); } inline const LLMatrix3a& LLMatrix3a::getIdentity() { - extern const LLMatrix3a LL_M3A_IDENTITY; - return LL_M3A_IDENTITY; + extern const LLMatrix3a LL_M3A_IDENTITY; + return LL_M3A_IDENTITY; } inline bool LLRotation::isOkRotation() const { - LLMatrix3a transpose; transpose.setTranspose( *this ); - LLMatrix3a product; product.setMul( *this, transpose ); + LLMatrix3a transpose; transpose.setTranspose( *this ); + LLMatrix3a product; product.setMul( *this, transpose ); - LLSimdScalar detMinusOne = getDeterminant() - 1.f; + LLSimdScalar detMinusOne = getDeterminant() - 1.f; - return product.isApproximatelyEqual( LLMatrix3a::getIdentity() ) && (detMinusOne.getAbs() < F_APPROXIMATELY_ZERO); + return product.isApproximatelyEqual( LLMatrix3a::getIdentity() ) && (detMinusOne.getAbs() < F_APPROXIMATELY_ZERO); } diff --git a/indra/llmath/llmatrix4a.cpp b/indra/llmath/llmatrix4a.cpp index fe8f0b98f3..00e30a248b 100644 --- a/indra/llmath/llmatrix4a.cpp +++ b/indra/llmath/llmatrix4a.cpp @@ -33,48 +33,48 @@ // necessarily the fastest way to implement. void matMulBoundBox(const LLMatrix4a &mat, const LLVector4a *in_extents, LLVector4a *out_extents) { - //get 8 corners of bounding box - LLVector4Logical mask[6]; + //get 8 corners of bounding box + LLVector4Logical mask[6]; - for (U32 i = 0; i < 6; ++i) - { - mask[i].clear(); - } + for (U32 i = 0; i < 6; ++i) + { + mask[i].clear(); + } - mask[0].setElement<2>(); //001 - mask[1].setElement<1>(); //010 - mask[2].setElement<1>(); //011 - mask[2].setElement<2>(); - mask[3].setElement<0>(); //100 - mask[4].setElement<0>(); //101 - mask[4].setElement<2>(); - mask[5].setElement<0>(); //110 - mask[5].setElement<1>(); + mask[0].setElement<2>(); //001 + mask[1].setElement<1>(); //010 + mask[2].setElement<1>(); //011 + mask[2].setElement<2>(); + mask[3].setElement<0>(); //100 + mask[4].setElement<0>(); //101 + mask[4].setElement<2>(); + mask[5].setElement<0>(); //110 + mask[5].setElement<1>(); - LLVector4a v[8]; + LLVector4a v[8]; - v[6] = in_extents[0]; - v[7] = in_extents[1]; + v[6] = in_extents[0]; + v[7] = in_extents[1]; - for (U32 i = 0; i < 6; ++i) - { - v[i].setSelectWithMask(mask[i], in_extents[0], in_extents[1]); - } + for (U32 i = 0; i < 6; ++i) + { + v[i].setSelectWithMask(mask[i], in_extents[0], in_extents[1]); + } - LLVector4a tv[8]; + LLVector4a tv[8]; - //transform bounding box into drawable space - for (U32 i = 0; i < 8; ++i) - { - mat.affineTransform(v[i], tv[i]); - } - - //find bounding box - out_extents[0] = out_extents[1] = tv[0]; + //transform bounding box into drawable space + for (U32 i = 0; i < 8; ++i) + { + mat.affineTransform(v[i], tv[i]); + } - for (U32 i = 1; i < 8; ++i) - { - out_extents[0].setMin(out_extents[0], tv[i]); - out_extents[1].setMax(out_extents[1], tv[i]); - } + //find bounding box + out_extents[0] = out_extents[1] = tv[0]; + + for (U32 i = 1; i < 8; ++i) + { + out_extents[0].setMin(out_extents[0], tv[i]); + out_extents[1].setMax(out_extents[1], tv[i]); + } } diff --git a/indra/llmath/llmatrix4a.h b/indra/llmath/llmatrix4a.h index 12fc6d570a..cf4e522467 100644 --- a/indra/llmath/llmatrix4a.h +++ b/indra/llmath/llmatrix4a.h @@ -1,31 +1,31 @@ -/** +/** * @file llmatrix4a.h * @brief LLMatrix4a class header file - memory aligned and vectorized 4x4 matrix * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ -#ifndef LL_LLMATRIX4A_H -#define LL_LLMATRIX4A_H +#ifndef LL_LLMATRIX4A_H +#define LL_LLMATRIX4A_H #include "llvector4a.h" #include "m4math.h" @@ -35,7 +35,7 @@ class LLMatrix4a { public: LL_ALIGN_16(LLVector4a mMatrix[4]); - + LLMatrix4a() { @@ -66,13 +66,13 @@ public: return *(LLMatrix4*)this; } - inline void clear() - { - mMatrix[0].clear(); - mMatrix[1].clear(); - mMatrix[2].clear(); - mMatrix[3].clear(); - } + inline void clear() + { + mMatrix[0].clear(); + mMatrix[1].clear(); + mMatrix[2].clear(); + mMatrix[3].clear(); + } inline void setIdentity() { @@ -82,14 +82,14 @@ public: mMatrix[3].set(0.f, 0.f, 0.f, 1.f); } - inline void loadu(const LLMatrix4& src) - { - mMatrix[0] = _mm_loadu_ps(src.mMatrix[0]); - mMatrix[1] = _mm_loadu_ps(src.mMatrix[1]); - mMatrix[2] = _mm_loadu_ps(src.mMatrix[2]); - mMatrix[3] = _mm_loadu_ps(src.mMatrix[3]); - } - + inline void loadu(const LLMatrix4& src) + { + mMatrix[0] = _mm_loadu_ps(src.mMatrix[0]); + mMatrix[1] = _mm_loadu_ps(src.mMatrix[1]); + mMatrix[2] = _mm_loadu_ps(src.mMatrix[2]); + mMatrix[3] = _mm_loadu_ps(src.mMatrix[3]); + } + inline void loadu(const F32* src) { mMatrix[0] = _mm_loadu_ps(src); @@ -98,90 +98,90 @@ public: mMatrix[3] = _mm_loadu_ps(src+12); } - inline void loadu(const LLMatrix3& src) - { - mMatrix[0].load3(src.mMatrix[0]); - mMatrix[1].load3(src.mMatrix[1]); - mMatrix[2].load3(src.mMatrix[2]); - mMatrix[3].set(0,0,0,1.f); - } - - inline void add(const LLMatrix4a& rhs) - { - mMatrix[0].add(rhs.mMatrix[0]); - mMatrix[1].add(rhs.mMatrix[1]); - mMatrix[2].add(rhs.mMatrix[2]); - mMatrix[3].add(rhs.mMatrix[3]); - } - - inline void setRows(const LLVector4a& r0, const LLVector4a& r1, const LLVector4a& r2) - { - mMatrix[0] = r0; - mMatrix[1] = r1; - mMatrix[2] = r2; - } - - inline void setMul(const LLMatrix4a& m, const F32 s) - { - mMatrix[0].setMul(m.mMatrix[0], s); - mMatrix[1].setMul(m.mMatrix[1], s); - mMatrix[2].setMul(m.mMatrix[2], s); - mMatrix[3].setMul(m.mMatrix[3], s); - } - - inline void setLerp(const LLMatrix4a& a, const LLMatrix4a& b, F32 w) - { - LLVector4a d0,d1,d2,d3; - d0.setSub(b.mMatrix[0], a.mMatrix[0]); - d1.setSub(b.mMatrix[1], a.mMatrix[1]); - d2.setSub(b.mMatrix[2], a.mMatrix[2]); - d3.setSub(b.mMatrix[3], a.mMatrix[3]); - - // this = a + d*w - - d0.mul(w); - d1.mul(w); - d2.mul(w); - d3.mul(w); - - mMatrix[0].setAdd(a.mMatrix[0],d0); - mMatrix[1].setAdd(a.mMatrix[1],d1); - mMatrix[2].setAdd(a.mMatrix[2],d2); - mMatrix[3].setAdd(a.mMatrix[3],d3); - } - - inline void rotate(const LLVector4a& v, LLVector4a& res) const - { - LLVector4a y,z; - - res = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0)); - y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1)); - z = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2)); - - res.mul(mMatrix[0]); - y.mul(mMatrix[1]); - z.mul(mMatrix[2]); - - res.add(y); - res.add(z); - } - - inline void affineTransformSSE(const LLVector4a& v, LLVector4a& res) const - { - LLVector4a x,y,z; - - x = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0)); - y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1)); - z = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2)); - - x.mul(mMatrix[0]); - y.mul(mMatrix[1]); - z.mul(mMatrix[2]); - - x.add(y); - z.add(mMatrix[3]); - res.setAdd(x,z); - } + inline void loadu(const LLMatrix3& src) + { + mMatrix[0].load3(src.mMatrix[0]); + mMatrix[1].load3(src.mMatrix[1]); + mMatrix[2].load3(src.mMatrix[2]); + mMatrix[3].set(0,0,0,1.f); + } + + inline void add(const LLMatrix4a& rhs) + { + mMatrix[0].add(rhs.mMatrix[0]); + mMatrix[1].add(rhs.mMatrix[1]); + mMatrix[2].add(rhs.mMatrix[2]); + mMatrix[3].add(rhs.mMatrix[3]); + } + + inline void setRows(const LLVector4a& r0, const LLVector4a& r1, const LLVector4a& r2) + { + mMatrix[0] = r0; + mMatrix[1] = r1; + mMatrix[2] = r2; + } + + inline void setMul(const LLMatrix4a& m, const F32 s) + { + mMatrix[0].setMul(m.mMatrix[0], s); + mMatrix[1].setMul(m.mMatrix[1], s); + mMatrix[2].setMul(m.mMatrix[2], s); + mMatrix[3].setMul(m.mMatrix[3], s); + } + + inline void setLerp(const LLMatrix4a& a, const LLMatrix4a& b, F32 w) + { + LLVector4a d0,d1,d2,d3; + d0.setSub(b.mMatrix[0], a.mMatrix[0]); + d1.setSub(b.mMatrix[1], a.mMatrix[1]); + d2.setSub(b.mMatrix[2], a.mMatrix[2]); + d3.setSub(b.mMatrix[3], a.mMatrix[3]); + + // this = a + d*w + + d0.mul(w); + d1.mul(w); + d2.mul(w); + d3.mul(w); + + mMatrix[0].setAdd(a.mMatrix[0],d0); + mMatrix[1].setAdd(a.mMatrix[1],d1); + mMatrix[2].setAdd(a.mMatrix[2],d2); + mMatrix[3].setAdd(a.mMatrix[3],d3); + } + + inline void rotate(const LLVector4a& v, LLVector4a& res) const + { + LLVector4a y,z; + + res = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0)); + y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1)); + z = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2)); + + res.mul(mMatrix[0]); + y.mul(mMatrix[1]); + z.mul(mMatrix[2]); + + res.add(y); + res.add(z); + } + + inline void affineTransformSSE(const LLVector4a& v, LLVector4a& res) const + { + LLVector4a x,y,z; + + x = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0)); + y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1)); + z = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2)); + + x.mul(mMatrix[0]); + y.mul(mMatrix[1]); + z.mul(mMatrix[2]); + + x.add(y); + z.add(mMatrix[3]); + res.setAdd(x,z); + } inline void affineTransformNonSSE(const LLVector4a& v, LLVector4a& res) const { @@ -192,7 +192,7 @@ public: res.set(x,y,z,w); } - inline void affineTransform(const LLVector4a& v, LLVector4a& res) const + inline void affineTransform(const LLVector4a& v, LLVector4a& res) const { affineTransformSSE(v,res); } @@ -236,7 +236,7 @@ inline std::ostream& operator<<(std::ostream& s, const LLMatrix4a& m) { s << "[" << m.mMatrix[0] << ", " << m.mMatrix[1] << ", " << m.mMatrix[2] << ", " << m.mMatrix[3] << "]"; return s; -} +} void matMulBoundBox(const LLMatrix4a &a, const LLVector4a *in_extents, LLVector4a *out_extents); diff --git a/indra/llmath/llmodularmath.cpp b/indra/llmath/llmodularmath.cpp index cdc20028bf..7a22866b5e 100644 --- a/indra/llmath/llmodularmath.cpp +++ b/indra/llmath/llmodularmath.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llmodularmath.cpp * @brief LLModularMath class implementation * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ diff --git a/indra/llmath/llmodularmath.h b/indra/llmath/llmodularmath.h index 0d4d28fadc..e0ae71417a 100644 --- a/indra/llmath/llmodularmath.h +++ b/indra/llmath/llmodularmath.h @@ -1,25 +1,25 @@ -/** +/** * @file llmodularmath.h * @brief Useful modular math functions. * * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -32,21 +32,21 @@ namespace LLModularMath // Return difference between lhs and rhs // treating the U32 operands and result // as unsigned values of given width. - template<int width> - inline U32 subtract(U32 lhs, U32 rhs) - { - // Generate a bit mask which will truncate - // unsigned values to given width at compile time. - const U32 mask = (1 << width) - 1; - - // Operands are unsigned, so modular - // arithmetic applies. If lhs < rhs, - // difference will wrap in to lower - // bits of result, which is then masked - // to give a value that can be represented - // by an unsigned value of width bits. - return mask & (lhs - rhs); - } + template<int width> + inline U32 subtract(U32 lhs, U32 rhs) + { + // Generate a bit mask which will truncate + // unsigned values to given width at compile time. + const U32 mask = (1 << width) - 1; + + // Operands are unsigned, so modular + // arithmetic applies. If lhs < rhs, + // difference will wrap in to lower + // bits of result, which is then masked + // to give a value that can be represented + // by an unsigned value of width bits. + return mask & (lhs - rhs); + } } #endif diff --git a/indra/llmath/lloctree.cpp b/indra/llmath/lloctree.cpp index 3fcb3a27d7..1d87ca797f 100644 --- a/indra/llmath/lloctree.cpp +++ b/indra/llmath/lloctree.cpp @@ -1,24 +1,24 @@ -/** +/** * @file lloctree.cpp * * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index 2e9625fff7..475ce20ae6 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -1,25 +1,25 @@ -/** +/** * @file lloctree.h - * @brief Octree declaration. + * @brief Octree declaration. * * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -61,11 +61,11 @@ template <class T, typename T_PTR> class LLOctreeListener: public LLTreeListener<T> { public: - typedef LLTreeListener<T> BaseType; + typedef LLTreeListener<T> BaseType; typedef LLOctreeNode<T, T_PTR> oct_node; - virtual void handleChildAddition(const oct_node* parent, oct_node* child) = 0; - virtual void handleChildRemoval(const oct_node* parent, const oct_node* child) = 0; + virtual void handleChildAddition(const oct_node* parent, oct_node* child) = 0; + virtual void handleChildRemoval(const oct_node* parent, const oct_node* child) = 0; }; template <class T, typename T_PTR> @@ -80,7 +80,7 @@ template <class T, typename T_PTR> class LLOctreeTravelerDepthFirst : public LLOctreeTraveler<T, T_PTR> { public: - virtual void traverse(const LLOctreeNode<T, T_PTR>* node) override; + virtual void traverse(const LLOctreeNode<T, T_PTR>* node) override; }; template <class T, typename T_PTR> @@ -94,7 +94,7 @@ public: typedef std::vector<T_PTR> element_list; typedef typename element_list::iterator element_iter; typedef typename element_list::const_iterator const_element_iter; - typedef typename std::vector<LLTreeListener<T>*>::iterator tree_listener_iter; + typedef typename std::vector<LLTreeListener<T>*>::iterator tree_listener_iter; typedef LLOctreeNode<T, T_PTR>** child_list; typedef LLOctreeNode<T, T_PTR>** child_iter; @@ -107,568 +107,568 @@ public: NO_CHILD_NODES = 255 // Note: This is an U8 to match the max value in mChildMap[] }; - LLOctreeNode( const LLVector4a& center, - const LLVector4a& size, - BaseType* parent, - U8 octant = NO_CHILD_NODES) - : mParent((oct_node*)parent), - mOctant(octant) - { - llassert(size[0] >= gOctreeMinSize*0.5f); - - mCenter = center; - mSize = size; - - updateMinMax(); - if ((mOctant == NO_CHILD_NODES) && mParent) - { - mOctant = ((oct_node*) mParent)->getOctant(mCenter); - } - - clearChildren(); - } - - virtual ~LLOctreeNode() - { - BaseType::destroyListeners(); - + LLOctreeNode( const LLVector4a& center, + const LLVector4a& size, + BaseType* parent, + U8 octant = NO_CHILD_NODES) + : mParent((oct_node*)parent), + mOctant(octant) + { + llassert(size[0] >= gOctreeMinSize*0.5f); + + mCenter = center; + mSize = size; + + updateMinMax(); + if ((mOctant == NO_CHILD_NODES) && mParent) + { + mOctant = ((oct_node*) mParent)->getOctant(mCenter); + } + + clearChildren(); + } + + virtual ~LLOctreeNode() + { + BaseType::destroyListeners(); + const U32 element_count = getElementCount(); for (U32 i = 0; i < element_count; ++i) - { - mData[i]->setBinIndex(-1); - mData[i] = NULL; - } - - mData.clear(); - - for (U32 i = 0; i < getChildCount(); i++) - { - delete getChild(i); - } - } - - inline const BaseType* getParent() const { return mParent; } - inline void setParent(BaseType* parent) { mParent = (oct_node*) parent; } - inline const LLVector4a& getCenter() const { return mCenter; } - inline const LLVector4a& getSize() const { return mSize; } - inline void setCenter(const LLVector4a& center) { mCenter = center; } - inline void setSize(const LLVector4a& size) { mSize = size; } - inline oct_node* getNodeAt(T* data) { return getNodeAt(data->getPositionGroup(), data->getBinRadius()); } - inline U8 getOctant() const { return mOctant; } - inline const oct_node* getOctParent() const { return (const oct_node*) getParent(); } - inline oct_node* getOctParent() { return (oct_node*) getParent(); } - - U8 getOctant(const LLVector4a& pos) const //get the octant pos is in - { - return (U8) (pos.greaterThan(mCenter).getGatheredBits() & 0x7); - } - - inline bool isInside(const LLVector4a& pos, const F32& rad) const - { - return rad <= mSize[0]*2.f && isInside(pos); - } - - inline bool isInside(T* data) const - { - return isInside(data->getPositionGroup(), data->getBinRadius()); - } - - bool isInside(const LLVector4a& pos) const - { - S32 gt = pos.greaterThan(mMax).getGatheredBits() & 0x7; - if (gt) - { - return false; - } - - S32 lt = pos.lessEqual(mMin).getGatheredBits() & 0x7; - if (lt) - { - return false; - } - - return true; - } - - void updateMinMax() - { - mMax.setAdd(mCenter, mSize); - mMin.setSub(mCenter, mSize); - } - - inline oct_listener* getOctListener(U32 index) - { - return (oct_listener*) BaseType::getListener(index); - } - - inline bool contains(T* xform) - { - return contains(xform->getBinRadius()); - } - - bool contains(F32 radius) - { - if (mParent == NULL) - { //root node contains nothing - return false; - } - - F32 size = mSize[0]; - F32 p_size = size * 2.f; - - return (radius <= gOctreeMinSize && size <= gOctreeMinSize) || - (radius <= p_size && radius > size); - } - - static void pushCenter(LLVector4a ¢er, const LLVector4a &size, const T* data) - { - const LLVector4a& pos = data->getPositionGroup(); - - LLVector4Logical gt = pos.greaterThan(center); - - LLVector4a up; - up = _mm_and_ps(size, gt); - - LLVector4a down; - down = _mm_andnot_ps(gt, size); - - center.add(up); - center.sub(down); - } - - void accept(oct_traveler* visitor) { visitor->visit(this); } - virtual bool isLeaf() const { return mChildCount == 0; } - + { + mData[i]->setBinIndex(-1); + mData[i] = NULL; + } + + mData.clear(); + + for (U32 i = 0; i < getChildCount(); i++) + { + delete getChild(i); + } + } + + inline const BaseType* getParent() const { return mParent; } + inline void setParent(BaseType* parent) { mParent = (oct_node*) parent; } + inline const LLVector4a& getCenter() const { return mCenter; } + inline const LLVector4a& getSize() const { return mSize; } + inline void setCenter(const LLVector4a& center) { mCenter = center; } + inline void setSize(const LLVector4a& size) { mSize = size; } + inline oct_node* getNodeAt(T* data) { return getNodeAt(data->getPositionGroup(), data->getBinRadius()); } + inline U8 getOctant() const { return mOctant; } + inline const oct_node* getOctParent() const { return (const oct_node*) getParent(); } + inline oct_node* getOctParent() { return (oct_node*) getParent(); } + + U8 getOctant(const LLVector4a& pos) const //get the octant pos is in + { + return (U8) (pos.greaterThan(mCenter).getGatheredBits() & 0x7); + } + + inline bool isInside(const LLVector4a& pos, const F32& rad) const + { + return rad <= mSize[0]*2.f && isInside(pos); + } + + inline bool isInside(T* data) const + { + return isInside(data->getPositionGroup(), data->getBinRadius()); + } + + bool isInside(const LLVector4a& pos) const + { + S32 gt = pos.greaterThan(mMax).getGatheredBits() & 0x7; + if (gt) + { + return false; + } + + S32 lt = pos.lessEqual(mMin).getGatheredBits() & 0x7; + if (lt) + { + return false; + } + + return true; + } + + void updateMinMax() + { + mMax.setAdd(mCenter, mSize); + mMin.setSub(mCenter, mSize); + } + + inline oct_listener* getOctListener(U32 index) + { + return (oct_listener*) BaseType::getListener(index); + } + + inline bool contains(T* xform) + { + return contains(xform->getBinRadius()); + } + + bool contains(F32 radius) + { + if (mParent == NULL) + { //root node contains nothing + return false; + } + + F32 size = mSize[0]; + F32 p_size = size * 2.f; + + return (radius <= gOctreeMinSize && size <= gOctreeMinSize) || + (radius <= p_size && radius > size); + } + + static void pushCenter(LLVector4a ¢er, const LLVector4a &size, const T* data) + { + const LLVector4a& pos = data->getPositionGroup(); + + LLVector4Logical gt = pos.greaterThan(center); + + LLVector4a up; + up = _mm_and_ps(size, gt); + + LLVector4a down; + down = _mm_andnot_ps(gt, size); + + center.add(up); + center.sub(down); + } + + void accept(oct_traveler* visitor) { visitor->visit(this); } + virtual bool isLeaf() const { return mChildCount == 0; } + U32 getElementCount() const { return (U32)mData.size(); } bool isEmpty() const { return mData.empty(); } element_iter getDataBegin() { return mData.begin(); } element_iter getDataEnd() { return mData.end(); } const_element_iter getDataBegin() const { return mData.cbegin(); } const_element_iter getDataEnd() const { return mData.cend(); } - - U32 getChildCount() const { return mChildCount; } - oct_node* getChild(U32 index) { return mChild[index]; } - const oct_node* getChild(U32 index) const { return mChild[index]; } - child_list& getChildren() { return mChild; } - const child_list& getChildren() const { return mChild; } - - void accept(tree_traveler* visitor) const { visitor->visit(this); } - void accept(oct_traveler* visitor) const { visitor->visit(this); } - - void validateChildMap() - { - for (U32 i = 0; i < 8; i++) - { - U8 idx = mChildMap[i]; - if (idx != NO_CHILD_NODES) - { - oct_node* child = mChild[idx]; - if (child->getOctant() != i) - { - LL_ERRS() << "Invalid child map, bad octant data." << LL_ENDL; - } + U32 getChildCount() const { return mChildCount; } + oct_node* getChild(U32 index) { return mChild[index]; } + const oct_node* getChild(U32 index) const { return mChild[index]; } + child_list& getChildren() { return mChild; } + const child_list& getChildren() const { return mChild; } + + void accept(tree_traveler* visitor) const { visitor->visit(this); } + void accept(oct_traveler* visitor) const { visitor->visit(this); } + + void validateChildMap() + { + for (U32 i = 0; i < 8; i++) + { + U8 idx = mChildMap[i]; + if (idx != NO_CHILD_NODES) + { + oct_node* child = mChild[idx]; - if (getOctant(child->getCenter()) != child->getOctant()) - { - LL_ERRS() << "Invalid child octant compared to position data." << LL_ENDL; - } - } - } - } + if (child->getOctant() != i) + { + LL_ERRS() << "Invalid child map, bad octant data." << LL_ENDL; + } + + if (getOctant(child->getCenter()) != child->getOctant()) + { + LL_ERRS() << "Invalid child octant compared to position data." << LL_ENDL; + } + } + } + } - oct_node* getNodeAt(const LLVector4a& pos, const F32& rad) - { + oct_node* getNodeAt(const LLVector4a& pos, const F32& rad) + { oct_node* node = this; - if (node->isInside(pos, rad)) - { - //do a quick search by octant - U8 octant = node->getOctant(pos); - - //traverse the tree until we find a node that has no node - //at the appropriate octant or is smaller than the object. - //by definition, that node is the smallest node that contains - // the data - U8 next_node = node->mChildMap[octant]; - - while (next_node != NO_CHILD_NODES && node->getSize()[0] >= rad) - { - node = node->getChild(next_node); - octant = node->getOctant(pos); - next_node = node->mChildMap[octant]; - } - } - else if (!node->contains(rad) && node->getParent()) - { //if we got here, data does not exist in this node + if (node->isInside(pos, rad)) + { + //do a quick search by octant + U8 octant = node->getOctant(pos); + + //traverse the tree until we find a node that has no node + //at the appropriate octant or is smaller than the object. + //by definition, that node is the smallest node that contains + // the data + U8 next_node = node->mChildMap[octant]; + + while (next_node != NO_CHILD_NODES && node->getSize()[0] >= rad) + { + node = node->getChild(next_node); + octant = node->getOctant(pos); + next_node = node->mChildMap[octant]; + } + } + else if (!node->contains(rad) && node->getParent()) + { //if we got here, data does not exist in this node return ((oct_node*) node->getParent())->getNodeAt(pos, rad); - } + } + + return node; + } - return node; - } - - virtual bool insert(T* data) - { + virtual bool insert(T* data) + { //LL_PROFILE_ZONE_NAMED_COLOR("Octree::insert()",OCTREE_DEBUG_COLOR_INSERT); - if (data == NULL || data->getBinIndex() != -1) - { - OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE BRANCH !!!" << LL_ENDL; - return false; - } + if (data == NULL || data->getBinIndex() != -1) + { + OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE BRANCH !!!" << LL_ENDL; + return false; + } oct_node* parent = getOctParent(); - //is it here? - if (isInside(data->getPositionGroup())) - { - if ((((getElementCount() < gOctreeMaxCapacity || getSize()[0] <= gOctreeMinSize) && contains(data->getBinRadius())) || - (data->getBinRadius() > getSize()[0] && parent && parent->getElementCount() >= gOctreeMaxCapacity))) - { //it belongs here + //is it here? + if (isInside(data->getPositionGroup())) + { + if ((((getElementCount() < gOctreeMaxCapacity || getSize()[0] <= gOctreeMinSize) && contains(data->getBinRadius())) || + (data->getBinRadius() > getSize()[0] && parent && parent->getElementCount() >= gOctreeMaxCapacity))) + { //it belongs here mData.push_back(data); data->setBinIndex(getElementCount() - 1); - BaseType::insert(data); - return true; - } - else - { - //find a child to give it to - oct_node* child = NULL; - for (U32 i = 0; i < getChildCount(); i++) - { - child = getChild(i); - if (child->isInside(data->getPositionGroup())) - { - child->insert(data); - return false; - } - } - - //it's here, but no kids are in the right place, make a new kid - LLVector4a center = getCenter(); - LLVector4a size = getSize(); - size.mul(0.5f); - - //push center in direction of data + BaseType::insert(data); + return true; + } + else + { + //find a child to give it to + oct_node* child = NULL; + for (U32 i = 0; i < getChildCount(); i++) + { + child = getChild(i); + if (child->isInside(data->getPositionGroup())) + { + child->insert(data); + return false; + } + } + + //it's here, but no kids are in the right place, make a new kid + LLVector4a center = getCenter(); + LLVector4a size = getSize(); + size.mul(0.5f); + + //push center in direction of data oct_node::pushCenter(center, size, data); - // handle case where floating point number gets too small - LLVector4a val; - val.setSub(center, getCenter()); - val.setAbs(val); - LLVector4a min_diff(gOctreeMinSize); + // handle case where floating point number gets too small + LLVector4a val; + val.setSub(center, getCenter()); + val.setAbs(val); + LLVector4a min_diff(gOctreeMinSize); - S32 lt = val.lessThan(min_diff).getGatheredBits() & 0x7; + S32 lt = val.lessThan(min_diff).getGatheredBits() & 0x7; - if( lt == 0x7 ) - { + if( lt == 0x7 ) + { mData.push_back(data); data->setBinIndex(getElementCount() - 1); - BaseType::insert(data); - return true; - } + BaseType::insert(data); + return true; + } #if LL_OCTREE_PARANOIA_CHECK - if (getChildCount() == 8) - { - //this really isn't possible, something bad has happened - OCT_ERRS << "Octree detected floating point error and gave up." << LL_ENDL; - return false; - } - - //make sure no existing node matches this position - for (U32 i = 0; i < getChildCount(); i++) - { - if (mChild[i]->getCenter().equals3(center)) - { - OCT_ERRS << "Octree detected duplicate child center and gave up." << LL_ENDL; - return false; - } - } + if (getChildCount() == 8) + { + //this really isn't possible, something bad has happened + OCT_ERRS << "Octree detected floating point error and gave up." << LL_ENDL; + return false; + } + + //make sure no existing node matches this position + for (U32 i = 0; i < getChildCount(); i++) + { + if (mChild[i]->getCenter().equals3(center)) + { + OCT_ERRS << "Octree detected duplicate child center and gave up." << LL_ENDL; + return false; + } + } #endif - llassert(size[0] >= gOctreeMinSize*0.5f); - //make the new kid + llassert(size[0] >= gOctreeMinSize*0.5f); + //make the new kid child = new oct_node(center, size, this); - addChild(child); - - child->insert(data); - } - } - else if (parent) - { - //it's not in here, give it to the root - OCT_ERRS << "Octree insertion failed, starting over from root!" << LL_ENDL; - - oct_node* node = this; - - while (parent) - { - node = parent; - parent = node->getOctParent(); - } - - node->insert(data); - } - else - { - // It's not in here, and we are root. - // LLOctreeRoot::insert() should have expanded - // root by now, something is wrong - OCT_ERRS << "Octree insertion failed! Root expansion failed." << LL_ENDL; - } - - return false; - } - - void _remove(T* data, S32 i) + addChild(child); + + child->insert(data); + } + } + else if (parent) + { + //it's not in here, give it to the root + OCT_ERRS << "Octree insertion failed, starting over from root!" << LL_ENDL; + + oct_node* node = this; + + while (parent) + { + node = parent; + parent = node->getOctParent(); + } + + node->insert(data); + } + else + { + // It's not in here, and we are root. + // LLOctreeRoot::insert() should have expanded + // root by now, something is wrong + OCT_ERRS << "Octree insertion failed! Root expansion failed." << LL_ENDL; + } + + return false; + } + + void _remove(T* data, S32 i) { //precondition -- getElementCount() > 0, idx is in range [0, getElementCount()) - data->setBinIndex(-1); - + data->setBinIndex(-1); + const U32 new_element_count = getElementCount() - 1; - if (new_element_count > 0) - { - if (new_element_count != i) - { - mData[i] = mData[new_element_count]; //might unref data, do not access data after this point - mData[i]->setBinIndex(i); - } - - mData[new_element_count] = NULL; - mData.pop_back(); - } - else - { - mData.clear(); - } - - this->notifyRemoval(data); - checkAlive(); - } - - bool remove(T* data) - { + if (new_element_count > 0) + { + if (new_element_count != i) + { + mData[i] = mData[new_element_count]; //might unref data, do not access data after this point + mData[i]->setBinIndex(i); + } + + mData[new_element_count] = NULL; + mData.pop_back(); + } + else + { + mData.clear(); + } + + this->notifyRemoval(data); + checkAlive(); + } + + bool remove(T* data) + { //LL_PROFILE_ZONE_NAMED_COLOR("Octree::remove()", OCTREE_DEBUG_COLOR_REMOVE); - S32 i = data->getBinIndex(); + S32 i = data->getBinIndex(); if (i >= 0 && i < getElementCount()) - { - if (mData[i] == data) - { //found it - _remove(data, i); - llassert(data->getBinIndex() == -1); - return true; - } - } - - if (isInside(data)) - { - oct_node* dest = getNodeAt(data); - - if (dest != this) - { - bool ret = dest->remove(data); - llassert(data->getBinIndex() == -1); - return ret; - } - } - - //SHE'S GONE MISSING... - //none of the children have it, let's just brute force this bastard out - //starting with the root node (UGLY CODE COMETH!) - oct_node* parent = getOctParent(); - oct_node* node = this; - - while (parent != NULL) - { - node = parent; - parent = node->getOctParent(); - } - - //node is now root - LL_WARNS() << "!!! OCTREE REMOVING ELEMENT BY ADDRESS, SEVERE PERFORMANCE PENALTY |||" << LL_ENDL; - node->removeByAddress(data); - llassert(data->getBinIndex() == -1); - return true; - } - - void removeByAddress(T* data) - { + { + if (mData[i] == data) + { //found it + _remove(data, i); + llassert(data->getBinIndex() == -1); + return true; + } + } + + if (isInside(data)) + { + oct_node* dest = getNodeAt(data); + + if (dest != this) + { + bool ret = dest->remove(data); + llassert(data->getBinIndex() == -1); + return ret; + } + } + + //SHE'S GONE MISSING... + //none of the children have it, let's just brute force this bastard out + //starting with the root node (UGLY CODE COMETH!) + oct_node* parent = getOctParent(); + oct_node* node = this; + + while (parent != NULL) + { + node = parent; + parent = node->getOctParent(); + } + + //node is now root + LL_WARNS() << "!!! OCTREE REMOVING ELEMENT BY ADDRESS, SEVERE PERFORMANCE PENALTY |||" << LL_ENDL; + node->removeByAddress(data); + llassert(data->getBinIndex() == -1); + return true; + } + + void removeByAddress(T* data) + { const U32 element_count = getElementCount(); for (U32 i = 0; i < element_count; ++i) - { - if (mData[i] == data) - { //we have data - _remove(data, i); - LL_WARNS() << "FOUND!" << LL_ENDL; - return; - } - } - - for (U32 i = 0; i < getChildCount(); i++) - { //we don't contain data, so pass this guy down + { + if (mData[i] == data) + { //we have data + _remove(data, i); + LL_WARNS() << "FOUND!" << LL_ENDL; + return; + } + } + + for (U32 i = 0; i < getChildCount(); i++) + { //we don't contain data, so pass this guy down oct_node* child = (oct_node*) getChild(i); - child->removeByAddress(data); - } - } - - void clearChildren() - { - mChildCount = 0; - memset(mChildMap, NO_CHILD_NODES, sizeof(mChildMap)); - } - - void validate() - { + child->removeByAddress(data); + } + } + + void clearChildren() + { + mChildCount = 0; + memset(mChildMap, NO_CHILD_NODES, sizeof(mChildMap)); + } + + void validate() + { #if LL_OCTREE_PARANOIA_CHECK - for (U32 i = 0; i < getChildCount(); i++) - { - mChild[i]->validate(); - if (mChild[i]->getParent() != this) - { - LL_ERRS() << "Octree child has invalid parent." << LL_ENDL; - } - } + for (U32 i = 0; i < getChildCount(); i++) + { + mChild[i]->validate(); + if (mChild[i]->getParent() != this) + { + LL_ERRS() << "Octree child has invalid parent." << LL_ENDL; + } + } #endif - } - - virtual bool balance() - { - return false; - } - - void destroy() - { - for (U32 i = 0; i < getChildCount(); i++) - { - mChild[i]->destroy(); - delete mChild[i]; - } - } - - void addChild(oct_node* child, bool silent = false) - { + } + + virtual bool balance() + { + return false; + } + + void destroy() + { + for (U32 i = 0; i < getChildCount(); i++) + { + mChild[i]->destroy(); + delete mChild[i]; + } + } + + void addChild(oct_node* child, bool silent = false) + { #if LL_OCTREE_PARANOIA_CHECK - if (child->getSize().equals3(getSize())) - { - OCT_ERRS << "Child size is same as parent size!" << LL_ENDL; - } - - for (U32 i = 0; i < getChildCount(); i++) - { - if(!mChild[i]->getSize().equals3(child->getSize())) - { - OCT_ERRS <<"Invalid octree child size." << LL_ENDL; - } - if (mChild[i]->getCenter().equals3(child->getCenter())) - { - OCT_ERRS <<"Duplicate octree child position." << LL_ENDL; - } - } - - if (mChild.size() >= 8) - { - OCT_ERRS <<"Octree node has too many children... why?" << LL_ENDL; - } + if (child->getSize().equals3(getSize())) + { + OCT_ERRS << "Child size is same as parent size!" << LL_ENDL; + } + + for (U32 i = 0; i < getChildCount(); i++) + { + if(!mChild[i]->getSize().equals3(child->getSize())) + { + OCT_ERRS <<"Invalid octree child size." << LL_ENDL; + } + if (mChild[i]->getCenter().equals3(child->getCenter())) + { + OCT_ERRS <<"Duplicate octree child position." << LL_ENDL; + } + } + + if (mChild.size() >= 8) + { + OCT_ERRS <<"Octree node has too many children... why?" << LL_ENDL; + } #endif - mChildMap[child->getOctant()] = mChildCount; - - mChild[mChildCount] = child; - ++mChildCount; - child->setParent(this); - - if (!silent) - { - for (U32 i = 0; i < this->getListenerCount(); i++) - { - oct_listener* listener = getOctListener(i); - listener->handleChildAddition(this, child); - } - } - } - - void removeChild(S32 index, bool destroy = false) - { - for (U32 i = 0; i < this->getListenerCount(); i++) - { - oct_listener* listener = getOctListener(i); - listener->handleChildRemoval(this, getChild(index)); - } - - if (destroy) - { - mChild[index]->destroy(); - delete mChild[index]; - } - - --mChildCount; - - mChild[index] = mChild[mChildCount]; - - //rebuild child map - memset(mChildMap, NO_CHILD_NODES, sizeof(mChildMap)); - - for (U32 i = 0; i < mChildCount; ++i) - { - mChildMap[mChild[i]->getOctant()] = i; - } - - checkAlive(); - } - - void checkAlive() - { - if (getChildCount() == 0 && getElementCount() == 0) - { - oct_node* parent = getOctParent(); - if (parent) - { - parent->deleteChild(this); - } - } - } - - void deleteChild(oct_node* node) - { - for (U32 i = 0; i < getChildCount(); i++) - { - if (getChild(i) == node) - { - removeChild(i, true); - return; - } - } - - OCT_ERRS << "Octree failed to delete requested child." << LL_ENDL; - } + mChildMap[child->getOctant()] = mChildCount; + + mChild[mChildCount] = child; + ++mChildCount; + child->setParent(this); + + if (!silent) + { + for (U32 i = 0; i < this->getListenerCount(); i++) + { + oct_listener* listener = getOctListener(i); + listener->handleChildAddition(this, child); + } + } + } + + void removeChild(S32 index, bool destroy = false) + { + for (U32 i = 0; i < this->getListenerCount(); i++) + { + oct_listener* listener = getOctListener(i); + listener->handleChildRemoval(this, getChild(index)); + } + + if (destroy) + { + mChild[index]->destroy(); + delete mChild[index]; + } + + --mChildCount; + + mChild[index] = mChild[mChildCount]; + + //rebuild child map + memset(mChildMap, NO_CHILD_NODES, sizeof(mChildMap)); + + for (U32 i = 0; i < mChildCount; ++i) + { + mChildMap[mChild[i]->getOctant()] = i; + } + + checkAlive(); + } + + void checkAlive() + { + if (getChildCount() == 0 && getElementCount() == 0) + { + oct_node* parent = getOctParent(); + if (parent) + { + parent->deleteChild(this); + } + } + } + + void deleteChild(oct_node* node) + { + for (U32 i = 0; i < getChildCount(); i++) + { + if (getChild(i) == node) + { + removeChild(i, true); + return; + } + } + + OCT_ERRS << "Octree failed to delete requested child." << LL_ENDL; + } protected: - typedef enum - { - CENTER = 0, - SIZE = 1, - MAX = 2, - MIN = 3 - } eDName; - - LLVector4a mCenter; - LLVector4a mSize; - LLVector4a mMax; - LLVector4a mMin; - - oct_node* mParent; - U8 mOctant; + typedef enum + { + CENTER = 0, + SIZE = 1, + MAX = 2, + MIN = 3 + } eDName; + + LLVector4a mCenter; + LLVector4a mSize; + LLVector4a mMax; + LLVector4a mMin; + + oct_node* mParent; + U8 mOctant; oct_node* mChild[8]; - U8 mChildMap[8]; - U32 mChildCount; + U8 mChildMap[8]; + U32 mChildCount; - element_list mData; -}; + element_list mData; +}; //just like a regular node, except it might expand on insert and compress on balance template <class T, typename T_PTR> @@ -678,152 +678,152 @@ public: typedef LLOctreeNode<T, T_PTR> BaseType; typedef LLOctreeNode<T, T_PTR> oct_node; - LLOctreeRoot(const LLVector4a& center, - const LLVector4a& size, - BaseType* parent) - : BaseType(center, size, parent) - { - } - - bool balance() override - { + LLOctreeRoot(const LLVector4a& center, + const LLVector4a& size, + BaseType* parent) + : BaseType(center, size, parent) + { + } + + bool balance() override + { //LL_PROFILE_ZONE_NAMED_COLOR("Octree::balance()",OCTREE_DEBUG_COLOR_BALANCE); - if (this->getChildCount() == 1 && - !(this->mChild[0]->isLeaf()) && - this->mChild[0]->getElementCount() == 0) - { //if we have only one child and that child is an empty branch, make that child the root - oct_node* child = this->mChild[0]; - - //make the root node look like the child - this->setCenter(this->mChild[0]->getCenter()); - this->setSize(this->mChild[0]->getSize()); - this->updateMinMax(); - - //reset root node child list - this->clearChildren(); - - //copy the child's children into the root node silently - //(don't notify listeners of addition) - for (U32 i = 0; i < child->getChildCount(); i++) - { - this->addChild(child->getChild(i), true); - } - - //destroy child - child->clearChildren(); - delete child; - - return false; - } - - return true; - } - - // LLOctreeRoot::insert - bool insert(T* data) override - { - if (data == nullptr) - { - OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE ROOT !!!" << LL_ENDL; - return false; - } - - if (data->getBinRadius() > 4096.0) - { - OCT_ERRS << "!!! ELEMENT EXCEEDS MAXIMUM SIZE IN OCTREE ROOT !!!" << LL_ENDL; - return false; - } - - LLVector4a MAX_MAG; - MAX_MAG.splat(1024.f*1024.f); - - const LLVector4a& v = data->getPositionGroup(); - - LLVector4a val; - val.setSub(v, BaseType::mCenter); - val.setAbs(val); - S32 lt = val.lessThan(MAX_MAG).getGatheredBits() & 0x7; - - if (lt != 0x7) - { - //OCT_ERRS << "!!! ELEMENT EXCEEDS RANGE OF SPATIAL PARTITION !!!" << LL_ENDL; - return false; - } - - if (this->getSize()[0] > data->getBinRadius() && this->isInside(data->getPositionGroup())) - { - //we got it, just act like a branch - oct_node* node = this->getNodeAt(data); - if (node == this) - { + if (this->getChildCount() == 1 && + !(this->mChild[0]->isLeaf()) && + this->mChild[0]->getElementCount() == 0) + { //if we have only one child and that child is an empty branch, make that child the root + oct_node* child = this->mChild[0]; + + //make the root node look like the child + this->setCenter(this->mChild[0]->getCenter()); + this->setSize(this->mChild[0]->getSize()); + this->updateMinMax(); + + //reset root node child list + this->clearChildren(); + + //copy the child's children into the root node silently + //(don't notify listeners of addition) + for (U32 i = 0; i < child->getChildCount(); i++) + { + this->addChild(child->getChild(i), true); + } + + //destroy child + child->clearChildren(); + delete child; + + return false; + } + + return true; + } + + // LLOctreeRoot::insert + bool insert(T* data) override + { + if (data == nullptr) + { + OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE ROOT !!!" << LL_ENDL; + return false; + } + + if (data->getBinRadius() > 4096.0) + { + OCT_ERRS << "!!! ELEMENT EXCEEDS MAXIMUM SIZE IN OCTREE ROOT !!!" << LL_ENDL; + return false; + } + + LLVector4a MAX_MAG; + MAX_MAG.splat(1024.f*1024.f); + + const LLVector4a& v = data->getPositionGroup(); + + LLVector4a val; + val.setSub(v, BaseType::mCenter); + val.setAbs(val); + S32 lt = val.lessThan(MAX_MAG).getGatheredBits() & 0x7; + + if (lt != 0x7) + { + //OCT_ERRS << "!!! ELEMENT EXCEEDS RANGE OF SPATIAL PARTITION !!!" << LL_ENDL; + return false; + } + + if (this->getSize()[0] > data->getBinRadius() && this->isInside(data->getPositionGroup())) + { + //we got it, just act like a branch + oct_node* node = this->getNodeAt(data); + if (node == this) + { oct_node::insert(data); - } - else if (node->isInside(data->getPositionGroup())) - { - node->insert(data); - } - else - { - // calling node->insert(data) will return us to root - OCT_ERRS << "Failed to insert data at child node" << LL_ENDL; - } - } - else if (this->getChildCount() == 0) - { - //first object being added, just wrap it up - while (!(this->getSize()[0] > data->getBinRadius() && this->isInside(data->getPositionGroup()))) - { - LLVector4a center, size; - center = this->getCenter(); - size = this->getSize(); + } + else if (node->isInside(data->getPositionGroup())) + { + node->insert(data); + } + else + { + // calling node->insert(data) will return us to root + OCT_ERRS << "Failed to insert data at child node" << LL_ENDL; + } + } + else if (this->getChildCount() == 0) + { + //first object being added, just wrap it up + while (!(this->getSize()[0] > data->getBinRadius() && this->isInside(data->getPositionGroup()))) + { + LLVector4a center, size; + center = this->getCenter(); + size = this->getSize(); oct_node::pushCenter(center, size, data); - this->setCenter(center); - size.mul(2.f); - this->setSize(size); - this->updateMinMax(); - } + this->setCenter(center); + size.mul(2.f); + this->setSize(size); + this->updateMinMax(); + } oct_node::insert(data); - } - else - { - while (!(this->getSize()[0] > data->getBinRadius() && this->isInside(data->getPositionGroup()))) - { - //the data is outside the root node, we need to grow - LLVector4a center(this->getCenter()); - LLVector4a size(this->getSize()); - - //expand this node - LLVector4a newcenter(center); + } + else + { + while (!(this->getSize()[0] > data->getBinRadius() && this->isInside(data->getPositionGroup()))) + { + //the data is outside the root node, we need to grow + LLVector4a center(this->getCenter()); + LLVector4a size(this->getSize()); + + //expand this node + LLVector4a newcenter(center); oct_node::pushCenter(newcenter, size, data); - this->setCenter(newcenter); - LLVector4a size2 = size; - size2.mul(2.f); - this->setSize(size2); - this->updateMinMax(); + this->setCenter(newcenter); + LLVector4a size2 = size; + size2.mul(2.f); + this->setSize(size2); + this->updateMinMax(); - llassert(size[0] >= gOctreeMinSize); + llassert(size[0] >= gOctreeMinSize); - //copy our children to a new branch + //copy our children to a new branch oct_node* newnode = new oct_node(center, size, this); - - for (U32 i = 0; i < this->getChildCount(); i++) - { + + for (U32 i = 0; i < this->getChildCount(); i++) + { oct_node* child = this->getChild(i); - newnode->addChild(child); - } + newnode->addChild(child); + } - //clear our children and add the root copy - this->clearChildren(); - this->addChild(newnode); - } + //clear our children and add the root copy + this->clearChildren(); + this->addChild(newnode); + } - //insert the data - insert(data); - } + //insert the data + insert(data); + } - return false; - } + return false; + } bool isLeaf() const override { @@ -833,26 +833,26 @@ public: }; //======================== -// LLOctreeTraveler +// LLOctreeTraveler //======================== template <class T, typename T_PTR> void LLOctreeTraveler<T, T_PTR>::traverse(const LLOctreeNode<T, T_PTR>* node) { - node->accept(this); - for (U32 i = 0; i < node->getChildCount(); i++) - { - traverse(node->getChild(i)); - } + node->accept(this); + for (U32 i = 0; i < node->getChildCount(); i++) + { + traverse(node->getChild(i)); + } } template <class T, typename T_PTR> void LLOctreeTravelerDepthFirst<T, T_PTR>::traverse(const LLOctreeNode<T, T_PTR>* node) { - for (U32 i = 0; i < node->getChildCount(); i++) - { - traverse(node->getChild(i)); - } - node->accept(this); + for (U32 i = 0; i < node->getChildCount(); i++) + { + traverse(node->getChild(i)); + } + node->accept(this); } #endif diff --git a/indra/llmath/llperlin.cpp b/indra/llmath/llperlin.cpp index e1da2bf92b..1fcad07f49 100644 --- a/indra/llmath/llperlin.cpp +++ b/indra/llmath/llperlin.cpp @@ -1,24 +1,24 @@ -/** +/** * @file llperlin.cpp * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -44,69 +44,69 @@ bool LLPerlinNoise::sInitialized = 0; static void normalize2(F32 v[2]) { - F32 s = 1.f/(F32)sqrt(v[0] * v[0] + v[1] * v[1]); - v[0] = v[0] * s; - v[1] = v[1] * s; + F32 s = 1.f/(F32)sqrt(v[0] * v[0] + v[1] * v[1]); + v[0] = v[0] * s; + v[1] = v[1] * s; } static void normalize3(F32 v[3]) { - F32 s = 1.f/(F32)sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); - v[0] = v[0] * s; - v[1] = v[1] * s; - v[2] = v[2] * s; + F32 s = 1.f/(F32)sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); + v[0] = v[0] * s; + v[1] = v[1] * s; + v[2] = v[2] * s; } static void fast_setup(F32 vec, U8 &b0, U8 &b1, F32 &r0, F32 &r1) { - S32 t_S32; - - r1 = vec + NF32; - t_S32 = lltrunc(r1); - b0 = (U8)t_S32; - b1 = b0 + 1; - r0 = r1 - t_S32; - r1 = r0 - 1.f; + S32 t_S32; + + r1 = vec + NF32; + t_S32 = lltrunc(r1); + b0 = (U8)t_S32; + b1 = b0 + 1; + r0 = r1 - t_S32; + r1 = r0 - 1.f; } void LLPerlinNoise::init(void) { - int i, j, k; - - for (i = 0 ; i < B ; i++) - { - p[i] = i; - - g1[i] = (F32)((rand() % (B + B)) - B) / B; - - for (j = 0 ; j < 2 ; j++) - g2[i][j] = (F32)((rand() % (B + B)) - B) / B; - normalize2(g2[i]); - - for (j = 0 ; j < 3 ; j++) - g3[i][j] = (F32)((rand() % (B + B)) - B) / B; - normalize3(g3[i]); - } - - while (--i) - { - k = p[i]; - p[i] = p[j = rand() % B]; - p[j] = k; - } - - for (i = 0 ; i < B + 2 ; i++) - { - p[B + i] = p[i]; - g1[B + i] = g1[i]; - for (j = 0 ; j < 2 ; j++) - g2[B + i][j] = g2[i][j]; - for (j = 0 ; j < 3 ; j++) - g3[B + i][j] = g3[i][j]; - } - - sInitialized = true; + int i, j, k; + + for (i = 0 ; i < B ; i++) + { + p[i] = i; + + g1[i] = (F32)((rand() % (B + B)) - B) / B; + + for (j = 0 ; j < 2 ; j++) + g2[i][j] = (F32)((rand() % (B + B)) - B) / B; + normalize2(g2[i]); + + for (j = 0 ; j < 3 ; j++) + g3[i][j] = (F32)((rand() % (B + B)) - B) / B; + normalize3(g3[i]); + } + + while (--i) + { + k = p[i]; + p[i] = p[j = rand() % B]; + p[j] = k; + } + + for (i = 0 ; i < B + 2 ; i++) + { + p[B + i] = p[i]; + g1[B + i] = g1[i]; + for (j = 0 ; j < 2 ; j++) + g2[B + i][j] = g2[i][j]; + for (j = 0 ; j < 3 ; j++) + g3[B + i][j] = g3[i][j]; + } + + sInitialized = true; } @@ -119,176 +119,176 @@ void LLPerlinNoise::init(void) F32 LLPerlinNoise::noise1(F32 x) { - int bx0, bx1; - F32 rx0, rx1, sx, t, u, v; + int bx0, bx1; + F32 rx0, rx1, sx, t, u, v; - if (!sInitialized) - init(); + if (!sInitialized) + init(); - t = x + N; - bx0 = (lltrunc(t)) & BM; - bx1 = (bx0+1) & BM; - rx0 = t - lltrunc(t); - rx1 = rx0 - 1.f; + t = x + N; + bx0 = (lltrunc(t)) & BM; + bx1 = (bx0+1) & BM; + rx0 = t - lltrunc(t); + rx1 = rx0 - 1.f; - sx = s_curve(rx0); + sx = s_curve(rx0); - u = rx0 * g1[ p[ bx0 ] ]; - v = rx1 * g1[ p[ bx1 ] ]; + u = rx0 * g1[ p[ bx0 ] ]; + v = rx1 * g1[ p[ bx1 ] ]; - return lerp_m(sx, u, v); + return lerp_m(sx, u, v); } static F32 fast_at2(F32 rx, F32 ry, F32 *q) { - return rx * q[0] + ry * q[1]; + return rx * q[0] + ry * q[1]; } F32 LLPerlinNoise::noise2(F32 x, F32 y) { - U8 bx0, bx1, by0, by1; - U32 b00, b10, b01, b11; - F32 rx0, rx1, ry0, ry1, *q, sx, sy, a, b, u, v; - S32 i, j; + U8 bx0, bx1, by0, by1; + U32 b00, b10, b01, b11; + F32 rx0, rx1, ry0, ry1, *q, sx, sy, a, b, u, v; + S32 i, j; - if (!sInitialized) - init(); + if (!sInitialized) + init(); - fast_setup(x, bx0, bx1, rx0, rx1); - fast_setup(y, by0, by1, ry0, ry1); + fast_setup(x, bx0, bx1, rx0, rx1); + fast_setup(y, by0, by1, ry0, ry1); - i = *(p + bx0); - j = *(p + bx1); + i = *(p + bx0); + j = *(p + bx1); - b00 = *(p + i + by0); - b10 = *(p + j + by0); - b01 = *(p + i + by1); - b11 = *(p + j + by1); + b00 = *(p + i + by0); + b10 = *(p + j + by0); + b01 = *(p + i + by1); + b11 = *(p + j + by1); - sx = s_curve(rx0); - sy = s_curve(ry0); + sx = s_curve(rx0); + sy = s_curve(ry0); - q = *(g2 + b00); - u = fast_at2(rx0, ry0, q); - q = *(g2 + b10); - v = fast_at2(rx1, ry0, q); - a = lerp_m(sx, u, v); + q = *(g2 + b00); + u = fast_at2(rx0, ry0, q); + q = *(g2 + b10); + v = fast_at2(rx1, ry0, q); + a = lerp_m(sx, u, v); - q = *(g2 + b01); - u = fast_at2(rx0,ry1,q); - q = *(g2 + b11); - v = fast_at2(rx1,ry1,q); - b = lerp_m(sx, u, v); + q = *(g2 + b01); + u = fast_at2(rx0,ry1,q); + q = *(g2 + b11); + v = fast_at2(rx1,ry1,q); + b = lerp_m(sx, u, v); - return lerp_m(sy, a, b); + return lerp_m(sy, a, b); } static F32 fast_at3(F32 rx, F32 ry, F32 rz, F32 *q) { - return rx * q[0] + ry * q[1] + rz * q[2]; + return rx * q[0] + ry * q[1] + rz * q[2]; } F32 LLPerlinNoise::noise3(F32 x, F32 y, F32 z) { - U8 bx0, bx1, by0, by1, bz0, bz1; - S32 b00, b10, b01, b11; - F32 rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v; - S32 i, j; - - if (!sInitialized) - init(); - - fast_setup(x, bx0,bx1, rx0,rx1); - fast_setup(y, by0,by1, ry0,ry1); - fast_setup(z, bz0,bz1, rz0,rz1); - - i = p[ bx0 ]; - j = p[ bx1 ]; - - b00 = p[ i + by0 ]; - b10 = p[ j + by0 ]; - b01 = p[ i + by1 ]; - b11 = p[ j + by1 ]; - - t = s_curve(rx0); - sy = s_curve(ry0); - sz = s_curve(rz0); - - q = g3[ b00 + bz0 ]; - u = fast_at3(rx0,ry0,rz0,q); - q = g3[ b10 + bz0 ]; - v = fast_at3(rx1,ry0,rz0,q); - a = lerp_m(t, u, v); - - q = g3[ b01 + bz0 ]; - u = fast_at3(rx0,ry1,rz0,q); - q = g3[ b11 + bz0 ]; - v = fast_at3(rx1,ry1,rz0,q); - b = lerp_m(t, u, v); - - c = lerp_m(sy, a, b); - - q = g3[ b00 + bz1 ]; - u = fast_at3(rx0,ry0,rz1,q); - q = g3[ b10 + bz1 ]; - v = fast_at3(rx1,ry0,rz1,q); - a = lerp_m(t, u, v); - - q = g3[ b01 + bz1 ]; - u = fast_at3(rx0,ry1,rz1,q); - q = g3[ b11 + bz1 ]; - v = fast_at3(rx1,ry1,rz1,q); - b = lerp_m(t, u, v); - - d = lerp_m(sy, a, b); - - return lerp_m(sz, c, d); + U8 bx0, bx1, by0, by1, bz0, bz1; + S32 b00, b10, b01, b11; + F32 rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v; + S32 i, j; + + if (!sInitialized) + init(); + + fast_setup(x, bx0,bx1, rx0,rx1); + fast_setup(y, by0,by1, ry0,ry1); + fast_setup(z, bz0,bz1, rz0,rz1); + + i = p[ bx0 ]; + j = p[ bx1 ]; + + b00 = p[ i + by0 ]; + b10 = p[ j + by0 ]; + b01 = p[ i + by1 ]; + b11 = p[ j + by1 ]; + + t = s_curve(rx0); + sy = s_curve(ry0); + sz = s_curve(rz0); + + q = g3[ b00 + bz0 ]; + u = fast_at3(rx0,ry0,rz0,q); + q = g3[ b10 + bz0 ]; + v = fast_at3(rx1,ry0,rz0,q); + a = lerp_m(t, u, v); + + q = g3[ b01 + bz0 ]; + u = fast_at3(rx0,ry1,rz0,q); + q = g3[ b11 + bz0 ]; + v = fast_at3(rx1,ry1,rz0,q); + b = lerp_m(t, u, v); + + c = lerp_m(sy, a, b); + + q = g3[ b00 + bz1 ]; + u = fast_at3(rx0,ry0,rz1,q); + q = g3[ b10 + bz1 ]; + v = fast_at3(rx1,ry0,rz1,q); + a = lerp_m(t, u, v); + + q = g3[ b01 + bz1 ]; + u = fast_at3(rx0,ry1,rz1,q); + q = g3[ b11 + bz1 ]; + v = fast_at3(rx1,ry1,rz1,q); + b = lerp_m(t, u, v); + + d = lerp_m(sy, a, b); + + return lerp_m(sz, c, d); } F32 LLPerlinNoise::turbulence2(F32 x, F32 y, F32 freq) { - F32 t, lx, ly; - - for (t = 0.f ; freq >= 1.f ; freq *= 0.5f) - { - lx = freq * x; - ly = freq * y; - t += noise2(lx, ly)/freq; - } - return t; + F32 t, lx, ly; + + for (t = 0.f ; freq >= 1.f ; freq *= 0.5f) + { + lx = freq * x; + ly = freq * y; + t += noise2(lx, ly)/freq; + } + return t; } F32 LLPerlinNoise::turbulence3(F32 x, F32 y, F32 z, F32 freq) { - F32 t, lx, ly, lz; - - for (t = 0.f ; freq >= 1.f ; freq *= 0.5f) - { - lx = freq * x; - ly = freq * y; - lz = freq * z; - t += noise3(lx,ly,lz)/freq; -// t += fabs(noise3(lx,ly,lz)) / freq; // Like snow - bubbly at low frequencies -// t += sqrt(fabs(noise3(lx,ly,lz))) / freq; // Better at low freq -// t += (noise3(lx,ly,lz)*noise3(lx,ly,lz)) / freq; - } - return t; + F32 t, lx, ly, lz; + + for (t = 0.f ; freq >= 1.f ; freq *= 0.5f) + { + lx = freq * x; + ly = freq * y; + lz = freq * z; + t += noise3(lx,ly,lz)/freq; +// t += fabs(noise3(lx,ly,lz)) / freq; // Like snow - bubbly at low frequencies +// t += sqrt(fabs(noise3(lx,ly,lz))) / freq; // Better at low freq +// t += (noise3(lx,ly,lz)*noise3(lx,ly,lz)) / freq; + } + return t; } F32 LLPerlinNoise::clouds3(F32 x, F32 y, F32 z, F32 freq) { - F32 t, lx, ly, lz; - - for (t = 0.f ; freq >= 1.f ; freq *= 0.5f) - { - lx = freq * x; - ly = freq * y; - lz = freq * z; -// t += noise3(lx,ly,lz)/freq; -// t += fabs(noise3(lx,ly,lz)) / freq; // Like snow - bubbly at low frequencies -// t += sqrt(fabs(noise3(lx,ly,lz))) / freq; // Better at low freq - t += (noise3(lx,ly,lz)*noise3(lx,ly,lz)) / freq; - } - return t; + F32 t, lx, ly, lz; + + for (t = 0.f ; freq >= 1.f ; freq *= 0.5f) + { + lx = freq * x; + ly = freq * y; + lz = freq * z; +// t += noise3(lx,ly,lz)/freq; +// t += fabs(noise3(lx,ly,lz)) / freq; // Like snow - bubbly at low frequencies +// t += sqrt(fabs(noise3(lx,ly,lz))) / freq; // Better at low freq + t += (noise3(lx,ly,lz)*noise3(lx,ly,lz)) / freq; + } + return t; } diff --git a/indra/llmath/llperlin.h b/indra/llmath/llperlin.h index 40cf19d1ec..2b001ba951 100644 --- a/indra/llmath/llperlin.h +++ b/indra/llmath/llperlin.h @@ -1,24 +1,24 @@ -/** +/** * @file llperlin.h * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -32,15 +32,15 @@ class LLPerlinNoise { public: - static F32 noise1(F32 x); - static F32 noise2(F32 x, F32 y); - static F32 noise3(F32 x, F32 y, F32 z); - static F32 turbulence2(F32 x, F32 y, F32 freq); - static F32 turbulence3(F32 x, F32 y, F32 z, F32 freq); - static F32 clouds3(F32 x, F32 y, F32 z, F32 freq); + static F32 noise1(F32 x); + static F32 noise2(F32 x, F32 y); + static F32 noise3(F32 x, F32 y, F32 z); + static F32 turbulence2(F32 x, F32 y, F32 freq); + static F32 turbulence3(F32 x, F32 y, F32 z, F32 freq); + static F32 clouds3(F32 x, F32 y, F32 z, F32 freq); private: - static bool sInitialized; - static void init(void); + static bool sInitialized; + static void init(void); }; #endif // LL_PERLIN_ diff --git a/indra/llmath/llplane.h b/indra/llmath/llplane.h index 64a3eed0e5..4e8546e32b 100644 --- a/indra/llmath/llplane.h +++ b/indra/llmath/llplane.h @@ -1,24 +1,24 @@ -/** +/** * @file llplane.h * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -31,7 +31,7 @@ // A simple way to specify a plane is to give its normal, // and it's nearest approach to the origin. -// +// // Given the equation for a plane : A*x + B*y + C*z + D = 0 // The plane normal = [A, B, C] // The closest approach = D / sqrt(A*A + B*B + C*C) @@ -41,67 +41,67 @@ LL_ALIGN_PREFIX(16) class LLPlane { public: - - // Constructors - LLPlane() {}; // no default constructor - LLPlane(const LLVector3 &p0, F32 d) { setVec(p0, d); } - LLPlane(const LLVector3 &p0, const LLVector3 &n) { setVec(p0, n); } - inline void setVec(const LLVector3 &p0, F32 d) { mV.set(p0[0], p0[1], p0[2], d); } - - // Set - inline void setVec(const LLVector3 &p0, const LLVector3 &n) - { - F32 d = -(p0 * n); - setVec(n, d); - } - inline void setVec(const LLVector3 &p0, const LLVector3 &p1, const LLVector3 &p2) - { - LLVector3 u, v, w; - u = p1 - p0; - v = p2 - p0; - w = u % v; - w.normVec(); - F32 d = -(w * p0); - setVec(w, d); - } - - inline LLPlane& operator=(const LLVector4& v2) { mV.set(v2[0],v2[1],v2[2],v2[3]); return *this;} - - inline LLPlane& operator=(const LLVector4a& v2) { mV.set(v2[0],v2[1],v2[2],v2[3]); return *this;} - - inline void set(const LLPlane& p2) { mV = p2.mV; } - - // - F32 dist(const LLVector3 &v2) const { return mV[0]*v2[0] + mV[1]*v2[1] + mV[2]*v2[2] + mV[3]; } - - inline LLSimdScalar dot3(const LLVector4a& b) const { return mV.dot3(b); } - - // Read-only access a single float in this vector. Do not use in proximity to any function call that manipulates - // the data at the whole vector level or you will incur a substantial penalty. Consider using the splat functions instead - inline F32 operator[](const S32 idx) const { return mV[idx]; } - - // preferable when index is known at compile time - template <int N> LL_FORCE_INLINE void getAt(LLSimdScalar& v) const { v = mV.getScalarAt<N>(); } - - // reset the vector to 0, 0, 0, 1 - inline void clear() { mV.set(0, 0, 0, 1); } - - inline void getVector3(LLVector3& vec) const { vec.set(mV[0], mV[1], mV[2]); } - - // Retrieve the mask indicating which of the x, y, or z axis are greater or equal to zero. - inline U8 calcPlaneMask() - { - return mV.greaterEqual(LLVector4a::getZero()).getGatheredBits() & LLVector4Logical::MASK_XYZ; - } - - //check if two planes are nearly same - bool equal(const LLPlane& p) const - { - return mV.equals4(p.mV); - } + + // Constructors + LLPlane() {}; // no default constructor + LLPlane(const LLVector3 &p0, F32 d) { setVec(p0, d); } + LLPlane(const LLVector3 &p0, const LLVector3 &n) { setVec(p0, n); } + inline void setVec(const LLVector3 &p0, F32 d) { mV.set(p0[0], p0[1], p0[2], d); } + + // Set + inline void setVec(const LLVector3 &p0, const LLVector3 &n) + { + F32 d = -(p0 * n); + setVec(n, d); + } + inline void setVec(const LLVector3 &p0, const LLVector3 &p1, const LLVector3 &p2) + { + LLVector3 u, v, w; + u = p1 - p0; + v = p2 - p0; + w = u % v; + w.normVec(); + F32 d = -(w * p0); + setVec(w, d); + } + + inline LLPlane& operator=(const LLVector4& v2) { mV.set(v2[0],v2[1],v2[2],v2[3]); return *this;} + + inline LLPlane& operator=(const LLVector4a& v2) { mV.set(v2[0],v2[1],v2[2],v2[3]); return *this;} + + inline void set(const LLPlane& p2) { mV = p2.mV; } + + // + F32 dist(const LLVector3 &v2) const { return mV[0]*v2[0] + mV[1]*v2[1] + mV[2]*v2[2] + mV[3]; } + + inline LLSimdScalar dot3(const LLVector4a& b) const { return mV.dot3(b); } + + // Read-only access a single float in this vector. Do not use in proximity to any function call that manipulates + // the data at the whole vector level or you will incur a substantial penalty. Consider using the splat functions instead + inline F32 operator[](const S32 idx) const { return mV[idx]; } + + // preferable when index is known at compile time + template <int N> LL_FORCE_INLINE void getAt(LLSimdScalar& v) const { v = mV.getScalarAt<N>(); } + + // reset the vector to 0, 0, 0, 1 + inline void clear() { mV.set(0, 0, 0, 1); } + + inline void getVector3(LLVector3& vec) const { vec.set(mV[0], mV[1], mV[2]); } + + // Retrieve the mask indicating which of the x, y, or z axis are greater or equal to zero. + inline U8 calcPlaneMask() + { + return mV.greaterEqual(LLVector4a::getZero()).getGatheredBits() & LLVector4Logical::MASK_XYZ; + } + + //check if two planes are nearly same + bool equal(const LLPlane& p) const + { + return mV.equals4(p.mV); + } private: - LLVector4a mV; + LLVector4a mV; } LL_ALIGN_POSTFIX(16); diff --git a/indra/llmath/llquantize.h b/indra/llmath/llquantize.h index 10c950abbb..e8d880122e 100644 --- a/indra/llmath/llquantize.h +++ b/indra/llmath/llquantize.h @@ -1,4 +1,4 @@ -/** +/** * @file llquantize.h * @brief useful routines for quantizing floats to various length ints * and back out again @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -41,112 +41,112 @@ const F32 OOU8MAX = 1.f/(F32)(U8MAX); LL_ALIGN_16( const F32 F_OOU8MAX_4A[4] ) = { OOU8MAX, OOU8MAX, OOU8MAX, OOU8MAX }; const U8 FIRSTVALIDCHAR = 54; -const U8 MAXSTRINGVAL = U8MAX - FIRSTVALIDCHAR; //we don't allow newline or null +const U8 MAXSTRINGVAL = U8MAX - FIRSTVALIDCHAR; //we don't allow newline or null inline U16 F32_to_U16_ROUND(F32 val, F32 lower, F32 upper) { - val = llclamp(val, lower, upper); - // make sure that the value is positive and normalized to <0, 1> - val -= lower; - val /= (upper - lower); + val = llclamp(val, lower, upper); + // make sure that the value is positive and normalized to <0, 1> + val -= lower; + val /= (upper - lower); - // round the value. Sreturn the U16 - return (U16)(ll_round(val*U16MAX)); + // round the value. Sreturn the U16 + return (U16)(ll_round(val*U16MAX)); } inline U16 F32_to_U16(F32 val, F32 lower, F32 upper) { - val = llclamp(val, lower, upper); - // make sure that the value is positive and normalized to <0, 1> - val -= lower; - val /= (upper - lower); + val = llclamp(val, lower, upper); + // make sure that the value is positive and normalized to <0, 1> + val -= lower; + val /= (upper - lower); - // return the U16 - return (U16)(llfloor(val*U16MAX)); + // return the U16 + return (U16)(llfloor(val*U16MAX)); } inline F32 U16_to_F32(U16 ival, F32 lower, F32 upper) { - F32 val = ival*OOU16MAX; - F32 delta = (upper - lower); - val *= delta; - val += lower; + F32 val = ival*OOU16MAX; + F32 delta = (upper - lower); + val *= delta; + val += lower; - F32 max_error = delta*OOU16MAX; + F32 max_error = delta*OOU16MAX; - // make sure that zero's come through as zero - if (fabsf(val) < max_error) - val = 0.f; + // make sure that zero's come through as zero + if (fabsf(val) < max_error) + val = 0.f; - return val; + return val; } inline U8 F32_to_U8_ROUND(F32 val, F32 lower, F32 upper) { - val = llclamp(val, lower, upper); - // make sure that the value is positive and normalized to <0, 1> - val -= lower; - val /= (upper - lower); + val = llclamp(val, lower, upper); + // make sure that the value is positive and normalized to <0, 1> + val -= lower; + val /= (upper - lower); - // return the rounded U8 - return (U8)(ll_round(val*U8MAX)); + // return the rounded U8 + return (U8)(ll_round(val*U8MAX)); } inline U8 F32_to_U8(F32 val, F32 lower, F32 upper) { - val = llclamp(val, lower, upper); - // make sure that the value is positive and normalized to <0, 1> - val -= lower; - val /= (upper - lower); + val = llclamp(val, lower, upper); + // make sure that the value is positive and normalized to <0, 1> + val -= lower; + val /= (upper - lower); - // return the U8 - return (U8)(llfloor(val*U8MAX)); + // return the U8 + return (U8)(llfloor(val*U8MAX)); } inline F32 U8_to_F32(U8 ival, F32 lower, F32 upper) { - F32 val = ival*OOU8MAX; - F32 delta = (upper - lower); - val *= delta; - val += lower; + F32 val = ival*OOU8MAX; + F32 delta = (upper - lower); + val *= delta; + val += lower; - F32 max_error = delta*OOU8MAX; + F32 max_error = delta*OOU8MAX; - // make sure that zero's come through as zero - if (fabsf(val) < max_error) - val = 0.f; + // make sure that zero's come through as zero + if (fabsf(val) < max_error) + val = 0.f; - return val; + return val; } inline U8 F32_TO_STRING(F32 val, F32 lower, F32 upper) { - val = llclamp(val, lower, upper); //[lower, upper] - // make sure that the value is positive and normalized to <0, 1> - val -= lower; //[0, upper-lower] - val /= (upper - lower); //[0,1] - val = val * MAXSTRINGVAL; //[0, MAXSTRINGVAL] - val = floor(val + 0.5f); //[0, MAXSTRINGVAL] - - U8 stringVal = (U8)(val) + FIRSTVALIDCHAR; //[FIRSTVALIDCHAR, MAXSTRINGVAL + FIRSTVALIDCHAR] - return stringVal; + val = llclamp(val, lower, upper); //[lower, upper] + // make sure that the value is positive and normalized to <0, 1> + val -= lower; //[0, upper-lower] + val /= (upper - lower); //[0,1] + val = val * MAXSTRINGVAL; //[0, MAXSTRINGVAL] + val = floor(val + 0.5f); //[0, MAXSTRINGVAL] + + U8 stringVal = (U8)(val) + FIRSTVALIDCHAR; //[FIRSTVALIDCHAR, MAXSTRINGVAL + FIRSTVALIDCHAR] + return stringVal; } inline F32 STRING_TO_F32(U8 ival, F32 lower, F32 upper) { - // remove empty space left for NULL, newline, etc. - ival -= FIRSTVALIDCHAR; //[0, MAXSTRINGVAL] + // remove empty space left for NULL, newline, etc. + ival -= FIRSTVALIDCHAR; //[0, MAXSTRINGVAL] - F32 val = (F32)ival * (1.f / (F32)MAXSTRINGVAL); //[0, 1] - F32 delta = (upper - lower); - val *= delta; //[0, upper - lower] - val += lower; //[lower, upper] + F32 val = (F32)ival * (1.f / (F32)MAXSTRINGVAL); //[0, 1] + F32 delta = (upper - lower); + val *= delta; //[0, upper - lower] + val += lower; //[lower, upper] - return val; + return val; } #endif diff --git a/indra/llmath/llquaternion.cpp b/indra/llmath/llquaternion.cpp index dd3d552832..aefb82b2f0 100644 --- a/indra/llmath/llquaternion.cpp +++ b/indra/llmath/llquaternion.cpp @@ -5,28 +5,28 @@ * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #include "linden_common.h" -#include "llmath.h" // for F_PI +#include "llmath.h" // for F_PI #include "llquaternion.h" @@ -41,67 +41,67 @@ // WARNING: Don't use this for global const definitions! using this // at the top of a *.cpp file might not give you what you think. const LLQuaternion LLQuaternion::DEFAULT; - + // Constructors LLQuaternion::LLQuaternion(const LLMatrix4 &mat) { - *this = mat.quaternion(); - normalize(); + *this = mat.quaternion(); + normalize(); } LLQuaternion::LLQuaternion(const LLMatrix3 &mat) { - *this = mat.quaternion(); - normalize(); + *this = mat.quaternion(); + normalize(); } LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &vec) { - F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]); - if (mag > FP_MAG_THRESHOLD) - { - angle *= 0.5; - F32 c = cosf(angle); - F32 s = sinf(angle) / mag; - mQ[VX] = vec.mV[VX] * s; - mQ[VY] = vec.mV[VY] * s; - mQ[VZ] = vec.mV[VZ] * s; - mQ[VW] = c; - } - else - { - loadIdentity(); - } + F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]); + if (mag > FP_MAG_THRESHOLD) + { + angle *= 0.5; + F32 c = cosf(angle); + F32 s = sinf(angle) / mag; + mQ[VX] = vec.mV[VX] * s; + mQ[VY] = vec.mV[VY] * s; + mQ[VZ] = vec.mV[VZ] * s; + mQ[VW] = c; + } + else + { + loadIdentity(); + } } LLQuaternion::LLQuaternion(F32 angle, const LLVector3 &vec) { - F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]); - if (mag > FP_MAG_THRESHOLD) - { - angle *= 0.5; - F32 c = cosf(angle); - F32 s = sinf(angle) / mag; - mQ[VX] = vec.mV[VX] * s; - mQ[VY] = vec.mV[VY] * s; - mQ[VZ] = vec.mV[VZ] * s; - mQ[VW] = c; - } - else - { - loadIdentity(); - } + F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]); + if (mag > FP_MAG_THRESHOLD) + { + angle *= 0.5; + F32 c = cosf(angle); + F32 s = sinf(angle) / mag; + mQ[VX] = vec.mV[VX] * s; + mQ[VY] = vec.mV[VY] * s; + mQ[VZ] = vec.mV[VZ] * s; + mQ[VW] = c; + } + else + { + loadIdentity(); + } } LLQuaternion::LLQuaternion(const LLVector3 &x_axis, - const LLVector3 &y_axis, - const LLVector3 &z_axis) + const LLVector3 &y_axis, + const LLVector3 &z_axis) { - LLMatrix3 mat; - mat.setRows(x_axis, y_axis, z_axis); - *this = mat.quaternion(); - normalize(); + LLMatrix3 mat; + mat.setRows(x_axis, y_axis, z_axis); + *this = mat.quaternion(); + normalize(); } LLQuaternion::LLQuaternion(const LLSD &sd) @@ -110,34 +110,34 @@ LLQuaternion::LLQuaternion(const LLSD &sd) } // Quatizations -void LLQuaternion::quantize16(F32 lower, F32 upper) +void LLQuaternion::quantize16(F32 lower, F32 upper) { - F32 x = mQ[VX]; - F32 y = mQ[VY]; - F32 z = mQ[VZ]; - F32 s = mQ[VS]; + F32 x = mQ[VX]; + F32 y = mQ[VY]; + F32 z = mQ[VZ]; + F32 s = mQ[VS]; - x = U16_to_F32(F32_to_U16_ROUND(x, lower, upper), lower, upper); - y = U16_to_F32(F32_to_U16_ROUND(y, lower, upper), lower, upper); - z = U16_to_F32(F32_to_U16_ROUND(z, lower, upper), lower, upper); - s = U16_to_F32(F32_to_U16_ROUND(s, lower, upper), lower, upper); + x = U16_to_F32(F32_to_U16_ROUND(x, lower, upper), lower, upper); + y = U16_to_F32(F32_to_U16_ROUND(y, lower, upper), lower, upper); + z = U16_to_F32(F32_to_U16_ROUND(z, lower, upper), lower, upper); + s = U16_to_F32(F32_to_U16_ROUND(s, lower, upper), lower, upper); - mQ[VX] = x; - mQ[VY] = y; - mQ[VZ] = z; - mQ[VS] = s; + mQ[VX] = x; + mQ[VY] = y; + mQ[VZ] = z; + mQ[VS] = s; - normalize(); + normalize(); } -void LLQuaternion::quantize8(F32 lower, F32 upper) +void LLQuaternion::quantize8(F32 lower, F32 upper) { - mQ[VX] = U8_to_F32(F32_to_U8_ROUND(mQ[VX], lower, upper), lower, upper); - mQ[VY] = U8_to_F32(F32_to_U8_ROUND(mQ[VY], lower, upper), lower, upper); - mQ[VZ] = U8_to_F32(F32_to_U8_ROUND(mQ[VZ], lower, upper), lower, upper); - mQ[VS] = U8_to_F32(F32_to_U8_ROUND(mQ[VS], lower, upper), lower, upper); + mQ[VX] = U8_to_F32(F32_to_U8_ROUND(mQ[VX], lower, upper), lower, upper); + mQ[VY] = U8_to_F32(F32_to_U8_ROUND(mQ[VY], lower, upper), lower, upper); + mQ[VZ] = U8_to_F32(F32_to_U8_ROUND(mQ[VZ], lower, upper), lower, upper); + mQ[VS] = U8_to_F32(F32_to_U8_ROUND(mQ[VS], lower, upper), lower, upper); - normalize(); + normalize(); } // LLVector3 Magnitude and Normalization Functions @@ -145,190 +145,190 @@ void LLQuaternion::quantize8(F32 lower, F32 upper) // Set LLQuaternion routines -const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, F32 x, F32 y, F32 z) -{ - F32 mag = sqrtf(x * x + y * y + z * z); - if (mag > FP_MAG_THRESHOLD) - { - angle *= 0.5; - F32 c = cosf(angle); - F32 s = sinf(angle) / mag; - mQ[VX] = x * s; - mQ[VY] = y * s; - mQ[VZ] = z * s; - mQ[VW] = c; - } - else - { - loadIdentity(); - } - return (*this); -} - -const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, const LLVector3 &vec) -{ - F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]); - if (mag > FP_MAG_THRESHOLD) - { - angle *= 0.5; - F32 c = cosf(angle); - F32 s = sinf(angle) / mag; - mQ[VX] = vec.mV[VX] * s; - mQ[VY] = vec.mV[VY] * s; - mQ[VZ] = vec.mV[VZ] * s; - mQ[VW] = c; - } - else - { - loadIdentity(); - } - return (*this); -} - -const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, const LLVector4 &vec) -{ - F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]); - if (mag > FP_MAG_THRESHOLD) - { - angle *= 0.5; - F32 c = cosf(angle); - F32 s = sinf(angle) / mag; - mQ[VX] = vec.mV[VX] * s; - mQ[VY] = vec.mV[VY] * s; - mQ[VZ] = vec.mV[VZ] * s; - mQ[VW] = c; - } - else - { - loadIdentity(); - } - return (*this); -} - -const LLQuaternion& LLQuaternion::setEulerAngles(F32 roll, F32 pitch, F32 yaw) -{ - LLMatrix3 rot_mat(roll, pitch, yaw); - rot_mat.orthogonalize(); - *this = rot_mat.quaternion(); - - normalize(); - return (*this); +const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, F32 x, F32 y, F32 z) +{ + F32 mag = sqrtf(x * x + y * y + z * z); + if (mag > FP_MAG_THRESHOLD) + { + angle *= 0.5; + F32 c = cosf(angle); + F32 s = sinf(angle) / mag; + mQ[VX] = x * s; + mQ[VY] = y * s; + mQ[VZ] = z * s; + mQ[VW] = c; + } + else + { + loadIdentity(); + } + return (*this); +} + +const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, const LLVector3 &vec) +{ + F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]); + if (mag > FP_MAG_THRESHOLD) + { + angle *= 0.5; + F32 c = cosf(angle); + F32 s = sinf(angle) / mag; + mQ[VX] = vec.mV[VX] * s; + mQ[VY] = vec.mV[VY] * s; + mQ[VZ] = vec.mV[VZ] * s; + mQ[VW] = c; + } + else + { + loadIdentity(); + } + return (*this); +} + +const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, const LLVector4 &vec) +{ + F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]); + if (mag > FP_MAG_THRESHOLD) + { + angle *= 0.5; + F32 c = cosf(angle); + F32 s = sinf(angle) / mag; + mQ[VX] = vec.mV[VX] * s; + mQ[VY] = vec.mV[VY] * s; + mQ[VZ] = vec.mV[VZ] * s; + mQ[VW] = c; + } + else + { + loadIdentity(); + } + return (*this); +} + +const LLQuaternion& LLQuaternion::setEulerAngles(F32 roll, F32 pitch, F32 yaw) +{ + LLMatrix3 rot_mat(roll, pitch, yaw); + rot_mat.orthogonalize(); + *this = rot_mat.quaternion(); + + normalize(); + return (*this); } // deprecated -const LLQuaternion& LLQuaternion::set(const LLMatrix3 &mat) +const LLQuaternion& LLQuaternion::set(const LLMatrix3 &mat) { - *this = mat.quaternion(); - normalize(); - return (*this); + *this = mat.quaternion(); + normalize(); + return (*this); } // deprecated -const LLQuaternion& LLQuaternion::set(const LLMatrix4 &mat) +const LLQuaternion& LLQuaternion::set(const LLMatrix4 &mat) { - *this = mat.quaternion(); - normalize(); - return (*this); + *this = mat.quaternion(); + normalize(); + return (*this); } // deprecated -const LLQuaternion& LLQuaternion::setQuat(F32 angle, F32 x, F32 y, F32 z) -{ - F32 mag = sqrtf(x * x + y * y + z * z); - if (mag > FP_MAG_THRESHOLD) - { - angle *= 0.5; - F32 c = cosf(angle); - F32 s = sinf(angle) / mag; - mQ[VX] = x * s; - mQ[VY] = y * s; - mQ[VZ] = z * s; - mQ[VW] = c; - } - else - { - loadIdentity(); - } - return (*this); +const LLQuaternion& LLQuaternion::setQuat(F32 angle, F32 x, F32 y, F32 z) +{ + F32 mag = sqrtf(x * x + y * y + z * z); + if (mag > FP_MAG_THRESHOLD) + { + angle *= 0.5; + F32 c = cosf(angle); + F32 s = sinf(angle) / mag; + mQ[VX] = x * s; + mQ[VY] = y * s; + mQ[VZ] = z * s; + mQ[VW] = c; + } + else + { + loadIdentity(); + } + return (*this); } // deprecated -const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector3 &vec) -{ - F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]); - if (mag > FP_MAG_THRESHOLD) - { - angle *= 0.5; - F32 c = cosf(angle); - F32 s = sinf(angle) / mag; - mQ[VX] = vec.mV[VX] * s; - mQ[VY] = vec.mV[VY] * s; - mQ[VZ] = vec.mV[VZ] * s; - mQ[VW] = c; - } - else - { - loadIdentity(); - } - return (*this); -} - -const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector4 &vec) -{ - F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]); - if (mag > FP_MAG_THRESHOLD) - { - angle *= 0.5; - F32 c = cosf(angle); - F32 s = sinf(angle) / mag; - mQ[VX] = vec.mV[VX] * s; - mQ[VY] = vec.mV[VY] * s; - mQ[VZ] = vec.mV[VZ] * s; - mQ[VW] = c; - } - else - { - loadIdentity(); - } - return (*this); -} - -const LLQuaternion& LLQuaternion::setQuat(F32 roll, F32 pitch, F32 yaw) -{ - roll *= 0.5f; - pitch *= 0.5f; - yaw *= 0.5f; - F32 sinX = sinf(roll); - F32 cosX = cosf(roll); - F32 sinY = sinf(pitch); - F32 cosY = cosf(pitch); - F32 sinZ = sinf(yaw); - F32 cosZ = cosf(yaw); - mQ[VW] = cosX * cosY * cosZ - sinX * sinY * sinZ; - mQ[VX] = sinX * cosY * cosZ + cosX * sinY * sinZ; - mQ[VY] = cosX * sinY * cosZ - sinX * cosY * sinZ; - mQ[VZ] = cosX * cosY * sinZ + sinX * sinY * cosZ; - return (*this); -} - -const LLQuaternion& LLQuaternion::setQuat(const LLMatrix3 &mat) -{ - *this = mat.quaternion(); - normalize(); - return (*this); -} - -const LLQuaternion& LLQuaternion::setQuat(const LLMatrix4 &mat) -{ - *this = mat.quaternion(); - normalize(); - return (*this); +const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector3 &vec) +{ + F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]); + if (mag > FP_MAG_THRESHOLD) + { + angle *= 0.5; + F32 c = cosf(angle); + F32 s = sinf(angle) / mag; + mQ[VX] = vec.mV[VX] * s; + mQ[VY] = vec.mV[VY] * s; + mQ[VZ] = vec.mV[VZ] * s; + mQ[VW] = c; + } + else + { + loadIdentity(); + } + return (*this); +} + +const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector4 &vec) +{ + F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]); + if (mag > FP_MAG_THRESHOLD) + { + angle *= 0.5; + F32 c = cosf(angle); + F32 s = sinf(angle) / mag; + mQ[VX] = vec.mV[VX] * s; + mQ[VY] = vec.mV[VY] * s; + mQ[VZ] = vec.mV[VZ] * s; + mQ[VW] = c; + } + else + { + loadIdentity(); + } + return (*this); +} + +const LLQuaternion& LLQuaternion::setQuat(F32 roll, F32 pitch, F32 yaw) +{ + roll *= 0.5f; + pitch *= 0.5f; + yaw *= 0.5f; + F32 sinX = sinf(roll); + F32 cosX = cosf(roll); + F32 sinY = sinf(pitch); + F32 cosY = cosf(pitch); + F32 sinZ = sinf(yaw); + F32 cosZ = cosf(yaw); + mQ[VW] = cosX * cosY * cosZ - sinX * sinY * sinZ; + mQ[VX] = sinX * cosY * cosZ + cosX * sinY * sinZ; + mQ[VY] = cosX * sinY * cosZ - sinX * cosY * sinZ; + mQ[VZ] = cosX * cosY * sinZ + sinX * sinY * cosZ; + return (*this); +} + +const LLQuaternion& LLQuaternion::setQuat(const LLMatrix3 &mat) +{ + *this = mat.quaternion(); + normalize(); + return (*this); +} + +const LLQuaternion& LLQuaternion::setQuat(const LLMatrix4 &mat) +{ + *this = mat.quaternion(); + normalize(); + return (*this); //#if 1 -// // NOTE: LLQuaternion's are actually inverted with respect to -// // the matrices, so this code also assumes inverted quaternions -// // (-x, -y, -z, w). The result is that roll,pitch,yaw are applied -// // in reverse order (yaw,pitch,roll). -// F64 cosX = cos(roll); +// // NOTE: LLQuaternion's are actually inverted with respect to +// // the matrices, so this code also assumes inverted quaternions +// // (-x, -y, -z, w). The result is that roll,pitch,yaw are applied +// // in reverse order (yaw,pitch,roll). +// F64 cosX = cos(roll); // F64 cosY = cos(pitch); // F64 cosZ = cos(yaw); // @@ -337,24 +337,24 @@ const LLQuaternion& LLQuaternion::setQuat(const LLMatrix4 &mat) // F64 sinZ = sin(yaw); // // mQ[VW] = (F32)sqrt(cosY*cosZ - sinX*sinY*sinZ + cosX*cosZ + cosX*cosY + 1.0)*.5; -// if (fabs(mQ[VW]) < F_APPROXIMATELY_ZERO) -// { -// // null rotation, any axis will do -// mQ[VX] = 0.0f; -// mQ[VY] = 1.0f; -// mQ[VZ] = 0.0f; -// } -// else -// { -// F32 inv_s = 1.0f / (4.0f * mQ[VW]); -// mQ[VX] = (F32)-(-sinX*cosY - cosX*sinY*sinZ - sinX*cosZ) * inv_s; -// mQ[VY] = (F32)-(-cosX*sinY*cosZ + sinX*sinZ - sinY) * inv_s; -// mQ[VZ] = (F32)-(-cosY*sinZ - sinX*sinY*cosZ - cosX*sinZ) * inv_s; -// } +// if (fabs(mQ[VW]) < F_APPROXIMATELY_ZERO) +// { +// // null rotation, any axis will do +// mQ[VX] = 0.0f; +// mQ[VY] = 1.0f; +// mQ[VZ] = 0.0f; +// } +// else +// { +// F32 inv_s = 1.0f / (4.0f * mQ[VW]); +// mQ[VX] = (F32)-(-sinX*cosY - cosX*sinY*sinZ - sinX*cosZ) * inv_s; +// mQ[VY] = (F32)-(-cosX*sinY*cosZ + sinX*sinZ - sinY) * inv_s; +// mQ[VZ] = (F32)-(-cosY*sinZ - sinX*sinY*cosZ - cosX*sinZ) * inv_s; +// } // //#else // This only works on a certain subset of roll/pitch/yaw -// -// F64 cosX = cosf(roll/2.0); +// +// F64 cosX = cosf(roll/2.0); // F64 cosY = cosf(pitch/2.0); // F64 cosZ = cosf(yaw/2.0); // @@ -368,19 +368,19 @@ const LLQuaternion& LLQuaternion::setQuat(const LLMatrix4 &mat) // mQ[VZ] = (F32)(cosX*cosY*sinZ - sinX*sinY*cosZ); //#endif // -// normalize(); -// return (*this); +// normalize(); +// return (*this); } // SJB: This code is correct for a logicly stored (non-transposed) matrix; -// Our matrices are stored transposed, OpenGL style, so this generates the -// INVERSE matrix, or the CORRECT matrix form an INVERSE quaternion. -// Because we use similar logic in LLMatrix3::quaternion(), -// we are internally consistant so everything works OK :) -LLMatrix3 LLQuaternion::getMatrix3(void) const +// Our matrices are stored transposed, OpenGL style, so this generates the +// INVERSE matrix, or the CORRECT matrix form an INVERSE quaternion. +// Because we use similar logic in LLMatrix3::quaternion(), +// we are internally consistant so everything works OK :) +LLMatrix3 LLQuaternion::getMatrix3(void) const { - LLMatrix3 mat; - F32 xx, xy, xz, xw, yy, yz, yw, zz, zw; + LLMatrix3 mat; + F32 xx, xy, xz, xw, yy, yz, yw, zz, zw; xx = mQ[VX] * mQ[VX]; xy = mQ[VX] * mQ[VY]; @@ -395,24 +395,24 @@ LLMatrix3 LLQuaternion::getMatrix3(void) const zw = mQ[VZ] * mQ[VW]; mat.mMatrix[0][0] = 1.f - 2.f * ( yy + zz ); - mat.mMatrix[0][1] = 2.f * ( xy + zw ); - mat.mMatrix[0][2] = 2.f * ( xz - yw ); + mat.mMatrix[0][1] = 2.f * ( xy + zw ); + mat.mMatrix[0][2] = 2.f * ( xz - yw ); - mat.mMatrix[1][0] = 2.f * ( xy - zw ); + mat.mMatrix[1][0] = 2.f * ( xy - zw ); mat.mMatrix[1][1] = 1.f - 2.f * ( xx + zz ); - mat.mMatrix[1][2] = 2.f * ( yz + xw ); + mat.mMatrix[1][2] = 2.f * ( yz + xw ); - mat.mMatrix[2][0] = 2.f * ( xz + yw ); - mat.mMatrix[2][1] = 2.f * ( yz - xw ); + mat.mMatrix[2][0] = 2.f * ( xz + yw ); + mat.mMatrix[2][1] = 2.f * ( yz - xw ); mat.mMatrix[2][2] = 1.f - 2.f * ( xx + yy ); - return mat; + return mat; } -LLMatrix4 LLQuaternion::getMatrix4(void) const +LLMatrix4 LLQuaternion::getMatrix4(void) const { - LLMatrix4 mat; - F32 xx, xy, xz, xw, yy, yz, yw, zz, zw; + LLMatrix4 mat; + F32 xx, xy, xz, xw, yy, yz, yw, zz, zw; xx = mQ[VX] * mQ[VX]; xy = mQ[VX] * mQ[VY]; @@ -427,20 +427,20 @@ LLMatrix4 LLQuaternion::getMatrix4(void) const zw = mQ[VZ] * mQ[VW]; mat.mMatrix[0][0] = 1.f - 2.f * ( yy + zz ); - mat.mMatrix[0][1] = 2.f * ( xy + zw ); - mat.mMatrix[0][2] = 2.f * ( xz - yw ); + mat.mMatrix[0][1] = 2.f * ( xy + zw ); + mat.mMatrix[0][2] = 2.f * ( xz - yw ); - mat.mMatrix[1][0] = 2.f * ( xy - zw ); + mat.mMatrix[1][0] = 2.f * ( xy - zw ); mat.mMatrix[1][1] = 1.f - 2.f * ( xx + zz ); - mat.mMatrix[1][2] = 2.f * ( yz + xw ); + mat.mMatrix[1][2] = 2.f * ( yz + xw ); - mat.mMatrix[2][0] = 2.f * ( xz + yw ); - mat.mMatrix[2][1] = 2.f * ( yz - xw ); + mat.mMatrix[2][0] = 2.f * ( xz + yw ); + mat.mMatrix[2][1] = 2.f * ( yz - xw ); mat.mMatrix[2][2] = 1.f - 2.f * ( xx + yy ); - // TODO -- should we set the translation portion to zero? + // TODO -- should we set the translation portion to zero? - return mat; + return mat; } @@ -452,110 +452,110 @@ LLMatrix4 LLQuaternion::getMatrix4(void) const // calculate the shortest rotation from a to b void LLQuaternion::shortestArc(const LLVector3 &a, const LLVector3 &b) { - F32 ab = a * b; // dotproduct - LLVector3 c = a % b; // crossproduct - F32 cc = c * c; // squared length of the crossproduct - if (ab * ab + cc) // test if the arguments have sufficient magnitude - { - if (cc > 0.0f) // test if the arguments are (anti)parallel - { - F32 s = sqrtf(ab * ab + cc) + ab; // note: don't try to optimize this line - F32 m = 1.0f / sqrtf(cc + s * s); // the inverted magnitude of the quaternion - mQ[VX] = c.mV[VX] * m; - mQ[VY] = c.mV[VY] * m; - mQ[VZ] = c.mV[VZ] * m; - mQ[VW] = s * m; - return; - } - if (ab < 0.0f) // test if the angle is bigger than PI/2 (anti parallel) - { - c = a - b; // the arguments are anti-parallel, we have to choose an axis - F32 m = sqrtf(c.mV[VX] * c.mV[VX] + c.mV[VY] * c.mV[VY]); // the length projected on the XY-plane - if (m > FP_MAG_THRESHOLD) - { - mQ[VX] = -c.mV[VY] / m; // return the quaternion with the axis in the XY-plane - mQ[VY] = c.mV[VX] / m; - mQ[VZ] = 0.0f; - mQ[VW] = 0.0f; - return; - } - else // the vectors are parallel to the Z-axis - { - mQ[VX] = 1.0f; // rotate around the X-axis - mQ[VY] = 0.0f; - mQ[VZ] = 0.0f; - mQ[VW] = 0.0f; - return; - } - } - } - loadIdentity(); + F32 ab = a * b; // dotproduct + LLVector3 c = a % b; // crossproduct + F32 cc = c * c; // squared length of the crossproduct + if (ab * ab + cc) // test if the arguments have sufficient magnitude + { + if (cc > 0.0f) // test if the arguments are (anti)parallel + { + F32 s = sqrtf(ab * ab + cc) + ab; // note: don't try to optimize this line + F32 m = 1.0f / sqrtf(cc + s * s); // the inverted magnitude of the quaternion + mQ[VX] = c.mV[VX] * m; + mQ[VY] = c.mV[VY] * m; + mQ[VZ] = c.mV[VZ] * m; + mQ[VW] = s * m; + return; + } + if (ab < 0.0f) // test if the angle is bigger than PI/2 (anti parallel) + { + c = a - b; // the arguments are anti-parallel, we have to choose an axis + F32 m = sqrtf(c.mV[VX] * c.mV[VX] + c.mV[VY] * c.mV[VY]); // the length projected on the XY-plane + if (m > FP_MAG_THRESHOLD) + { + mQ[VX] = -c.mV[VY] / m; // return the quaternion with the axis in the XY-plane + mQ[VY] = c.mV[VX] / m; + mQ[VZ] = 0.0f; + mQ[VW] = 0.0f; + return; + } + else // the vectors are parallel to the Z-axis + { + mQ[VX] = 1.0f; // rotate around the X-axis + mQ[VY] = 0.0f; + mQ[VZ] = 0.0f; + mQ[VW] = 0.0f; + return; + } + } + } + loadIdentity(); } // constrains rotation to a cone angle specified in radians const LLQuaternion &LLQuaternion::constrain(F32 radians) { - const F32 cos_angle_lim = cosf( radians/2 ); // mQ[VW] limit - const F32 sin_angle_lim = sinf( radians/2 ); // rotation axis length limit + const F32 cos_angle_lim = cosf( radians/2 ); // mQ[VW] limit + const F32 sin_angle_lim = sinf( radians/2 ); // rotation axis length limit - if (mQ[VW] < 0.f) - { - mQ[VX] *= -1.f; - mQ[VY] *= -1.f; - mQ[VZ] *= -1.f; - mQ[VW] *= -1.f; - } + if (mQ[VW] < 0.f) + { + mQ[VX] *= -1.f; + mQ[VY] *= -1.f; + mQ[VZ] *= -1.f; + mQ[VW] *= -1.f; + } - // if rotation angle is greater than limit (cos is less than limit) - if( mQ[VW] < cos_angle_lim ) - { - mQ[VW] = cos_angle_lim; - F32 axis_len = sqrtf( mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] ); // sin(theta/2) - F32 axis_mult_fact = sin_angle_lim / axis_len; - mQ[VX] *= axis_mult_fact; - mQ[VY] *= axis_mult_fact; - mQ[VZ] *= axis_mult_fact; - } + // if rotation angle is greater than limit (cos is less than limit) + if( mQ[VW] < cos_angle_lim ) + { + mQ[VW] = cos_angle_lim; + F32 axis_len = sqrtf( mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] ); // sin(theta/2) + F32 axis_mult_fact = sin_angle_lim / axis_len; + mQ[VX] *= axis_mult_fact; + mQ[VY] *= axis_mult_fact; + mQ[VZ] *= axis_mult_fact; + } - return *this; + return *this; } // Operators std::ostream& operator<<(std::ostream &s, const LLQuaternion &a) { - s << "{ " - << a.mQ[VX] << ", " << a.mQ[VY] << ", " << a.mQ[VZ] << ", " << a.mQ[VW] - << " }"; - return s; + s << "{ " + << a.mQ[VX] << ", " << a.mQ[VY] << ", " << a.mQ[VZ] << ", " << a.mQ[VW] + << " }"; + return s; } // Does NOT renormalize the result -LLQuaternion operator*(const LLQuaternion &a, const LLQuaternion &b) +LLQuaternion operator*(const LLQuaternion &a, const LLQuaternion &b) { -// LLQuaternion::mMultCount++; +// LLQuaternion::mMultCount++; - LLQuaternion q( - b.mQ[3] * a.mQ[0] + b.mQ[0] * a.mQ[3] + b.mQ[1] * a.mQ[2] - b.mQ[2] * a.mQ[1], - b.mQ[3] * a.mQ[1] + b.mQ[1] * a.mQ[3] + b.mQ[2] * a.mQ[0] - b.mQ[0] * a.mQ[2], - b.mQ[3] * a.mQ[2] + b.mQ[2] * a.mQ[3] + b.mQ[0] * a.mQ[1] - b.mQ[1] * a.mQ[0], - b.mQ[3] * a.mQ[3] - b.mQ[0] * a.mQ[0] - b.mQ[1] * a.mQ[1] - b.mQ[2] * a.mQ[2] - ); - return q; + LLQuaternion q( + b.mQ[3] * a.mQ[0] + b.mQ[0] * a.mQ[3] + b.mQ[1] * a.mQ[2] - b.mQ[2] * a.mQ[1], + b.mQ[3] * a.mQ[1] + b.mQ[1] * a.mQ[3] + b.mQ[2] * a.mQ[0] - b.mQ[0] * a.mQ[2], + b.mQ[3] * a.mQ[2] + b.mQ[2] * a.mQ[3] + b.mQ[0] * a.mQ[1] - b.mQ[1] * a.mQ[0], + b.mQ[3] * a.mQ[3] - b.mQ[0] * a.mQ[0] - b.mQ[1] * a.mQ[1] - b.mQ[2] * a.mQ[2] + ); + return q; } /* -LLMatrix4 operator*(const LLMatrix4 &m, const LLQuaternion &q) +LLMatrix4 operator*(const LLMatrix4 &m, const LLQuaternion &q) { - LLMatrix4 qmat(q); - return (m*qmat); + LLMatrix4 qmat(q); + return (m*qmat); } */ -LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot) +LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot) { F32 rw = - rot.mQ[VX] * a.mV[VX] - rot.mQ[VY] * a.mV[VY] - rot.mQ[VZ] * a.mV[VZ]; F32 rx = rot.mQ[VW] * a.mV[VX] + rot.mQ[VY] * a.mV[VZ] - rot.mQ[VZ] * a.mV[VY]; @@ -569,7 +569,7 @@ LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot) return LLVector4(nx, ny, nz, a.mV[VW]); } -LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot) +LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot) { F32 rw = - rot.mQ[VX] * a.mV[VX] - rot.mQ[VY] * a.mV[VY] - rot.mQ[VZ] * a.mV[VZ]; F32 rx = rot.mQ[VW] * a.mV[VX] + rot.mQ[VY] * a.mV[VZ] - rot.mQ[VZ] * a.mV[VY]; @@ -583,7 +583,7 @@ LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot) return LLVector3(nx, ny, nz); } -LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) +LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) { F64 rw = - rot.mQ[VX] * a.mdV[VX] - rot.mQ[VY] * a.mdV[VY] - rot.mQ[VZ] * a.mdV[VZ]; F64 rx = rot.mQ[VW] * a.mdV[VX] + rot.mQ[VY] * a.mdV[VZ] - rot.mQ[VZ] * a.mdV[VY]; @@ -599,10 +599,10 @@ LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) F32 dot(const LLQuaternion &a, const LLQuaternion &b) { - return a.mQ[VX] * b.mQ[VX] + - a.mQ[VY] * b.mQ[VY] + - a.mQ[VZ] * b.mQ[VZ] + - a.mQ[VW] * b.mQ[VW]; + return a.mQ[VX] * b.mQ[VX] + + a.mQ[VY] * b.mQ[VY] + + a.mQ[VZ] * b.mQ[VZ] + + a.mQ[VW] * b.mQ[VW]; } // DEMO HACK: This lerp is probably inocrrect now due intermediate normalization @@ -611,258 +611,258 @@ F32 dot(const LLQuaternion &a, const LLQuaternion &b) // linear interpolation LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q) { - LLQuaternion r; - r = t * (q - p) + p; - r.normalize(); - return r; + LLQuaternion r; + r = t * (q - p) + p; + r.normalize(); + return r; } #endif // lerp from identity to q LLQuaternion lerp(F32 t, const LLQuaternion &q) { - LLQuaternion r; - r.mQ[VX] = t * q.mQ[VX]; - r.mQ[VY] = t * q.mQ[VY]; - r.mQ[VZ] = t * q.mQ[VZ]; - r.mQ[VW] = t * (q.mQ[VZ] - 1.f) + 1.f; - r.normalize(); - return r; + LLQuaternion r; + r.mQ[VX] = t * q.mQ[VX]; + r.mQ[VY] = t * q.mQ[VY]; + r.mQ[VZ] = t * q.mQ[VZ]; + r.mQ[VW] = t * (q.mQ[VZ] - 1.f) + 1.f; + r.normalize(); + return r; } LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q) { - LLQuaternion r; - F32 inv_t; + LLQuaternion r; + F32 inv_t; - inv_t = 1.f - t; + inv_t = 1.f - t; - r.mQ[VX] = t * q.mQ[VX] + (inv_t * p.mQ[VX]); - r.mQ[VY] = t * q.mQ[VY] + (inv_t * p.mQ[VY]); - r.mQ[VZ] = t * q.mQ[VZ] + (inv_t * p.mQ[VZ]); - r.mQ[VW] = t * q.mQ[VW] + (inv_t * p.mQ[VW]); - r.normalize(); - return r; + r.mQ[VX] = t * q.mQ[VX] + (inv_t * p.mQ[VX]); + r.mQ[VY] = t * q.mQ[VY] + (inv_t * p.mQ[VY]); + r.mQ[VZ] = t * q.mQ[VZ] + (inv_t * p.mQ[VZ]); + r.mQ[VW] = t * q.mQ[VW] + (inv_t * p.mQ[VW]); + r.normalize(); + return r; } // spherical linear interpolation LLQuaternion slerp( F32 u, const LLQuaternion &a, const LLQuaternion &b ) { - // cosine theta = dot product of a and b - F32 cos_t = a.mQ[0]*b.mQ[0] + a.mQ[1]*b.mQ[1] + a.mQ[2]*b.mQ[2] + a.mQ[3]*b.mQ[3]; - - // if b is on opposite hemisphere from a, use -a instead - bool bflip; - if (cos_t < 0.0f) - { - cos_t = -cos_t; - bflip = true; - } - else - bflip = false; - - // if B is (within precision limits) the same as A, - // just linear interpolate between A and B. - F32 alpha; // interpolant - F32 beta; // 1 - interpolant - if (1.0f - cos_t < 0.00001f) - { - beta = 1.0f - u; - alpha = u; - } - else - { - F32 theta = acosf(cos_t); - F32 sin_t = sinf(theta); - beta = sinf(theta - u*theta) / sin_t; - alpha = sinf(u*theta) / sin_t; - } - - if (bflip) - beta = -beta; - - // interpolate - LLQuaternion ret; - ret.mQ[0] = beta*a.mQ[0] + alpha*b.mQ[0]; - ret.mQ[1] = beta*a.mQ[1] + alpha*b.mQ[1]; - ret.mQ[2] = beta*a.mQ[2] + alpha*b.mQ[2]; - ret.mQ[3] = beta*a.mQ[3] + alpha*b.mQ[3]; - - return ret; + // cosine theta = dot product of a and b + F32 cos_t = a.mQ[0]*b.mQ[0] + a.mQ[1]*b.mQ[1] + a.mQ[2]*b.mQ[2] + a.mQ[3]*b.mQ[3]; + + // if b is on opposite hemisphere from a, use -a instead + bool bflip; + if (cos_t < 0.0f) + { + cos_t = -cos_t; + bflip = true; + } + else + bflip = false; + + // if B is (within precision limits) the same as A, + // just linear interpolate between A and B. + F32 alpha; // interpolant + F32 beta; // 1 - interpolant + if (1.0f - cos_t < 0.00001f) + { + beta = 1.0f - u; + alpha = u; + } + else + { + F32 theta = acosf(cos_t); + F32 sin_t = sinf(theta); + beta = sinf(theta - u*theta) / sin_t; + alpha = sinf(u*theta) / sin_t; + } + + if (bflip) + beta = -beta; + + // interpolate + LLQuaternion ret; + ret.mQ[0] = beta*a.mQ[0] + alpha*b.mQ[0]; + ret.mQ[1] = beta*a.mQ[1] + alpha*b.mQ[1]; + ret.mQ[2] = beta*a.mQ[2] + alpha*b.mQ[2]; + ret.mQ[3] = beta*a.mQ[3] + alpha*b.mQ[3]; + + return ret; } // lerp whenever possible LLQuaternion nlerp(F32 t, const LLQuaternion &a, const LLQuaternion &b) { - if (dot(a, b) < 0.f) - { - return slerp(t, a, b); - } - else - { - return lerp(t, a, b); - } + if (dot(a, b) < 0.f) + { + return slerp(t, a, b); + } + else + { + return lerp(t, a, b); + } } LLQuaternion nlerp(F32 t, const LLQuaternion &q) { - if (q.mQ[VW] < 0.f) - { - return slerp(t, q); - } - else - { - return lerp(t, q); - } + if (q.mQ[VW] < 0.f) + { + return slerp(t, q); + } + else + { + return lerp(t, q); + } } // slerp from identity quaternion to another quaternion LLQuaternion slerp(F32 t, const LLQuaternion &q) { - F32 c = q.mQ[VW]; - if (1.0f == t || 1.0f == c) - { - // the trivial cases - return q; - } + F32 c = q.mQ[VW]; + if (1.0f == t || 1.0f == c) + { + // the trivial cases + return q; + } - LLQuaternion r; - F32 s, angle, stq, stp; + LLQuaternion r; + F32 s, angle, stq, stp; - s = (F32) sqrt(1.f - c*c); + s = (F32) sqrt(1.f - c*c); if (c < 0.0f) { - // when c < 0.0 then theta > PI/2 - // since quat and -quat are the same rotation we invert one of + // when c < 0.0 then theta > PI/2 + // since quat and -quat are the same rotation we invert one of // p or q to reduce unecessary spins - // A equivalent way to do it is to convert acos(c) as if it had - // been negative, and to negate stp - angle = (F32) acos(-c); + // A equivalent way to do it is to convert acos(c) as if it had + // been negative, and to negate stp + angle = (F32) acos(-c); stp = -(F32) sin(angle * (1.f - t)); stq = (F32) sin(angle * t); - } + } else { - angle = (F32) acos(c); + angle = (F32) acos(c); stp = (F32) sin(angle * (1.f - t)); stq = (F32) sin(angle * t); } - r.mQ[VX] = (q.mQ[VX] * stq) / s; - r.mQ[VY] = (q.mQ[VY] * stq) / s; - r.mQ[VZ] = (q.mQ[VZ] * stq) / s; - r.mQ[VW] = (stp + q.mQ[VW] * stq) / s; + r.mQ[VX] = (q.mQ[VX] * stq) / s; + r.mQ[VY] = (q.mQ[VY] * stq) / s; + r.mQ[VZ] = (q.mQ[VZ] * stq) / s; + r.mQ[VW] = (stp + q.mQ[VW] * stq) / s; - return r; + return r; } LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) { - LLQuaternion xQ( xRot*DEG_TO_RAD, LLVector3(1.0f, 0.0f, 0.0f) ); - LLQuaternion yQ( yRot*DEG_TO_RAD, LLVector3(0.0f, 1.0f, 0.0f) ); - LLQuaternion zQ( zRot*DEG_TO_RAD, LLVector3(0.0f, 0.0f, 1.0f) ); - LLQuaternion ret; - switch( order ) - { - case LLQuaternion::XYZ: - ret = xQ * yQ * zQ; - break; - case LLQuaternion::YZX: - ret = yQ * zQ * xQ; - break; - case LLQuaternion::ZXY: - ret = zQ * xQ * yQ; - break; - case LLQuaternion::XZY: - ret = xQ * zQ * yQ; - break; - case LLQuaternion::YXZ: - ret = yQ * xQ * zQ; - break; - case LLQuaternion::ZYX: - ret = zQ * yQ * xQ; - break; - } - return ret; + LLQuaternion xQ( xRot*DEG_TO_RAD, LLVector3(1.0f, 0.0f, 0.0f) ); + LLQuaternion yQ( yRot*DEG_TO_RAD, LLVector3(0.0f, 1.0f, 0.0f) ); + LLQuaternion zQ( zRot*DEG_TO_RAD, LLVector3(0.0f, 0.0f, 1.0f) ); + LLQuaternion ret; + switch( order ) + { + case LLQuaternion::XYZ: + ret = xQ * yQ * zQ; + break; + case LLQuaternion::YZX: + ret = yQ * zQ * xQ; + break; + case LLQuaternion::ZXY: + ret = zQ * xQ * yQ; + break; + case LLQuaternion::XZY: + ret = xQ * zQ * yQ; + break; + case LLQuaternion::YXZ: + ret = yQ * xQ * zQ; + break; + case LLQuaternion::ZYX: + ret = zQ * yQ * xQ; + break; + } + return ret; } const char *OrderToString( const LLQuaternion::Order order ) { - const char *p = NULL; - switch( order ) - { - default: - case LLQuaternion::XYZ: - p = "XYZ"; - break; - case LLQuaternion::YZX: - p = "YZX"; - break; - case LLQuaternion::ZXY: - p = "ZXY"; - break; - case LLQuaternion::XZY: - p = "XZY"; - break; - case LLQuaternion::YXZ: - p = "YXZ"; - break; - case LLQuaternion::ZYX: - p = "ZYX"; - break; - } - return p; + const char *p = NULL; + switch( order ) + { + default: + case LLQuaternion::XYZ: + p = "XYZ"; + break; + case LLQuaternion::YZX: + p = "YZX"; + break; + case LLQuaternion::ZXY: + p = "ZXY"; + break; + case LLQuaternion::XZY: + p = "XZY"; + break; + case LLQuaternion::YXZ: + p = "YXZ"; + break; + case LLQuaternion::ZYX: + p = "ZYX"; + break; + } + return p; } LLQuaternion::Order StringToOrder( const char *str ) { - if (strncmp(str, "XYZ", 3)==0 || strncmp(str, "xyz", 3)==0) - return LLQuaternion::XYZ; + if (strncmp(str, "XYZ", 3)==0 || strncmp(str, "xyz", 3)==0) + return LLQuaternion::XYZ; - if (strncmp(str, "YZX", 3)==0 || strncmp(str, "yzx", 3)==0) - return LLQuaternion::YZX; + if (strncmp(str, "YZX", 3)==0 || strncmp(str, "yzx", 3)==0) + return LLQuaternion::YZX; - if (strncmp(str, "ZXY", 3)==0 || strncmp(str, "zxy", 3)==0) - return LLQuaternion::ZXY; + if (strncmp(str, "ZXY", 3)==0 || strncmp(str, "zxy", 3)==0) + return LLQuaternion::ZXY; - if (strncmp(str, "XZY", 3)==0 || strncmp(str, "xzy", 3)==0) - return LLQuaternion::XZY; + if (strncmp(str, "XZY", 3)==0 || strncmp(str, "xzy", 3)==0) + return LLQuaternion::XZY; - if (strncmp(str, "YXZ", 3)==0 || strncmp(str, "yxz", 3)==0) - return LLQuaternion::YXZ; + if (strncmp(str, "YXZ", 3)==0 || strncmp(str, "yxz", 3)==0) + return LLQuaternion::YXZ; - if (strncmp(str, "ZYX", 3)==0 || strncmp(str, "zyx", 3)==0) - return LLQuaternion::ZYX; + if (strncmp(str, "ZYX", 3)==0 || strncmp(str, "zyx", 3)==0) + return LLQuaternion::ZYX; - return LLQuaternion::XYZ; + return LLQuaternion::XYZ; } void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const { - F32 v = sqrtf(mQ[VX] * mQ[VX] + mQ[VY] * mQ[VY] + mQ[VZ] * mQ[VZ]); // length of the vector-component - if (v > FP_MAG_THRESHOLD) - { - F32 oomag = 1.0f / v; - F32 w = mQ[VW]; - if (mQ[VW] < 0.0f) - { - w = -w; // make VW positive - oomag = -oomag; // invert the axis - } - vec.mV[VX] = mQ[VX] * oomag; // normalize the axis - vec.mV[VY] = mQ[VY] * oomag; - vec.mV[VZ] = mQ[VZ] * oomag; - *angle = 2.0f * atan2f(v, w); // get the angle - } - else - { - *angle = 0.0f; // no rotation - vec.mV[VX] = 0.0f; // around some dummy axis - vec.mV[VY] = 0.0f; - vec.mV[VZ] = 1.0f; - } + F32 v = sqrtf(mQ[VX] * mQ[VX] + mQ[VY] * mQ[VY] + mQ[VZ] * mQ[VZ]); // length of the vector-component + if (v > FP_MAG_THRESHOLD) + { + F32 oomag = 1.0f / v; + F32 w = mQ[VW]; + if (mQ[VW] < 0.0f) + { + w = -w; // make VW positive + oomag = -oomag; // invert the axis + } + vec.mV[VX] = mQ[VX] * oomag; // normalize the axis + vec.mV[VY] = mQ[VY] * oomag; + vec.mV[VZ] = mQ[VZ] * oomag; + *angle = 2.0f * atan2f(v, w); // get the angle + } + else + { + *angle = 0.0f; // no rotation + vec.mV[VX] = 0.0f; // around some dummy axis + vec.mV[VY] = 0.0f; + vec.mV[VZ] = 1.0f; + } } const LLQuaternion& LLQuaternion::setFromAzimuthAndAltitude(F32 azimuthRadians, F32 altitudeRadians) @@ -888,93 +888,93 @@ void LLQuaternion::getAzimuthAndAltitude(F32 &azimuthRadians, F32 &altitudeRadia // quaternion does not need to be normalized void LLQuaternion::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const { - F32 sx = 2 * (mQ[VX] * mQ[VW] - mQ[VY] * mQ[VZ]); // sine of the roll - F32 sy = 2 * (mQ[VY] * mQ[VW] + mQ[VX] * mQ[VZ]); // sine of the pitch - F32 ys = mQ[VW] * mQ[VW] - mQ[VY] * mQ[VY]; // intermediate cosine 1 - F32 xz = mQ[VX] * mQ[VX] - mQ[VZ] * mQ[VZ]; // intermediate cosine 2 - F32 cx = ys - xz; // cosine of the roll - F32 cy = sqrtf(sx * sx + cx * cx); // cosine of the pitch - if (cy > GIMBAL_THRESHOLD) // no gimbal lock - { - *roll = atan2f(sx, cx); - *pitch = atan2f(sy, cy); - *yaw = atan2f(2 * (mQ[VZ] * mQ[VW] - mQ[VX] * mQ[VY]), ys + xz); - } - else // gimbal lock - { - if (sy > 0) - { - *pitch = F_PI_BY_TWO; - *yaw = 2 * atan2f(mQ[VZ] + mQ[VX], mQ[VW] + mQ[VY]); - } - else - { - *pitch = -F_PI_BY_TWO; - *yaw = 2 * atan2f(mQ[VZ] - mQ[VX], mQ[VW] - mQ[VY]); - } - *roll = 0; - } + F32 sx = 2 * (mQ[VX] * mQ[VW] - mQ[VY] * mQ[VZ]); // sine of the roll + F32 sy = 2 * (mQ[VY] * mQ[VW] + mQ[VX] * mQ[VZ]); // sine of the pitch + F32 ys = mQ[VW] * mQ[VW] - mQ[VY] * mQ[VY]; // intermediate cosine 1 + F32 xz = mQ[VX] * mQ[VX] - mQ[VZ] * mQ[VZ]; // intermediate cosine 2 + F32 cx = ys - xz; // cosine of the roll + F32 cy = sqrtf(sx * sx + cx * cx); // cosine of the pitch + if (cy > GIMBAL_THRESHOLD) // no gimbal lock + { + *roll = atan2f(sx, cx); + *pitch = atan2f(sy, cy); + *yaw = atan2f(2 * (mQ[VZ] * mQ[VW] - mQ[VX] * mQ[VY]), ys + xz); + } + else // gimbal lock + { + if (sy > 0) + { + *pitch = F_PI_BY_TWO; + *yaw = 2 * atan2f(mQ[VZ] + mQ[VX], mQ[VW] + mQ[VY]); + } + else + { + *pitch = -F_PI_BY_TWO; + *yaw = 2 * atan2f(mQ[VZ] - mQ[VX], mQ[VW] - mQ[VY]); + } + *roll = 0; + } } // Saves space by using the fact that our quaternions are normalized LLVector3 LLQuaternion::packToVector3() const { - F32 x = mQ[VX]; - F32 y = mQ[VY]; - F32 z = mQ[VZ]; - F32 w = mQ[VW]; - F32 mag = sqrtf(x * x + y * y + z * z + w * w); - if (mag > FP_MAG_THRESHOLD) - { - x /= mag; - y /= mag; - z /= mag; // no need to normalize w, it's not used - } - if( mQ[VW] >= 0 ) - { - return LLVector3( x, y , z ); - } - else - { - return LLVector3( -x, -y, -z ); - } + F32 x = mQ[VX]; + F32 y = mQ[VY]; + F32 z = mQ[VZ]; + F32 w = mQ[VW]; + F32 mag = sqrtf(x * x + y * y + z * z + w * w); + if (mag > FP_MAG_THRESHOLD) + { + x /= mag; + y /= mag; + z /= mag; // no need to normalize w, it's not used + } + if( mQ[VW] >= 0 ) + { + return LLVector3( x, y , z ); + } + else + { + return LLVector3( -x, -y, -z ); + } } // Saves space by using the fact that our quaternions are normalized void LLQuaternion::unpackFromVector3( const LLVector3& vec ) { - mQ[VX] = vec.mV[VX]; - mQ[VY] = vec.mV[VY]; - mQ[VZ] = vec.mV[VZ]; - F32 t = 1.f - vec.magVecSquared(); - if( t > 0 ) - { - mQ[VW] = sqrt( t ); - } - else - { - // Need this to avoid trying to find the square root of a negative number due - // to floating point error. - mQ[VW] = 0; - } + mQ[VX] = vec.mV[VX]; + mQ[VY] = vec.mV[VY]; + mQ[VZ] = vec.mV[VZ]; + F32 t = 1.f - vec.magVecSquared(); + if( t > 0 ) + { + mQ[VW] = sqrt( t ); + } + else + { + // Need this to avoid trying to find the square root of a negative number due + // to floating point error. + mQ[VW] = 0; + } } bool LLQuaternion::parseQuat(const std::string& buf, LLQuaternion* value) { - if( buf.empty() || value == NULL) - { - return false; - } + if( buf.empty() || value == NULL) + { + return false; + } - LLQuaternion quat; - S32 count = sscanf( buf.c_str(), "%f %f %f %f", quat.mQ + 0, quat.mQ + 1, quat.mQ + 2, quat.mQ + 3 ); - if( 4 == count ) - { - value->set( quat ); - return true; - } + LLQuaternion quat; + S32 count = sscanf( buf.c_str(), "%f %f %f %f", quat.mQ + 0, quat.mQ + 1, quat.mQ + 2, quat.mQ + 3 ); + if( 4 == count ) + { + value->set( quat ); + return true; + } - return false; + return false; } diff --git a/indra/llmath/llquaternion.h b/indra/llmath/llquaternion.h index 1c9da7c342..2caa993007 100644 --- a/indra/llmath/llquaternion.h +++ b/indra/llmath/llquaternion.h @@ -5,21 +5,21 @@ * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -40,137 +40,137 @@ class LLVector3d; class LLMatrix4; class LLMatrix3; -// NOTA BENE: Quaternion code is written assuming Unit Quaternions!!!! -// Moreover, it is written assuming that all vectors and matricies -// passed as arguments are normalized and unitary respectively. -// VERY VERY VERY VERY BAD THINGS will happen if these assumptions fail. +// NOTA BENE: Quaternion code is written assuming Unit Quaternions!!!! +// Moreover, it is written assuming that all vectors and matricies +// passed as arguments are normalized and unitary respectively. +// VERY VERY VERY VERY BAD THINGS will happen if these assumptions fail. static const U32 LENGTHOFQUAT = 4; class LLQuaternion { public: - F32 mQ[LENGTHOFQUAT]; - - static const LLQuaternion DEFAULT; - - LLQuaternion(); // Initializes Quaternion to (0,0,0,1) - explicit LLQuaternion(const LLMatrix4 &mat); // Initializes Quaternion from Matrix4 - explicit LLQuaternion(const LLMatrix3 &mat); // Initializes Quaternion from Matrix3 - LLQuaternion(F32 x, F32 y, F32 z, F32 w); // Initializes Quaternion to normalize(x, y, z, w) - LLQuaternion(F32 angle, const LLVector4 &vec); // Initializes Quaternion to axis_angle2quat(angle, vec) - LLQuaternion(F32 angle, const LLVector3 &vec); // Initializes Quaternion to axis_angle2quat(angle, vec) - LLQuaternion(const F32 *q); // Initializes Quaternion to normalize(x, y, z, w) - LLQuaternion(const LLVector3 &x_axis, - const LLVector3 &y_axis, - const LLVector3 &z_axis); // Initializes Quaternion from Matrix3 = [x_axis ; y_axis ; z_axis] + F32 mQ[LENGTHOFQUAT]; + + static const LLQuaternion DEFAULT; + + LLQuaternion(); // Initializes Quaternion to (0,0,0,1) + explicit LLQuaternion(const LLMatrix4 &mat); // Initializes Quaternion from Matrix4 + explicit LLQuaternion(const LLMatrix3 &mat); // Initializes Quaternion from Matrix3 + LLQuaternion(F32 x, F32 y, F32 z, F32 w); // Initializes Quaternion to normalize(x, y, z, w) + LLQuaternion(F32 angle, const LLVector4 &vec); // Initializes Quaternion to axis_angle2quat(angle, vec) + LLQuaternion(F32 angle, const LLVector3 &vec); // Initializes Quaternion to axis_angle2quat(angle, vec) + LLQuaternion(const F32 *q); // Initializes Quaternion to normalize(x, y, z, w) + LLQuaternion(const LLVector3 &x_axis, + const LLVector3 &y_axis, + const LLVector3 &z_axis); // Initializes Quaternion from Matrix3 = [x_axis ; y_axis ; z_axis] explicit LLQuaternion(const LLSD &sd); // Initializes Quaternion from LLSD array. LLSD getValue() const; void setValue(const LLSD& sd); - bool isIdentity() const; - bool isNotIdentity() const; - bool isFinite() const; // checks to see if all values of LLQuaternion are finite - void quantize16(F32 lower, F32 upper); // changes the vector to reflect quatization - void quantize8(F32 lower, F32 upper); // changes the vector to reflect quatization - void loadIdentity(); // Loads the quaternion that represents the identity rotation - - bool isEqualEps(const LLQuaternion &quat, F32 epsilon) const; - bool isNotEqualEps(const LLQuaternion &quat, F32 epsilon) const; - - const LLQuaternion& set(F32 x, F32 y, F32 z, F32 w); // Sets Quaternion to normalize(x, y, z, w) - const LLQuaternion& set(const LLQuaternion &quat); // Copies Quaternion - const LLQuaternion& set(const F32 *q); // Sets Quaternion to normalize(quat[VX], quat[VY], quat[VZ], quat[VW]) - const LLQuaternion& set(const LLMatrix3 &mat); // Sets Quaternion to mat2quat(mat) - const LLQuaternion& set(const LLMatrix4 &mat); // Sets Quaternion to mat2quat(mat) + bool isIdentity() const; + bool isNotIdentity() const; + bool isFinite() const; // checks to see if all values of LLQuaternion are finite + void quantize16(F32 lower, F32 upper); // changes the vector to reflect quatization + void quantize8(F32 lower, F32 upper); // changes the vector to reflect quatization + void loadIdentity(); // Loads the quaternion that represents the identity rotation + + bool isEqualEps(const LLQuaternion &quat, F32 epsilon) const; + bool isNotEqualEps(const LLQuaternion &quat, F32 epsilon) const; + + const LLQuaternion& set(F32 x, F32 y, F32 z, F32 w); // Sets Quaternion to normalize(x, y, z, w) + const LLQuaternion& set(const LLQuaternion &quat); // Copies Quaternion + const LLQuaternion& set(const F32 *q); // Sets Quaternion to normalize(quat[VX], quat[VY], quat[VZ], quat[VW]) + const LLQuaternion& set(const LLMatrix3 &mat); // Sets Quaternion to mat2quat(mat) + const LLQuaternion& set(const LLMatrix4 &mat); // Sets Quaternion to mat2quat(mat) const LLQuaternion& setFromAzimuthAndAltitude(F32 azimuth, F32 altitude); - - const LLQuaternion& setAngleAxis(F32 angle, F32 x, F32 y, F32 z); // Sets Quaternion to axis_angle2quat(angle, x, y, z) - const LLQuaternion& setAngleAxis(F32 angle, const LLVector3 &vec); // Sets Quaternion to axis_angle2quat(angle, vec) - const LLQuaternion& setAngleAxis(F32 angle, const LLVector4 &vec); // Sets Quaternion to axis_angle2quat(angle, vec) - const LLQuaternion& setEulerAngles(F32 roll, F32 pitch, F32 yaw); // Sets Quaternion to euler2quat(pitch, yaw, roll) - - const LLQuaternion& setQuatInit(F32 x, F32 y, F32 z, F32 w); // deprecated - const LLQuaternion& setQuat(const LLQuaternion &quat); // deprecated - const LLQuaternion& setQuat(const F32 *q); // deprecated - const LLQuaternion& setQuat(const LLMatrix3 &mat); // deprecated - const LLQuaternion& setQuat(const LLMatrix4 &mat); // deprecated - const LLQuaternion& setQuat(F32 angle, F32 x, F32 y, F32 z); // deprecated - const LLQuaternion& setQuat(F32 angle, const LLVector3 &vec); // deprecated - const LLQuaternion& setQuat(F32 angle, const LLVector4 &vec); // deprecated - const LLQuaternion& setQuat(F32 roll, F32 pitch, F32 yaw); // deprecated - - LLMatrix4 getMatrix4(void) const; // Returns the Matrix4 equivalent of Quaternion - LLMatrix3 getMatrix3(void) const; // Returns the Matrix3 equivalent of Quaternion - void getAngleAxis(F32* angle, F32* x, F32* y, F32* z) const; // returns rotation in radians about axis x,y,z - void getAngleAxis(F32* angle, LLVector3 &vec) const; - void getEulerAngles(F32 *roll, F32* pitch, F32 *yaw) const; + + const LLQuaternion& setAngleAxis(F32 angle, F32 x, F32 y, F32 z); // Sets Quaternion to axis_angle2quat(angle, x, y, z) + const LLQuaternion& setAngleAxis(F32 angle, const LLVector3 &vec); // Sets Quaternion to axis_angle2quat(angle, vec) + const LLQuaternion& setAngleAxis(F32 angle, const LLVector4 &vec); // Sets Quaternion to axis_angle2quat(angle, vec) + const LLQuaternion& setEulerAngles(F32 roll, F32 pitch, F32 yaw); // Sets Quaternion to euler2quat(pitch, yaw, roll) + + const LLQuaternion& setQuatInit(F32 x, F32 y, F32 z, F32 w); // deprecated + const LLQuaternion& setQuat(const LLQuaternion &quat); // deprecated + const LLQuaternion& setQuat(const F32 *q); // deprecated + const LLQuaternion& setQuat(const LLMatrix3 &mat); // deprecated + const LLQuaternion& setQuat(const LLMatrix4 &mat); // deprecated + const LLQuaternion& setQuat(F32 angle, F32 x, F32 y, F32 z); // deprecated + const LLQuaternion& setQuat(F32 angle, const LLVector3 &vec); // deprecated + const LLQuaternion& setQuat(F32 angle, const LLVector4 &vec); // deprecated + const LLQuaternion& setQuat(F32 roll, F32 pitch, F32 yaw); // deprecated + + LLMatrix4 getMatrix4(void) const; // Returns the Matrix4 equivalent of Quaternion + LLMatrix3 getMatrix3(void) const; // Returns the Matrix3 equivalent of Quaternion + void getAngleAxis(F32* angle, F32* x, F32* y, F32* z) const; // returns rotation in radians about axis x,y,z + void getAngleAxis(F32* angle, LLVector3 &vec) const; + void getEulerAngles(F32 *roll, F32* pitch, F32 *yaw) const; void getAzimuthAndAltitude(F32 &azimuth, F32 &altitude); - F32 normalize(); // Normalizes Quaternion and returns magnitude - F32 normQuat(); // deprecated - - const LLQuaternion& conjugate(void); // Conjugates Quaternion and returns result - const LLQuaternion& conjQuat(void); // deprecated - - // Other useful methods - const LLQuaternion& transpose(); // transpose (same as conjugate) - const LLQuaternion& transQuat(); // deprecated - - void shortestArc(const LLVector3 &a, const LLVector3 &b); // shortest rotation from a to b - const LLQuaternion& constrain(F32 radians); // constrains rotation to a cone angle specified in radians - - // Standard operators - friend std::ostream& operator<<(std::ostream &s, const LLQuaternion &a); // Prints a - friend LLQuaternion operator+(const LLQuaternion &a, const LLQuaternion &b); // Addition - friend LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b); // Subtraction - friend LLQuaternion operator-(const LLQuaternion &a); // Negation - friend LLQuaternion operator*(F32 a, const LLQuaternion &q); // Scale - friend LLQuaternion operator*(const LLQuaternion &q, F32 b); // Scale - friend LLQuaternion operator*(const LLQuaternion &a, const LLQuaternion &b); // Returns a * b - friend LLQuaternion operator~(const LLQuaternion &a); // Returns a* (Conjugate of a) - bool operator==(const LLQuaternion &b) const; // Returns a == b - bool operator!=(const LLQuaternion &b) const; // Returns a != b - - friend const LLQuaternion& operator*=(LLQuaternion &a, const LLQuaternion &b); // Returns a * b - - friend LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot); // Rotates a by rot - friend LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot); // Rotates a by rot - friend LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot); // Rotates a by rot - - // Non-standard operators - friend F32 dot(const LLQuaternion &a, const LLQuaternion &b); - friend LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q); // linear interpolation (t = 0 to 1) from p to q - friend LLQuaternion lerp(F32 t, const LLQuaternion &q); // linear interpolation (t = 0 to 1) from identity to q - friend LLQuaternion slerp(F32 t, const LLQuaternion &p, const LLQuaternion &q); // spherical linear interpolation from p to q - friend LLQuaternion slerp(F32 t, const LLQuaternion &q); // spherical linear interpolation from identity to q - friend LLQuaternion nlerp(F32 t, const LLQuaternion &p, const LLQuaternion &q); // normalized linear interpolation from p to q - friend LLQuaternion nlerp(F32 t, const LLQuaternion &q); // normalized linear interpolation from p to q - - LLVector3 packToVector3() const; // Saves space by using the fact that our quaternions are normalized - void unpackFromVector3(const LLVector3& vec); // Saves space by using the fact that our quaternions are normalized - - enum Order { - XYZ = 0, - YZX = 1, - ZXY = 2, - XZY = 3, - YXZ = 4, - ZYX = 5 - }; - // Creates a quaternions from maya's rotation representation, - // which is 3 rotations (in DEGREES) in the specified order - friend LLQuaternion mayaQ(F32 x, F32 y, F32 z, Order order); - - // Conversions between Order and strings like "xyz" or "ZYX" - friend const char *OrderToString( const Order order ); - friend Order StringToOrder( const char *str ); - - static bool parseQuat(const std::string& buf, LLQuaternion* value); - - // For debugging, only - //static U32 mMultCount; + F32 normalize(); // Normalizes Quaternion and returns magnitude + F32 normQuat(); // deprecated + + const LLQuaternion& conjugate(void); // Conjugates Quaternion and returns result + const LLQuaternion& conjQuat(void); // deprecated + + // Other useful methods + const LLQuaternion& transpose(); // transpose (same as conjugate) + const LLQuaternion& transQuat(); // deprecated + + void shortestArc(const LLVector3 &a, const LLVector3 &b); // shortest rotation from a to b + const LLQuaternion& constrain(F32 radians); // constrains rotation to a cone angle specified in radians + + // Standard operators + friend std::ostream& operator<<(std::ostream &s, const LLQuaternion &a); // Prints a + friend LLQuaternion operator+(const LLQuaternion &a, const LLQuaternion &b); // Addition + friend LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b); // Subtraction + friend LLQuaternion operator-(const LLQuaternion &a); // Negation + friend LLQuaternion operator*(F32 a, const LLQuaternion &q); // Scale + friend LLQuaternion operator*(const LLQuaternion &q, F32 b); // Scale + friend LLQuaternion operator*(const LLQuaternion &a, const LLQuaternion &b); // Returns a * b + friend LLQuaternion operator~(const LLQuaternion &a); // Returns a* (Conjugate of a) + bool operator==(const LLQuaternion &b) const; // Returns a == b + bool operator!=(const LLQuaternion &b) const; // Returns a != b + + friend const LLQuaternion& operator*=(LLQuaternion &a, const LLQuaternion &b); // Returns a * b + + friend LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot); // Rotates a by rot + friend LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot); // Rotates a by rot + friend LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot); // Rotates a by rot + + // Non-standard operators + friend F32 dot(const LLQuaternion &a, const LLQuaternion &b); + friend LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q); // linear interpolation (t = 0 to 1) from p to q + friend LLQuaternion lerp(F32 t, const LLQuaternion &q); // linear interpolation (t = 0 to 1) from identity to q + friend LLQuaternion slerp(F32 t, const LLQuaternion &p, const LLQuaternion &q); // spherical linear interpolation from p to q + friend LLQuaternion slerp(F32 t, const LLQuaternion &q); // spherical linear interpolation from identity to q + friend LLQuaternion nlerp(F32 t, const LLQuaternion &p, const LLQuaternion &q); // normalized linear interpolation from p to q + friend LLQuaternion nlerp(F32 t, const LLQuaternion &q); // normalized linear interpolation from p to q + + LLVector3 packToVector3() const; // Saves space by using the fact that our quaternions are normalized + void unpackFromVector3(const LLVector3& vec); // Saves space by using the fact that our quaternions are normalized + + enum Order { + XYZ = 0, + YZX = 1, + ZXY = 2, + XZY = 3, + YXZ = 4, + ZYX = 5 + }; + // Creates a quaternions from maya's rotation representation, + // which is 3 rotations (in DEGREES) in the specified order + friend LLQuaternion mayaQ(F32 x, F32 y, F32 z, Order order); + + // Conversions between Order and strings like "xyz" or "ZYX" + friend const char *OrderToString( const Order order ); + friend Order StringToOrder( const char *str ); + + static bool parseQuat(const std::string& buf, LLQuaternion* value); + + // For debugging, only + //static U32 mMultCount; }; inline LLSD LLQuaternion::getValue() const @@ -192,369 +192,369 @@ inline void LLQuaternion::setValue(const LLSD& sd) } // checker -inline bool LLQuaternion::isFinite() const +inline bool LLQuaternion::isFinite() const { - return (llfinite(mQ[VX]) && llfinite(mQ[VY]) && llfinite(mQ[VZ]) && llfinite(mQ[VS])); + return (llfinite(mQ[VX]) && llfinite(mQ[VY]) && llfinite(mQ[VZ]) && llfinite(mQ[VS])); } inline bool LLQuaternion::isIdentity() const { - return - ( mQ[VX] == 0.f ) && - ( mQ[VY] == 0.f ) && - ( mQ[VZ] == 0.f ) && - ( mQ[VS] == 1.f ); + return + ( mQ[VX] == 0.f ) && + ( mQ[VY] == 0.f ) && + ( mQ[VZ] == 0.f ) && + ( mQ[VS] == 1.f ); } inline bool LLQuaternion::isNotIdentity() const { - return - ( mQ[VX] != 0.f ) || - ( mQ[VY] != 0.f ) || - ( mQ[VZ] != 0.f ) || - ( mQ[VS] != 1.f ); + return + ( mQ[VX] != 0.f ) || + ( mQ[VY] != 0.f ) || + ( mQ[VZ] != 0.f ) || + ( mQ[VS] != 1.f ); } inline LLQuaternion::LLQuaternion(void) { - mQ[VX] = 0.f; - mQ[VY] = 0.f; - mQ[VZ] = 0.f; - mQ[VS] = 1.f; + mQ[VX] = 0.f; + mQ[VY] = 0.f; + mQ[VZ] = 0.f; + mQ[VS] = 1.f; } inline LLQuaternion::LLQuaternion(F32 x, F32 y, F32 z, F32 w) { - mQ[VX] = x; - mQ[VY] = y; - mQ[VZ] = z; - mQ[VS] = w; + mQ[VX] = x; + mQ[VY] = y; + mQ[VZ] = z; + mQ[VS] = w; - //RN: don't normalize this case as its used mainly for temporaries during calculations - //normalize(); - /* - F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); - mag -= 1.f; - mag = fabs(mag); - llassert(mag < 10.f*FP_MAG_THRESHOLD); - */ + //RN: don't normalize this case as its used mainly for temporaries during calculations + //normalize(); + /* + F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); + mag -= 1.f; + mag = fabs(mag); + llassert(mag < 10.f*FP_MAG_THRESHOLD); + */ } inline LLQuaternion::LLQuaternion(const F32 *q) { - mQ[VX] = q[VX]; - mQ[VY] = q[VY]; - mQ[VZ] = q[VZ]; - mQ[VS] = q[VW]; + mQ[VX] = q[VX]; + mQ[VY] = q[VY]; + mQ[VZ] = q[VZ]; + mQ[VS] = q[VW]; - normalize(); - /* - F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); - mag -= 1.f; - mag = fabs(mag); - llassert(mag < FP_MAG_THRESHOLD); - */ + normalize(); + /* + F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); + mag -= 1.f; + mag = fabs(mag); + llassert(mag < FP_MAG_THRESHOLD); + */ } inline void LLQuaternion::loadIdentity() { - mQ[VX] = 0.0f; - mQ[VY] = 0.0f; - mQ[VZ] = 0.0f; - mQ[VW] = 1.0f; + mQ[VX] = 0.0f; + mQ[VY] = 0.0f; + mQ[VZ] = 0.0f; + mQ[VW] = 1.0f; } inline bool LLQuaternion::isEqualEps(const LLQuaternion &quat, F32 epsilon) const { - return ( fabs(mQ[VX] - quat.mQ[VX]) < epsilon - && fabs(mQ[VY] - quat.mQ[VY]) < epsilon - && fabs(mQ[VZ] - quat.mQ[VZ]) < epsilon - && fabs(mQ[VS] - quat.mQ[VS]) < epsilon ); + return ( fabs(mQ[VX] - quat.mQ[VX]) < epsilon + && fabs(mQ[VY] - quat.mQ[VY]) < epsilon + && fabs(mQ[VZ] - quat.mQ[VZ]) < epsilon + && fabs(mQ[VS] - quat.mQ[VS]) < epsilon ); } inline bool LLQuaternion::isNotEqualEps(const LLQuaternion &quat, F32 epsilon) const { - return ( fabs(mQ[VX] - quat.mQ[VX]) > epsilon - || fabs(mQ[VY] - quat.mQ[VY]) > epsilon - || fabs(mQ[VZ] - quat.mQ[VZ]) > epsilon - || fabs(mQ[VS] - quat.mQ[VS]) > epsilon ); + return ( fabs(mQ[VX] - quat.mQ[VX]) > epsilon + || fabs(mQ[VY] - quat.mQ[VY]) > epsilon + || fabs(mQ[VZ] - quat.mQ[VZ]) > epsilon + || fabs(mQ[VS] - quat.mQ[VS]) > epsilon ); } -inline const LLQuaternion& LLQuaternion::set(F32 x, F32 y, F32 z, F32 w) +inline const LLQuaternion& LLQuaternion::set(F32 x, F32 y, F32 z, F32 w) { - mQ[VX] = x; - mQ[VY] = y; - mQ[VZ] = z; - mQ[VS] = w; - normalize(); - return (*this); + mQ[VX] = x; + mQ[VY] = y; + mQ[VZ] = z; + mQ[VS] = w; + normalize(); + return (*this); } -inline const LLQuaternion& LLQuaternion::set(const LLQuaternion &quat) +inline const LLQuaternion& LLQuaternion::set(const LLQuaternion &quat) { - mQ[VX] = quat.mQ[VX]; - mQ[VY] = quat.mQ[VY]; - mQ[VZ] = quat.mQ[VZ]; - mQ[VW] = quat.mQ[VW]; - normalize(); - return (*this); + mQ[VX] = quat.mQ[VX]; + mQ[VY] = quat.mQ[VY]; + mQ[VZ] = quat.mQ[VZ]; + mQ[VW] = quat.mQ[VW]; + normalize(); + return (*this); } -inline const LLQuaternion& LLQuaternion::set(const F32 *q) +inline const LLQuaternion& LLQuaternion::set(const F32 *q) { - mQ[VX] = q[VX]; - mQ[VY] = q[VY]; - mQ[VZ] = q[VZ]; - mQ[VS] = q[VW]; - normalize(); - return (*this); + mQ[VX] = q[VX]; + mQ[VY] = q[VY]; + mQ[VZ] = q[VZ]; + mQ[VS] = q[VW]; + normalize(); + return (*this); } // deprecated -inline const LLQuaternion& LLQuaternion::setQuatInit(F32 x, F32 y, F32 z, F32 w) +inline const LLQuaternion& LLQuaternion::setQuatInit(F32 x, F32 y, F32 z, F32 w) { - mQ[VX] = x; - mQ[VY] = y; - mQ[VZ] = z; - mQ[VS] = w; - normalize(); - return (*this); + mQ[VX] = x; + mQ[VY] = y; + mQ[VZ] = z; + mQ[VS] = w; + normalize(); + return (*this); } // deprecated -inline const LLQuaternion& LLQuaternion::setQuat(const LLQuaternion &quat) +inline const LLQuaternion& LLQuaternion::setQuat(const LLQuaternion &quat) { - mQ[VX] = quat.mQ[VX]; - mQ[VY] = quat.mQ[VY]; - mQ[VZ] = quat.mQ[VZ]; - mQ[VW] = quat.mQ[VW]; - normalize(); - return (*this); + mQ[VX] = quat.mQ[VX]; + mQ[VY] = quat.mQ[VY]; + mQ[VZ] = quat.mQ[VZ]; + mQ[VW] = quat.mQ[VW]; + normalize(); + return (*this); } // deprecated -inline const LLQuaternion& LLQuaternion::setQuat(const F32 *q) +inline const LLQuaternion& LLQuaternion::setQuat(const F32 *q) { - mQ[VX] = q[VX]; - mQ[VY] = q[VY]; - mQ[VZ] = q[VZ]; - mQ[VS] = q[VW]; - normalize(); - return (*this); + mQ[VX] = q[VX]; + mQ[VY] = q[VY]; + mQ[VZ] = q[VZ]; + mQ[VS] = q[VW]; + normalize(); + return (*this); } inline void LLQuaternion::getAngleAxis(F32* angle, F32* x, F32* y, F32* z) const { - F32 v = sqrtf(mQ[VX] * mQ[VX] + mQ[VY] * mQ[VY] + mQ[VZ] * mQ[VZ]); // length of the vector-component - if (v > FP_MAG_THRESHOLD) - { - F32 oomag = 1.0f / v; - F32 w = mQ[VW]; - if (w < 0.0f) - { - w = -w; // make VW positive - oomag = -oomag; // invert the axis - } - *x = mQ[VX] * oomag; // normalize the axis - *y = mQ[VY] * oomag; - *z = mQ[VZ] * oomag; - *angle = 2.0f * atan2f(v, w); // get the angle - } - else - { - *angle = 0.0f; // no rotation - *x = 0.0f; // around some dummy axis - *y = 0.0f; - *z = 1.0f; - } + F32 v = sqrtf(mQ[VX] * mQ[VX] + mQ[VY] * mQ[VY] + mQ[VZ] * mQ[VZ]); // length of the vector-component + if (v > FP_MAG_THRESHOLD) + { + F32 oomag = 1.0f / v; + F32 w = mQ[VW]; + if (w < 0.0f) + { + w = -w; // make VW positive + oomag = -oomag; // invert the axis + } + *x = mQ[VX] * oomag; // normalize the axis + *y = mQ[VY] * oomag; + *z = mQ[VZ] * oomag; + *angle = 2.0f * atan2f(v, w); // get the angle + } + else + { + *angle = 0.0f; // no rotation + *x = 0.0f; // around some dummy axis + *y = 0.0f; + *z = 1.0f; + } } inline const LLQuaternion& LLQuaternion::conjugate() { - mQ[VX] *= -1.f; - mQ[VY] *= -1.f; - mQ[VZ] *= -1.f; - return (*this); + mQ[VX] *= -1.f; + mQ[VY] *= -1.f; + mQ[VZ] *= -1.f; + return (*this); } inline const LLQuaternion& LLQuaternion::conjQuat() { - mQ[VX] *= -1.f; - mQ[VY] *= -1.f; - mQ[VZ] *= -1.f; - return (*this); + mQ[VX] *= -1.f; + mQ[VY] *= -1.f; + mQ[VZ] *= -1.f; + return (*this); } // Transpose inline const LLQuaternion& LLQuaternion::transpose() { - mQ[VX] *= -1.f; - mQ[VY] *= -1.f; - mQ[VZ] *= -1.f; - return (*this); + mQ[VX] *= -1.f; + mQ[VY] *= -1.f; + mQ[VZ] *= -1.f; + return (*this); } // deprecated inline const LLQuaternion& LLQuaternion::transQuat() { - mQ[VX] *= -1.f; - mQ[VY] *= -1.f; - mQ[VZ] *= -1.f; - return (*this); + mQ[VX] *= -1.f; + mQ[VY] *= -1.f; + mQ[VZ] *= -1.f; + return (*this); } -inline LLQuaternion operator+(const LLQuaternion &a, const LLQuaternion &b) +inline LLQuaternion operator+(const LLQuaternion &a, const LLQuaternion &b) { - return LLQuaternion( - a.mQ[VX] + b.mQ[VX], - a.mQ[VY] + b.mQ[VY], - a.mQ[VZ] + b.mQ[VZ], - a.mQ[VW] + b.mQ[VW] ); + return LLQuaternion( + a.mQ[VX] + b.mQ[VX], + a.mQ[VY] + b.mQ[VY], + a.mQ[VZ] + b.mQ[VZ], + a.mQ[VW] + b.mQ[VW] ); } -inline LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b) +inline LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b) { - return LLQuaternion( - a.mQ[VX] - b.mQ[VX], - a.mQ[VY] - b.mQ[VY], - a.mQ[VZ] - b.mQ[VZ], - a.mQ[VW] - b.mQ[VW] ); + return LLQuaternion( + a.mQ[VX] - b.mQ[VX], + a.mQ[VY] - b.mQ[VY], + a.mQ[VZ] - b.mQ[VZ], + a.mQ[VW] - b.mQ[VW] ); } -inline LLQuaternion operator-(const LLQuaternion &a) +inline LLQuaternion operator-(const LLQuaternion &a) { - return LLQuaternion( - -a.mQ[VX], - -a.mQ[VY], - -a.mQ[VZ], - -a.mQ[VW] ); + return LLQuaternion( + -a.mQ[VX], + -a.mQ[VY], + -a.mQ[VZ], + -a.mQ[VW] ); } -inline LLQuaternion operator*(F32 a, const LLQuaternion &q) +inline LLQuaternion operator*(F32 a, const LLQuaternion &q) { - return LLQuaternion( - a * q.mQ[VX], - a * q.mQ[VY], - a * q.mQ[VZ], - a * q.mQ[VW] ); + return LLQuaternion( + a * q.mQ[VX], + a * q.mQ[VY], + a * q.mQ[VZ], + a * q.mQ[VW] ); } -inline LLQuaternion operator*(const LLQuaternion &q, F32 a) +inline LLQuaternion operator*(const LLQuaternion &q, F32 a) { - return LLQuaternion( - a * q.mQ[VX], - a * q.mQ[VY], - a * q.mQ[VZ], - a * q.mQ[VW] ); + return LLQuaternion( + a * q.mQ[VX], + a * q.mQ[VY], + a * q.mQ[VZ], + a * q.mQ[VW] ); } -inline LLQuaternion operator~(const LLQuaternion &a) +inline LLQuaternion operator~(const LLQuaternion &a) { - LLQuaternion q(a); - q.conjQuat(); - return q; + LLQuaternion q(a); + q.conjQuat(); + return q; } -inline bool LLQuaternion::operator==(const LLQuaternion &b) const +inline bool LLQuaternion::operator==(const LLQuaternion &b) const { - return ( (mQ[VX] == b.mQ[VX]) - &&(mQ[VY] == b.mQ[VY]) - &&(mQ[VZ] == b.mQ[VZ]) - &&(mQ[VS] == b.mQ[VS])); + return ( (mQ[VX] == b.mQ[VX]) + &&(mQ[VY] == b.mQ[VY]) + &&(mQ[VZ] == b.mQ[VZ]) + &&(mQ[VS] == b.mQ[VS])); } -inline bool LLQuaternion::operator!=(const LLQuaternion &b) const +inline bool LLQuaternion::operator!=(const LLQuaternion &b) const { - return ( (mQ[VX] != b.mQ[VX]) - ||(mQ[VY] != b.mQ[VY]) - ||(mQ[VZ] != b.mQ[VZ]) - ||(mQ[VS] != b.mQ[VS])); + return ( (mQ[VX] != b.mQ[VX]) + ||(mQ[VY] != b.mQ[VY]) + ||(mQ[VZ] != b.mQ[VZ]) + ||(mQ[VS] != b.mQ[VS])); } -inline const LLQuaternion& operator*=(LLQuaternion &a, const LLQuaternion &b) +inline const LLQuaternion& operator*=(LLQuaternion &a, const LLQuaternion &b) { #if 1 - LLQuaternion q( - b.mQ[3] * a.mQ[0] + b.mQ[0] * a.mQ[3] + b.mQ[1] * a.mQ[2] - b.mQ[2] * a.mQ[1], - b.mQ[3] * a.mQ[1] + b.mQ[1] * a.mQ[3] + b.mQ[2] * a.mQ[0] - b.mQ[0] * a.mQ[2], - b.mQ[3] * a.mQ[2] + b.mQ[2] * a.mQ[3] + b.mQ[0] * a.mQ[1] - b.mQ[1] * a.mQ[0], - b.mQ[3] * a.mQ[3] - b.mQ[0] * a.mQ[0] - b.mQ[1] * a.mQ[1] - b.mQ[2] * a.mQ[2] - ); - a = q; + LLQuaternion q( + b.mQ[3] * a.mQ[0] + b.mQ[0] * a.mQ[3] + b.mQ[1] * a.mQ[2] - b.mQ[2] * a.mQ[1], + b.mQ[3] * a.mQ[1] + b.mQ[1] * a.mQ[3] + b.mQ[2] * a.mQ[0] - b.mQ[0] * a.mQ[2], + b.mQ[3] * a.mQ[2] + b.mQ[2] * a.mQ[3] + b.mQ[0] * a.mQ[1] - b.mQ[1] * a.mQ[0], + b.mQ[3] * a.mQ[3] - b.mQ[0] * a.mQ[0] - b.mQ[1] * a.mQ[1] - b.mQ[2] * a.mQ[2] + ); + a = q; #else - a = a * b; + a = a * b; #endif - return a; + return a; } const F32 ONE_PART_IN_A_MILLION = 0.000001f; -inline F32 LLQuaternion::normalize() -{ - F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); - - if (mag > FP_MAG_THRESHOLD) - { - // Floating point error can prevent some quaternions from achieving - // exact unity length. When trying to renormalize such quaternions we - // can oscillate between multiple quantized states. To prevent such - // drifts we only renomalize if the length is far enough from unity. - if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION) - { - F32 oomag = 1.f/mag; - mQ[VX] *= oomag; - mQ[VY] *= oomag; - mQ[VZ] *= oomag; - mQ[VS] *= oomag; - } - } - else - { - // we were given a very bad quaternion so we set it to identity - mQ[VX] = 0.f; - mQ[VY] = 0.f; - mQ[VZ] = 0.f; - mQ[VS] = 1.f; - } - - return mag; +inline F32 LLQuaternion::normalize() +{ + F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); + + if (mag > FP_MAG_THRESHOLD) + { + // Floating point error can prevent some quaternions from achieving + // exact unity length. When trying to renormalize such quaternions we + // can oscillate between multiple quantized states. To prevent such + // drifts we only renomalize if the length is far enough from unity. + if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION) + { + F32 oomag = 1.f/mag; + mQ[VX] *= oomag; + mQ[VY] *= oomag; + mQ[VZ] *= oomag; + mQ[VS] *= oomag; + } + } + else + { + // we were given a very bad quaternion so we set it to identity + mQ[VX] = 0.f; + mQ[VY] = 0.f; + mQ[VZ] = 0.f; + mQ[VS] = 1.f; + } + + return mag; } // deprecated -inline F32 LLQuaternion::normQuat() -{ - F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); - - if (mag > FP_MAG_THRESHOLD) - { - if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION) - { - // only renormalize if length not close enough to 1.0 already - F32 oomag = 1.f/mag; - mQ[VX] *= oomag; - mQ[VY] *= oomag; - mQ[VZ] *= oomag; - mQ[VS] *= oomag; - } - } - else - { - mQ[VX] = 0.f; - mQ[VY] = 0.f; - mQ[VZ] = 0.f; - mQ[VS] = 1.f; - } - - return mag; +inline F32 LLQuaternion::normQuat() +{ + F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); + + if (mag > FP_MAG_THRESHOLD) + { + if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION) + { + // only renormalize if length not close enough to 1.0 already + F32 oomag = 1.f/mag; + mQ[VX] *= oomag; + mQ[VY] *= oomag; + mQ[VZ] *= oomag; + mQ[VS] *= oomag; + } + } + else + { + mQ[VX] = 0.f; + mQ[VY] = 0.f; + mQ[VZ] = 0.f; + mQ[VS] = 1.f; + } + + return mag; } LLQuaternion::Order StringToOrder( const char *str ); @@ -565,11 +565,11 @@ LLQuaternion::Order StringToOrder( const char *str ); // --------------------- // A quaternion is a point in 4-dimensional complex space. // Q = { Qx, Qy, Qz, Qw } -// +// // // Why Quaternions? // ---------------- -// The set of quaternions that make up the the 4-D unit sphere +// The set of quaternions that make up the the 4-D unit sphere // can be mapped to the set of all rotations in 3-D space. Sometimes // it is easier to describe/manipulate rotations in quaternion space // than rotation-matrix space. @@ -580,22 +580,22 @@ LLQuaternion::Order StringToOrder( const char *str ); // In order to take advantage of quaternions we need to know how to // go from rotation-matricies to quaternions and back. We also have // to agree what variety of rotations we're generating. -// -// Consider the equation... v' = v * R +// +// Consider the equation... v' = v * R // // There are two ways to think about rotations of vectors. // 1) v' is the same vector in a different reference frame // 2) v' is a new vector in the same reference frame // // bookmark -- which way are we using? -// -// +// +// // Quaternion from Angle-Axis: // --------------------------- -// Suppose we wanted to represent a rotation of some angle (theta) +// Suppose we wanted to represent a rotation of some angle (theta) // about some axis ({Ax, Ay, Az})... // -// axis of rotation = {Ax, Ay, Az} +// axis of rotation = {Ax, Ay, Az} // angle_of_rotation = theta // // s = sin(0.5 * theta) diff --git a/indra/llmath/llquaternion2.h b/indra/llmath/llquaternion2.h index fd9c0cf3ab..902bfb7134 100644 --- a/indra/llmath/llquaternion2.h +++ b/indra/llmath/llquaternion2.h @@ -1,31 +1,31 @@ -/** +/** * @file llquaternion2.h * @brief LLQuaternion2 class header file - SIMD-enabled quaternion class * * $LicenseInfo:firstyear=2010&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ -#ifndef LL_QUATERNION2_H -#define LL_QUATERNION2_H +#ifndef LL_QUATERNION2_H +#define LL_QUATERNION2_H ///////////////////////////// // LLQuaternion2 @@ -44,61 +44,61 @@ class LLQuaternion2 { public: - ////////////////////////// - // Ctors - ////////////////////////// - - // Ctor - LLQuaternion2() {} + ////////////////////////// + // Ctors + ////////////////////////// + + // Ctor + LLQuaternion2() {} + + // Ctor from LLQuaternion + explicit LLQuaternion2( const class LLQuaternion& quat ); - // Ctor from LLQuaternion - explicit LLQuaternion2( const class LLQuaternion& quat ); + ////////////////////////// + // Get/Set + ////////////////////////// - ////////////////////////// - // Get/Set - ////////////////////////// + // Load from an LLQuaternion + inline void operator=( const LLQuaternion& quat ) + { + mQ.loadua( quat.mQ ); + } - // Load from an LLQuaternion - inline void operator=( const LLQuaternion& quat ) - { - mQ.loadua( quat.mQ ); - } + // Return the internal LLVector4a representation of the quaternion + inline const LLVector4a& getVector4a() const; + inline LLVector4a& getVector4aRw(); - // Return the internal LLVector4a representation of the quaternion - inline const LLVector4a& getVector4a() const; - inline LLVector4a& getVector4aRw(); + ///////////////////////// + // Quaternion modification + ///////////////////////// - ///////////////////////// - // Quaternion modification - ///////////////////////// - - // Set this quaternion to the conjugate of src - inline void setConjugate(const LLQuaternion2& src); + // Set this quaternion to the conjugate of src + inline void setConjugate(const LLQuaternion2& src); - // Renormalizes the quaternion. Assumes it has nonzero length. - inline void normalize(); + // Renormalizes the quaternion. Assumes it has nonzero length. + inline void normalize(); - // Quantize this quaternion to 8 bit precision - inline void quantize8(); + // Quantize this quaternion to 8 bit precision + inline void quantize8(); - // Quantize this quaternion to 16 bit precision - inline void quantize16(); + // Quantize this quaternion to 16 bit precision + inline void quantize16(); - ///////////////////////// - // Quaternion inspection - ///////////////////////// + ///////////////////////// + // Quaternion inspection + ///////////////////////// - // Return true if this quaternion is equal to 'rhs'. - // Note! Quaternions exhibit "double-cover", so any rotation has two equally valid - // quaternion representations and they will NOT compare equal. - inline bool equals(const LLQuaternion2& rhs, F32 tolerance = F_APPROXIMATELY_ZERO ) const; + // Return true if this quaternion is equal to 'rhs'. + // Note! Quaternions exhibit "double-cover", so any rotation has two equally valid + // quaternion representations and they will NOT compare equal. + inline bool equals(const LLQuaternion2& rhs, F32 tolerance = F_APPROXIMATELY_ZERO ) const; - // Return true if all components are finite and the quaternion is normalized - inline bool isOkRotation() const; + // Return true if all components are finite and the quaternion is normalized + inline bool isOkRotation() const; protected: - LLVector4a mQ; + LLVector4a mQ; }; diff --git a/indra/llmath/llquaternion2.inl b/indra/llmath/llquaternion2.inl index 2a6987552d..ce5ed73926 100644 --- a/indra/llmath/llquaternion2.inl +++ b/indra/llmath/llquaternion2.inl @@ -1,25 +1,25 @@ -/** +/** * @file llquaternion2.inl * @brief LLQuaternion2 inline definitions * * $LicenseInfo:firstyear=2010&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -32,7 +32,7 @@ static const LLQuad LL_V4A_MINUS_ONE = {-1.f, -1.f, -1.f, -1.f}; // Ctor from LLQuaternion inline LLQuaternion2::LLQuaternion2( const LLQuaternion& quat ) { - mQ.set(quat.mQ[VX], quat.mQ[VY], quat.mQ[VZ], quat.mQ[VW]); + mQ.set(quat.mQ[VX], quat.mQ[VY], quat.mQ[VZ], quat.mQ[VW]); } ////////////////////////// @@ -42,12 +42,12 @@ inline LLQuaternion2::LLQuaternion2( const LLQuaternion& quat ) // Return the internal LLVector4a representation of the quaternion inline const LLVector4a& LLQuaternion2::getVector4a() const { - return mQ; + return mQ; } inline LLVector4a& LLQuaternion2::getVector4aRw() { - return mQ; + return mQ; } ///////////////////////// @@ -57,28 +57,28 @@ inline LLVector4a& LLQuaternion2::getVector4aRw() // Set this quaternion to the conjugate of src inline void LLQuaternion2::setConjugate(const LLQuaternion2& src) { - static LL_ALIGN_16( const U32 F_QUAT_INV_MASK_4A[4] ) = { 0x80000000, 0x80000000, 0x80000000, 0x00000000 }; - mQ = _mm_xor_ps(src.mQ, *reinterpret_cast<const LLQuad*>(&F_QUAT_INV_MASK_4A)); + static LL_ALIGN_16( const U32 F_QUAT_INV_MASK_4A[4] ) = { 0x80000000, 0x80000000, 0x80000000, 0x00000000 }; + mQ = _mm_xor_ps(src.mQ, *reinterpret_cast<const LLQuad*>(&F_QUAT_INV_MASK_4A)); } // Renormalizes the quaternion. Assumes it has nonzero length. inline void LLQuaternion2::normalize() { - mQ.normalize4(); + mQ.normalize4(); } // Quantize this quaternion to 8 bit precision inline void LLQuaternion2::quantize8() { - mQ.quantize8( LL_V4A_MINUS_ONE, LL_V4A_PLUS_ONE ); - normalize(); + mQ.quantize8( LL_V4A_MINUS_ONE, LL_V4A_PLUS_ONE ); + normalize(); } // Quantize this quaternion to 16 bit precision inline void LLQuaternion2::quantize16() { - mQ.quantize16( LL_V4A_MINUS_ONE, LL_V4A_PLUS_ONE ); - normalize(); + mQ.quantize16( LL_V4A_MINUS_ONE, LL_V4A_PLUS_ONE ); + normalize(); } @@ -86,17 +86,17 @@ inline void LLQuaternion2::quantize16() // Quaternion inspection ///////////////////////// -// Return true if this quaternion is equal to 'rhs'. +// Return true if this quaternion is equal to 'rhs'. // Note! Quaternions exhibit "double-cover", so any rotation has two equally valid // quaternion representations and they will NOT compare equal. inline bool LLQuaternion2::equals(const LLQuaternion2 &rhs, F32 tolerance/* = F_APPROXIMATELY_ZERO*/) const { - return mQ.equals4(rhs.mQ, tolerance); + return mQ.equals4(rhs.mQ, tolerance); } // Return true if all components are finite and the quaternion is normalized inline bool LLQuaternion2::isOkRotation() const { - return mQ.isFinite4() && mQ.isNormalized4(); + return mQ.isFinite4() && mQ.isNormalized4(); } diff --git a/indra/llmath/llrect.cpp b/indra/llmath/llrect.cpp index 4083c99768..2a40dc69dd 100644 --- a/indra/llmath/llrect.cpp +++ b/indra/llmath/llrect.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llrect.cpp * @brief LLRect class implementation * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ diff --git a/indra/llmath/llrect.h b/indra/llmath/llrect.h index 25af04be06..317578da06 100644 --- a/indra/llmath/llrect.h +++ b/indra/llmath/llrect.h @@ -1,25 +1,25 @@ -/** +/** * @file llrect.h * @brief A rectangle in GL coordinates, with bottom,left = 0,0 * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -36,258 +36,258 @@ template <class Type> class LLRectBase { public: - typedef Type tCoordType; - Type mLeft; - Type mTop; - Type mRight; - Type mBottom; - - // Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect - Type getWidth() const { return mRight - mLeft; } - Type getHeight() const { return mTop - mBottom; } - Type getCenterX() const { return (mLeft + mRight) / 2; } - Type getCenterY() const { return (mTop + mBottom) / 2; } - - LLRectBase(): mLeft(0), mTop(0), mRight(0), mBottom(0) - {} - - LLRectBase(const LLRectBase &r): - mLeft(r.mLeft), mTop(r.mTop), mRight(r.mRight), mBottom(r.mBottom) - {} - - LLRectBase(Type left, Type top, Type right, Type bottom): - mLeft(left), mTop(top), mRight(right), mBottom(bottom) - {} - - explicit LLRectBase(const LLSD& sd) - { - setValue(sd); - } - - void setValue(const LLSD& sd) - { - mLeft = (Type)sd[0].asInteger(); - mTop = (Type)sd[1].asInteger(); - mRight = (Type)sd[2].asInteger(); - mBottom = (Type)sd[3].asInteger(); - } - - LLSD getValue() const - { - LLSD ret; - ret[0] = mLeft; - ret[1] = mTop; - ret[2] = mRight; - ret[3] = mBottom; - return ret; - } - - // Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect - bool pointInRect(const Type x, const Type y) const - { - return mLeft <= x && x < mRight && - mBottom <= y && y < mTop; - } - - //// Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect - bool localPointInRect(const Type x, const Type y) const - { - return 0 <= x && x < getWidth() && - 0 <= y && y < getHeight(); - } - - void clampPointToRect(Type& x, Type& y) - { - x = llclamp(x, mLeft, mRight); - y = llclamp(y, mBottom, mTop); - } - - void clipPointToRect(const Type start_x, const Type start_y, Type& end_x, Type& end_y) - { - if (!pointInRect(start_x, start_y)) - { - return; - } - Type clip_x = 0; - Type clip_y = 0; - Type delta_x = end_x - start_x; - Type delta_y = end_y - start_y; - if (end_x > mRight) clip_x = end_x - mRight; - if (end_x < mLeft) clip_x = end_x - mLeft; - if (end_y > mTop) clip_y = end_y - mTop; - if (end_y < mBottom) clip_y = end_y - mBottom; - // clip_? and delta_? should have same sign, since starting point is in rect - // so ratios will be positive + typedef Type tCoordType; + Type mLeft; + Type mTop; + Type mRight; + Type mBottom; + + // Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect + Type getWidth() const { return mRight - mLeft; } + Type getHeight() const { return mTop - mBottom; } + Type getCenterX() const { return (mLeft + mRight) / 2; } + Type getCenterY() const { return (mTop + mBottom) / 2; } + + LLRectBase(): mLeft(0), mTop(0), mRight(0), mBottom(0) + {} + + LLRectBase(const LLRectBase &r): + mLeft(r.mLeft), mTop(r.mTop), mRight(r.mRight), mBottom(r.mBottom) + {} + + LLRectBase(Type left, Type top, Type right, Type bottom): + mLeft(left), mTop(top), mRight(right), mBottom(bottom) + {} + + explicit LLRectBase(const LLSD& sd) + { + setValue(sd); + } + + void setValue(const LLSD& sd) + { + mLeft = (Type)sd[0].asInteger(); + mTop = (Type)sd[1].asInteger(); + mRight = (Type)sd[2].asInteger(); + mBottom = (Type)sd[3].asInteger(); + } + + LLSD getValue() const + { + LLSD ret; + ret[0] = mLeft; + ret[1] = mTop; + ret[2] = mRight; + ret[3] = mBottom; + return ret; + } + + // Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect + bool pointInRect(const Type x, const Type y) const + { + return mLeft <= x && x < mRight && + mBottom <= y && y < mTop; + } + + //// Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect + bool localPointInRect(const Type x, const Type y) const + { + return 0 <= x && x < getWidth() && + 0 <= y && y < getHeight(); + } + + void clampPointToRect(Type& x, Type& y) + { + x = llclamp(x, mLeft, mRight); + y = llclamp(y, mBottom, mTop); + } + + void clipPointToRect(const Type start_x, const Type start_y, Type& end_x, Type& end_y) + { + if (!pointInRect(start_x, start_y)) + { + return; + } + Type clip_x = 0; + Type clip_y = 0; + Type delta_x = end_x - start_x; + Type delta_y = end_y - start_y; + if (end_x > mRight) clip_x = end_x - mRight; + if (end_x < mLeft) clip_x = end_x - mLeft; + if (end_y > mTop) clip_y = end_y - mTop; + if (end_y < mBottom) clip_y = end_y - mBottom; + // clip_? and delta_? should have same sign, since starting point is in rect + // so ratios will be positive F32 ratio_x = 0; F32 ratio_y = 0; if (delta_x != 0) ratio_x = ((F32)clip_x / (F32)delta_x); if (delta_y != 0) ratio_y = ((F32)clip_y / (F32)delta_y); - if (ratio_x > ratio_y) - { - // clip along x direction - end_x -= (Type)(clip_x); - end_y -= (Type)(delta_y * ratio_x); - } - else - { - // clip along y direction - end_x -= (Type)(delta_x * ratio_y); - end_y -= (Type)clip_y; - } - } - - // Note: Does NOT follow GL_QUAD conventions: the top and right edges ARE considered part of the rect - // returns true if any part of rect is is inside this LLRect - bool overlaps(const LLRectBase& rect) const - { - return !(mLeft > rect.mRight - || mRight < rect.mLeft - || mBottom > rect.mTop - || mTop < rect.mBottom); - } - - bool contains(const LLRectBase& rect) const - { - return mLeft <= rect.mLeft - && mRight >= rect.mRight - && mBottom <= rect.mBottom - && mTop >= rect.mTop; - } - - LLRectBase& set(Type left, Type top, Type right, Type bottom) - { - mLeft = left; - mTop = top; - mRight = right; - mBottom = bottom; - return *this; - } - - // Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect - LLRectBase& setOriginAndSize( Type left, Type bottom, Type width, Type height) - { - mLeft = left; - mTop = bottom + height; - mRight = left + width; - mBottom = bottom; - return *this; - } - - // Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect - LLRectBase& setLeftTopAndSize( Type left, Type top, Type width, Type height) - { - mLeft = left; - mTop = top; - mRight = left + width; - mBottom = top - height; - return *this; - } - - LLRectBase& setCenterAndSize(Type x, Type y, Type width, Type height) - { - // width and height could be odd, so favor top, right with extra pixel - mLeft = x - width/2; - mBottom = y - height/2; - mTop = mBottom + height; - mRight = mLeft + width; - return *this; - } - - - LLRectBase& translate(Type horiz, Type vertical) - { - mLeft += horiz; - mRight += horiz; - mTop += vertical; - mBottom += vertical; - return *this; - } - - LLRectBase& stretch( Type dx, Type dy) - { - mLeft -= dx; - mRight += dx; - mTop += dy; - mBottom -= dy; - return makeValid(); - } - - LLRectBase& stretch( Type delta ) - { - stretch(delta, delta); - return *this; - } - - LLRectBase& makeValid() - { - mLeft = llmin(mLeft, mRight); - mBottom = llmin(mBottom, mTop); - return *this; - } - - bool isValid() const - { - return mLeft <= mRight && mBottom <= mTop; - } - - bool isEmpty() const - { - return mLeft == mRight || mBottom == mTop; - } - - bool notEmpty() const - { - return !isEmpty(); - } - - void unionWith(const LLRectBase &other) - { - mLeft = llmin(mLeft, other.mLeft); - mRight = llmax(mRight, other.mRight); - mBottom = llmin(mBottom, other.mBottom); - mTop = llmax(mTop, other.mTop); - } - - void intersectWith(const LLRectBase &other) - { - mLeft = llmax(mLeft, other.mLeft); - mRight = llmin(mRight, other.mRight); - mBottom = llmax(mBottom, other.mBottom); - mTop = llmin(mTop, other.mTop); - if (mLeft > mRight) - { - mLeft = mRight; - } - if (mBottom > mTop) - { - mBottom = mTop; - } - } - - friend std::ostream &operator<<(std::ostream &s, const LLRectBase &rect) - { - s << "{ L " << rect.mLeft << " B " << rect.mBottom - << " W " << rect.getWidth() << " H " << rect.getHeight() << " }"; - return s; - } - - bool operator==(const LLRectBase &b) const - { - return ((mLeft == b.mLeft) && - (mTop == b.mTop) && - (mRight == b.mRight) && - (mBottom == b.mBottom)); - } - - bool operator!=(const LLRectBase &b) const - { - return ((mLeft != b.mLeft) || - (mTop != b.mTop) || - (mRight != b.mRight) || - (mBottom != b.mBottom)); - } - - static LLRectBase<Type> null; + if (ratio_x > ratio_y) + { + // clip along x direction + end_x -= (Type)(clip_x); + end_y -= (Type)(delta_y * ratio_x); + } + else + { + // clip along y direction + end_x -= (Type)(delta_x * ratio_y); + end_y -= (Type)clip_y; + } + } + + // Note: Does NOT follow GL_QUAD conventions: the top and right edges ARE considered part of the rect + // returns true if any part of rect is is inside this LLRect + bool overlaps(const LLRectBase& rect) const + { + return !(mLeft > rect.mRight + || mRight < rect.mLeft + || mBottom > rect.mTop + || mTop < rect.mBottom); + } + + bool contains(const LLRectBase& rect) const + { + return mLeft <= rect.mLeft + && mRight >= rect.mRight + && mBottom <= rect.mBottom + && mTop >= rect.mTop; + } + + LLRectBase& set(Type left, Type top, Type right, Type bottom) + { + mLeft = left; + mTop = top; + mRight = right; + mBottom = bottom; + return *this; + } + + // Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect + LLRectBase& setOriginAndSize( Type left, Type bottom, Type width, Type height) + { + mLeft = left; + mTop = bottom + height; + mRight = left + width; + mBottom = bottom; + return *this; + } + + // Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect + LLRectBase& setLeftTopAndSize( Type left, Type top, Type width, Type height) + { + mLeft = left; + mTop = top; + mRight = left + width; + mBottom = top - height; + return *this; + } + + LLRectBase& setCenterAndSize(Type x, Type y, Type width, Type height) + { + // width and height could be odd, so favor top, right with extra pixel + mLeft = x - width/2; + mBottom = y - height/2; + mTop = mBottom + height; + mRight = mLeft + width; + return *this; + } + + + LLRectBase& translate(Type horiz, Type vertical) + { + mLeft += horiz; + mRight += horiz; + mTop += vertical; + mBottom += vertical; + return *this; + } + + LLRectBase& stretch( Type dx, Type dy) + { + mLeft -= dx; + mRight += dx; + mTop += dy; + mBottom -= dy; + return makeValid(); + } + + LLRectBase& stretch( Type delta ) + { + stretch(delta, delta); + return *this; + } + + LLRectBase& makeValid() + { + mLeft = llmin(mLeft, mRight); + mBottom = llmin(mBottom, mTop); + return *this; + } + + bool isValid() const + { + return mLeft <= mRight && mBottom <= mTop; + } + + bool isEmpty() const + { + return mLeft == mRight || mBottom == mTop; + } + + bool notEmpty() const + { + return !isEmpty(); + } + + void unionWith(const LLRectBase &other) + { + mLeft = llmin(mLeft, other.mLeft); + mRight = llmax(mRight, other.mRight); + mBottom = llmin(mBottom, other.mBottom); + mTop = llmax(mTop, other.mTop); + } + + void intersectWith(const LLRectBase &other) + { + mLeft = llmax(mLeft, other.mLeft); + mRight = llmin(mRight, other.mRight); + mBottom = llmax(mBottom, other.mBottom); + mTop = llmin(mTop, other.mTop); + if (mLeft > mRight) + { + mLeft = mRight; + } + if (mBottom > mTop) + { + mBottom = mTop; + } + } + + friend std::ostream &operator<<(std::ostream &s, const LLRectBase &rect) + { + s << "{ L " << rect.mLeft << " B " << rect.mBottom + << " W " << rect.getWidth() << " H " << rect.getHeight() << " }"; + return s; + } + + bool operator==(const LLRectBase &b) const + { + return ((mLeft == b.mLeft) && + (mTop == b.mTop) && + (mRight == b.mRight) && + (mBottom == b.mBottom)); + } + + bool operator!=(const LLRectBase &b) const + { + return ((mLeft != b.mLeft) || + (mTop != b.mTop) || + (mRight != b.mRight) || + (mBottom != b.mBottom)); + } + + static LLRectBase<Type> null; }; template <class Type> LLRectBase<Type> LLRectBase<Type>::null(0,0,0,0); diff --git a/indra/llmath/llrigginginfo.cpp b/indra/llmath/llrigginginfo.cpp index 0de07950c1..23dbddd78e 100644 --- a/indra/llmath/llrigginginfo.cpp +++ b/indra/llmath/llrigginginfo.cpp @@ -46,7 +46,7 @@ void LLJointRiggingInfo::setIsRiggedTo(bool val) { mIsRiggedTo = val; } - + LLVector4a *LLJointRiggingInfo::getRiggedExtents() { return mRiggedExtents; @@ -120,8 +120,8 @@ void LLJointRiggingInfoTab::clear() void showDetails(const LLJointRiggingInfoTab& src, const std::string& str) { - S32 count_rigged = 0; - S32 count_box = 0; + S32 count_rigged = 0; + S32 count_box = 0; LLVector4a zero_vec; zero_vec.clear(); for (S32 i=0; i<src.size(); i++) diff --git a/indra/llmath/llrigginginfo.h b/indra/llmath/llrigginginfo.h index 059c6ae082..fb550d013f 100644 --- a/indra/llmath/llrigginginfo.h +++ b/indra/llmath/llrigginginfo.h @@ -27,8 +27,8 @@ // Stores information related to associated rigged mesh vertices // This lives in llmath because llvolume lives in llmath. -#ifndef LL_LLRIGGINGINFO_H -#define LL_LLRIGGINGINFO_H +#ifndef LL_LLRIGGINGINFO_H +#define LL_LLRIGGINGINFO_H #include "llvector4a.h" @@ -46,7 +46,7 @@ public: void merge(const LLJointRiggingInfo& other); private: - LLVector4a mRiggedExtents[2]; + LLVector4a mRiggedExtents[2]; bool mIsRiggedTo; }; diff --git a/indra/llmath/llsdutil_math.cpp b/indra/llmath/llsdutil_math.cpp index 51e5e3764f..0ea1a9c77a 100644 --- a/indra/llmath/llsdutil_math.cpp +++ b/indra/llmath/llsdutil_math.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llsdutil_math.cpp * @author Phoenix * @date 2006-05-24 @@ -7,21 +7,21 @@ * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,12 +38,12 @@ #include "v4color.h" #if LL_WINDOWS -# define WIN32_LEAN_AND_MEAN -# include <winsock2.h> // for htonl +# define WIN32_LEAN_AND_MEAN +# include <winsock2.h> // for htonl #elif LL_LINUX -# include <netinet/in.h> +# include <netinet/in.h> #elif LL_DARWIN -# include <arpa/inet.h> +# include <arpa/inet.h> #endif #include "llsdserialize.h" @@ -51,114 +51,114 @@ // vector3 LLSD ll_sd_from_vector3(const LLVector3& vec) { - LLSD rv; - rv.append((F64)vec.mV[VX]); - rv.append((F64)vec.mV[VY]); - rv.append((F64)vec.mV[VZ]); - return rv; + LLSD rv; + rv.append((F64)vec.mV[VX]); + rv.append((F64)vec.mV[VY]); + rv.append((F64)vec.mV[VZ]); + return rv; } LLVector3 ll_vector3_from_sd(const LLSD& sd, S32 start_index) { - LLVector3 rv; - rv.mV[VX] = (F32)sd[start_index].asReal(); - rv.mV[VY] = (F32)sd[++start_index].asReal(); - rv.mV[VZ] = (F32)sd[++start_index].asReal(); - return rv; + LLVector3 rv; + rv.mV[VX] = (F32)sd[start_index].asReal(); + rv.mV[VY] = (F32)sd[++start_index].asReal(); + rv.mV[VZ] = (F32)sd[++start_index].asReal(); + return rv; } // vector4 LLSD ll_sd_from_vector4(const LLVector4& vec) { - LLSD rv; - rv.append((F64)vec.mV[VX]); - rv.append((F64)vec.mV[VY]); - rv.append((F64)vec.mV[VZ]); - rv.append((F64)vec.mV[VW]); - return rv; + LLSD rv; + rv.append((F64)vec.mV[VX]); + rv.append((F64)vec.mV[VY]); + rv.append((F64)vec.mV[VZ]); + rv.append((F64)vec.mV[VW]); + return rv; } LLVector4 ll_vector4_from_sd(const LLSD& sd, S32 start_index) { - LLVector4 rv; - rv.mV[VX] = (F32)sd[start_index].asReal(); - rv.mV[VY] = (F32)sd[++start_index].asReal(); - rv.mV[VZ] = (F32)sd[++start_index].asReal(); - rv.mV[VW] = (F32)sd[++start_index].asReal(); - return rv; + LLVector4 rv; + rv.mV[VX] = (F32)sd[start_index].asReal(); + rv.mV[VY] = (F32)sd[++start_index].asReal(); + rv.mV[VZ] = (F32)sd[++start_index].asReal(); + rv.mV[VW] = (F32)sd[++start_index].asReal(); + return rv; } // vector3d LLSD ll_sd_from_vector3d(const LLVector3d& vec) { - LLSD rv; - rv.append(vec.mdV[VX]); - rv.append(vec.mdV[VY]); - rv.append(vec.mdV[VZ]); - return rv; + LLSD rv; + rv.append(vec.mdV[VX]); + rv.append(vec.mdV[VY]); + rv.append(vec.mdV[VZ]); + return rv; } LLVector3d ll_vector3d_from_sd(const LLSD& sd, S32 start_index) { - LLVector3d rv; - rv.mdV[VX] = sd[start_index].asReal(); - rv.mdV[VY] = sd[++start_index].asReal(); - rv.mdV[VZ] = sd[++start_index].asReal(); - return rv; + LLVector3d rv; + rv.mdV[VX] = sd[start_index].asReal(); + rv.mdV[VY] = sd[++start_index].asReal(); + rv.mdV[VZ] = sd[++start_index].asReal(); + return rv; } //vector2 LLSD ll_sd_from_vector2(const LLVector2& vec) { - LLSD rv; - rv.append((F64)vec.mV[VX]); - rv.append((F64)vec.mV[VY]); - return rv; + LLSD rv; + rv.append((F64)vec.mV[VX]); + rv.append((F64)vec.mV[VY]); + return rv; } LLVector2 ll_vector2_from_sd(const LLSD& sd) { - LLVector2 rv; - rv.mV[VX] = (F32)sd[0].asReal(); - rv.mV[VY] = (F32)sd[1].asReal(); - return rv; + LLVector2 rv; + rv.mV[VX] = (F32)sd[0].asReal(); + rv.mV[VY] = (F32)sd[1].asReal(); + return rv; } // Quaternion LLSD ll_sd_from_quaternion(const LLQuaternion& quat) { - LLSD rv; - rv.append((F64)quat.mQ[VX]); - rv.append((F64)quat.mQ[VY]); - rv.append((F64)quat.mQ[VZ]); - rv.append((F64)quat.mQ[VW]); - return rv; + LLSD rv; + rv.append((F64)quat.mQ[VX]); + rv.append((F64)quat.mQ[VY]); + rv.append((F64)quat.mQ[VZ]); + rv.append((F64)quat.mQ[VW]); + return rv; } LLQuaternion ll_quaternion_from_sd(const LLSD& sd) { - LLQuaternion quat; - quat.mQ[VX] = (F32)sd[0].asReal(); - quat.mQ[VY] = (F32)sd[1].asReal(); - quat.mQ[VZ] = (F32)sd[2].asReal(); - quat.mQ[VW] = (F32)sd[3].asReal(); - return quat; + LLQuaternion quat; + quat.mQ[VX] = (F32)sd[0].asReal(); + quat.mQ[VY] = (F32)sd[1].asReal(); + quat.mQ[VZ] = (F32)sd[2].asReal(); + quat.mQ[VW] = (F32)sd[3].asReal(); + return quat; } // color4 LLSD ll_sd_from_color4(const LLColor4& c) { - LLSD rv; - rv.append(c.mV[0]); - rv.append(c.mV[1]); - rv.append(c.mV[2]); - rv.append(c.mV[3]); - return rv; + LLSD rv; + rv.append(c.mV[0]); + rv.append(c.mV[1]); + rv.append(c.mV[2]); + rv.append(c.mV[3]); + return rv; } LLColor4 ll_color4_from_sd(const LLSD& sd) { - LLColor4 c; - c.setValue(sd); - return c; + LLColor4 c; + c.setValue(sd); + return c; } diff --git a/indra/llmath/llsdutil_math.h b/indra/llmath/llsdutil_math.h index 0ea78cd231..8f8852f7c3 100644 --- a/indra/llmath/llsdutil_math.h +++ b/indra/llmath/llsdutil_math.h @@ -1,4 +1,4 @@ -/** +/** * @file llsdutil_math.h * @author Brad * @date 2009-05-19 @@ -7,21 +7,21 @@ * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ diff --git a/indra/llmath/llsimdmath.h b/indra/llmath/llsimdmath.h index 54a275633f..40953dc2e8 100644 --- a/indra/llmath/llsimdmath.h +++ b/indra/llmath/llsimdmath.h @@ -1,31 +1,31 @@ -/** +/** * @file llsimdmath.h * @brief Common header for SIMD-based math library (llvector4a, llmatrix3a, etc.) * * $LicenseInfo:firstyear=2010&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ -#ifndef LL_SIMD_MATH_H -#define LL_SIMD_MATH_H +#ifndef LL_SIMD_MATH_H +#define LL_SIMD_MATH_H #ifndef LLMATH_H #error "Please include llmath.h before this file." diff --git a/indra/llmath/llsimdtypes.h b/indra/llmath/llsimdtypes.h index bd991d0e71..9db152adf8 100644 --- a/indra/llmath/llsimdtypes.h +++ b/indra/llmath/llsimdtypes.h @@ -1,25 +1,25 @@ -/** +/** * @file llsimdtypes.h * @brief Declaration of basic SIMD math related types * * $LicenseInfo:firstyear=2010&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -31,7 +31,7 @@ #error "Please include llmath.h before this file." #endif -typedef __m128 LLQuad; +typedef __m128 LLQuad; #if LL_WINDOWS @@ -50,17 +50,17 @@ __forceinline const __m128i _mm_castps_si128( const __m128 a ) { return reinterp class LLBool32 { public: - inline LLBool32() {} - inline LLBool32(int rhs) : m_bool(rhs) {} - inline LLBool32(unsigned int rhs) : m_bool(rhs) {} - inline LLBool32(bool rhs) { m_bool = static_cast<const int>(rhs); } - inline LLBool32& operator= (bool rhs) { m_bool = (int)rhs; return *this; } - inline bool operator== (bool rhs) const { return static_cast<const bool&>(m_bool) == rhs; } - inline bool operator!= (bool rhs) const { return !operator==(rhs); } - inline operator bool() const { return static_cast<const bool&>(m_bool); } + inline LLBool32() {} + inline LLBool32(int rhs) : m_bool(rhs) {} + inline LLBool32(unsigned int rhs) : m_bool(rhs) {} + inline LLBool32(bool rhs) { m_bool = static_cast<const int>(rhs); } + inline LLBool32& operator= (bool rhs) { m_bool = (int)rhs; return *this; } + inline bool operator== (bool rhs) const { return static_cast<const bool&>(m_bool) == rhs; } + inline bool operator!= (bool rhs) const { return !operator==(rhs); } + inline operator bool() const { return static_cast<const bool&>(m_bool); } private: - int m_bool; + int m_bool; }; #if LL_WINDOWS @@ -70,55 +70,55 @@ private: class LLSimdScalar { public: - inline LLSimdScalar() {} - inline LLSimdScalar(LLQuad q) - { - mQ = q; - } + inline LLSimdScalar() {} + inline LLSimdScalar(LLQuad q) + { + mQ = q; + } + + inline LLSimdScalar(F32 f) + { + mQ = _mm_set_ss(f); + } + + static inline const LLSimdScalar& getZero() + { + extern const LLQuad F_ZERO_4A; + return reinterpret_cast<const LLSimdScalar&>(F_ZERO_4A); + } - inline LLSimdScalar(F32 f) - { - mQ = _mm_set_ss(f); - } + inline F32 getF32() const; - static inline const LLSimdScalar& getZero() - { - extern const LLQuad F_ZERO_4A; - return reinterpret_cast<const LLSimdScalar&>(F_ZERO_4A); - } + inline LLBool32 isApproximatelyEqual(const LLSimdScalar& rhs, F32 tolerance = F_APPROXIMATELY_ZERO) const; - inline F32 getF32() const; + inline LLSimdScalar getAbs() const; - inline LLBool32 isApproximatelyEqual(const LLSimdScalar& rhs, F32 tolerance = F_APPROXIMATELY_ZERO) const; + inline void setMax( const LLSimdScalar& a, const LLSimdScalar& b ); - inline LLSimdScalar getAbs() const; + inline void setMin( const LLSimdScalar& a, const LLSimdScalar& b ); - inline void setMax( const LLSimdScalar& a, const LLSimdScalar& b ); - - inline void setMin( const LLSimdScalar& a, const LLSimdScalar& b ); + inline LLSimdScalar& operator=(F32 rhs); - inline LLSimdScalar& operator=(F32 rhs); + inline LLSimdScalar& operator+=(const LLSimdScalar& rhs); - inline LLSimdScalar& operator+=(const LLSimdScalar& rhs); + inline LLSimdScalar& operator-=(const LLSimdScalar& rhs); - inline LLSimdScalar& operator-=(const LLSimdScalar& rhs); + inline LLSimdScalar& operator*=(const LLSimdScalar& rhs); - inline LLSimdScalar& operator*=(const LLSimdScalar& rhs); + inline LLSimdScalar& operator/=(const LLSimdScalar& rhs); - inline LLSimdScalar& operator/=(const LLSimdScalar& rhs); + inline operator LLQuad() const + { + return mQ; + } - inline operator LLQuad() const - { - return mQ; - } - - inline const LLQuad& getQuad() const - { - return mQ; - } + inline const LLQuad& getQuad() const + { + return mQ; + } private: - LLQuad mQ; + LLQuad mQ; }; #endif //LL_SIMD_TYPES_H diff --git a/indra/llmath/llsimdtypes.inl b/indra/llmath/llsimdtypes.inl index e905c84954..125f4b9df5 100644 --- a/indra/llmath/llsimdtypes.inl +++ b/indra/llmath/llsimdtypes.inl @@ -1,25 +1,25 @@ -/** +/** * @file llsimdtypes.inl * @brief Inlined definitions of basic SIMD math related types * * $LicenseInfo:firstyear=2010&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -33,127 +33,127 @@ inline LLSimdScalar operator+(const LLSimdScalar& a, const LLSimdScalar& b) { - LLSimdScalar t(a); - t += b; - return t; + LLSimdScalar t(a); + t += b; + return t; } inline LLSimdScalar operator-(const LLSimdScalar& a, const LLSimdScalar& b) { - LLSimdScalar t(a); - t -= b; - return t; + LLSimdScalar t(a); + t -= b; + return t; } inline LLSimdScalar operator*(const LLSimdScalar& a, const LLSimdScalar& b) { - LLSimdScalar t(a); - t *= b; - return t; + LLSimdScalar t(a); + t *= b; + return t; } inline LLSimdScalar operator/(const LLSimdScalar& a, const LLSimdScalar& b) { - LLSimdScalar t(a); - t /= b; - return t; + LLSimdScalar t(a); + t /= b; + return t; } inline LLSimdScalar operator-(const LLSimdScalar& a) { - static LL_ALIGN_16(const U32 signMask[4]) = {0x80000000, 0x80000000, 0x80000000, 0x80000000 }; - ll_assert_aligned(signMask,16); - return _mm_xor_ps(*reinterpret_cast<const LLQuad*>(signMask), a); + static LL_ALIGN_16(const U32 signMask[4]) = {0x80000000, 0x80000000, 0x80000000, 0x80000000 }; + ll_assert_aligned(signMask,16); + return _mm_xor_ps(*reinterpret_cast<const LLQuad*>(signMask), a); } inline LLBool32 operator==(const LLSimdScalar& a, const LLSimdScalar& b) { - return _mm_comieq_ss(a, b); + return _mm_comieq_ss(a, b); } inline LLBool32 operator!=(const LLSimdScalar& a, const LLSimdScalar& b) { - return _mm_comineq_ss(a, b); + return _mm_comineq_ss(a, b); } inline LLBool32 operator<(const LLSimdScalar& a, const LLSimdScalar& b) { - return _mm_comilt_ss(a, b); + return _mm_comilt_ss(a, b); } inline LLBool32 operator<=(const LLSimdScalar& a, const LLSimdScalar& b) { - return _mm_comile_ss(a, b); + return _mm_comile_ss(a, b); } inline LLBool32 operator>(const LLSimdScalar& a, const LLSimdScalar& b) { - return _mm_comigt_ss(a, b); + return _mm_comigt_ss(a, b); } inline LLBool32 operator>=(const LLSimdScalar& a, const LLSimdScalar& b) { - return _mm_comige_ss(a, b); + return _mm_comige_ss(a, b); } inline LLBool32 LLSimdScalar::isApproximatelyEqual(const LLSimdScalar& rhs, F32 tolerance /* = F_APPROXIMATELY_ZERO */) const { - const LLSimdScalar tol( tolerance ); - const LLSimdScalar diff = _mm_sub_ss( mQ, rhs.mQ ); - const LLSimdScalar absDiff = diff.getAbs(); - return absDiff <= tol; + const LLSimdScalar tol( tolerance ); + const LLSimdScalar diff = _mm_sub_ss( mQ, rhs.mQ ); + const LLSimdScalar absDiff = diff.getAbs(); + return absDiff <= tol; } inline void LLSimdScalar::setMax( const LLSimdScalar& a, const LLSimdScalar& b ) { - mQ = _mm_max_ss( a, b ); + mQ = _mm_max_ss( a, b ); } inline void LLSimdScalar::setMin( const LLSimdScalar& a, const LLSimdScalar& b ) { - mQ = _mm_min_ss( a, b ); + mQ = _mm_min_ss( a, b ); } -inline LLSimdScalar& LLSimdScalar::operator=(F32 rhs) -{ - mQ = _mm_set_ss(rhs); - return *this; +inline LLSimdScalar& LLSimdScalar::operator=(F32 rhs) +{ + mQ = _mm_set_ss(rhs); + return *this; } -inline LLSimdScalar& LLSimdScalar::operator+=(const LLSimdScalar& rhs) +inline LLSimdScalar& LLSimdScalar::operator+=(const LLSimdScalar& rhs) { - mQ = _mm_add_ss( mQ, rhs ); - return *this; + mQ = _mm_add_ss( mQ, rhs ); + return *this; } inline LLSimdScalar& LLSimdScalar::operator-=(const LLSimdScalar& rhs) { - mQ = _mm_sub_ss( mQ, rhs ); - return *this; + mQ = _mm_sub_ss( mQ, rhs ); + return *this; } inline LLSimdScalar& LLSimdScalar::operator*=(const LLSimdScalar& rhs) { - mQ = _mm_mul_ss( mQ, rhs ); - return *this; + mQ = _mm_mul_ss( mQ, rhs ); + return *this; } inline LLSimdScalar& LLSimdScalar::operator/=(const LLSimdScalar& rhs) { - mQ = _mm_div_ss( mQ, rhs ); - return *this; + mQ = _mm_div_ss( mQ, rhs ); + return *this; } inline LLSimdScalar LLSimdScalar::getAbs() const { - static const LL_ALIGN_16(U32 F_ABS_MASK_4A[4]) = { 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF }; - ll_assert_aligned(F_ABS_MASK_4A,16); - return _mm_and_ps( mQ, *reinterpret_cast<const LLQuad*>(F_ABS_MASK_4A)); + static const LL_ALIGN_16(U32 F_ABS_MASK_4A[4]) = { 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF }; + ll_assert_aligned(F_ABS_MASK_4A,16); + return _mm_and_ps( mQ, *reinterpret_cast<const LLQuad*>(F_ABS_MASK_4A)); } inline F32 LLSimdScalar::getF32() const -{ - F32 ret; - _mm_store_ss(&ret, mQ); - return ret; +{ + F32 ret; + _mm_store_ss(&ret, mQ); + return ret; } diff --git a/indra/llmath/llsphere.cpp b/indra/llmath/llsphere.cpp index 3f04ca704c..89349af6c8 100644 --- a/indra/llmath/llsphere.cpp +++ b/indra/llmath/llsphere.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llsphere.cpp * @author Andrew Meadows * @brief Simple line class that can compute nearest approach between two lines @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -30,341 +30,341 @@ #include "llsphere.h" LLSphere::LLSphere() -: mCenter(0.f, 0.f, 0.f), - mRadius(0.f) +: mCenter(0.f, 0.f, 0.f), + mRadius(0.f) { } LLSphere::LLSphere( const LLVector3& center, F32 radius) { - set(center, radius); + set(center, radius); } void LLSphere::set( const LLVector3& center, F32 radius ) { - mCenter = center; - setRadius(radius); + mCenter = center; + setRadius(radius); } void LLSphere::setCenter( const LLVector3& center) { - mCenter = center; + mCenter = center; } void LLSphere::setRadius( F32 radius) { - if (radius < 0.f) - { - radius = -radius; - } - mRadius = radius; + if (radius < 0.f) + { + radius = -radius; + } + mRadius = radius; } - + const LLVector3& LLSphere::getCenter() const { - return mCenter; + return mCenter; } F32 LLSphere::getRadius() const { - return mRadius; + return mRadius; } // returns 'true' if this sphere completely contains other_sphere bool LLSphere::contains(const LLSphere& other_sphere) const { - F32 separation = (mCenter - other_sphere.mCenter).length(); - return mRadius >= separation + other_sphere.mRadius; + F32 separation = (mCenter - other_sphere.mCenter).length(); + return mRadius >= separation + other_sphere.mRadius; } // returns 'true' if this sphere completely contains other_sphere bool LLSphere::overlaps(const LLSphere& other_sphere) const { - F32 separation = (mCenter - other_sphere.mCenter).length(); - return mRadius >= separation - other_sphere.mRadius; + F32 separation = (mCenter - other_sphere.mCenter).length(); + return mRadius >= separation - other_sphere.mRadius; } // returns overlap // negative overlap is closest approach F32 LLSphere::getOverlap(const LLSphere& other_sphere) const { - // separation is distance from other_sphere's edge and this center - return (mCenter - other_sphere.mCenter).length() - mRadius - other_sphere.mRadius; + // separation is distance from other_sphere's edge and this center + return (mCenter - other_sphere.mCenter).length() - mRadius - other_sphere.mRadius; } bool LLSphere::operator==(const LLSphere& rhs) const { - return fabs(mRadius - rhs.mRadius) <= FLT_EPSILON && - (mCenter - rhs.mCenter).length() <= FLT_EPSILON; + return fabs(mRadius - rhs.mRadius) <= FLT_EPSILON && + (mCenter - rhs.mCenter).length() <= FLT_EPSILON; } std::ostream& operator<<( std::ostream& output_stream, const LLSphere& sphere) { - output_stream << "{center=" << sphere.mCenter << "," << "radius=" << sphere.mRadius << "}"; - return output_stream; + output_stream << "{center=" << sphere.mCenter << "," << "radius=" << sphere.mRadius << "}"; + return output_stream; } -// static +// static // removes any spheres that are contained in others void LLSphere::collapse(std::vector<LLSphere>& sphere_list) { - std::vector<LLSphere>::iterator first_itr = sphere_list.begin(); - while (first_itr != sphere_list.end()) - { - bool delete_from_front = false; - - std::vector<LLSphere>::iterator second_itr = first_itr; - ++second_itr; - while (second_itr != sphere_list.end()) - { - if (second_itr->contains(*first_itr)) - { - delete_from_front = true; - break; - } - else if (first_itr->contains(*second_itr)) - { - sphere_list.erase(second_itr++); - } - else - { - ++second_itr; - } - } - - if (delete_from_front) - { - sphere_list.erase(first_itr++); - } - else - { - ++first_itr; - } - } + std::vector<LLSphere>::iterator first_itr = sphere_list.begin(); + while (first_itr != sphere_list.end()) + { + bool delete_from_front = false; + + std::vector<LLSphere>::iterator second_itr = first_itr; + ++second_itr; + while (second_itr != sphere_list.end()) + { + if (second_itr->contains(*first_itr)) + { + delete_from_front = true; + break; + } + else if (first_itr->contains(*second_itr)) + { + sphere_list.erase(second_itr++); + } + else + { + ++second_itr; + } + } + + if (delete_from_front) + { + sphere_list.erase(first_itr++); + } + else + { + ++first_itr; + } + } } // static // returns the bounding sphere that contains both spheres LLSphere LLSphere::getBoundingSphere(const LLSphere& first_sphere, const LLSphere& second_sphere) { - LLVector3 direction = second_sphere.mCenter - first_sphere.mCenter; - - // HACK -- it is possible to get enough floating point error in the - // other getBoundingSphere() method that we have to add some slop - // at the end. Unfortunately, this breaks the link-order invarience - // for the linkability tests... unless we also apply the same slop - // here. - F32 half_milimeter = 0.0005f; - - F32 distance = direction.length(); - if (0.f == distance) - { - direction.setVec(1.f, 0.f, 0.f); - } - else - { - direction.normVec(); - } - // the 'edge' is measured from the first_sphere's center - F32 max_edge = 0.f; - F32 min_edge = 0.f; - - max_edge = llmax(max_edge + first_sphere.getRadius(), max_edge + distance + second_sphere.getRadius() + half_milimeter); - min_edge = llmin(min_edge - first_sphere.getRadius(), min_edge + distance - second_sphere.getRadius() - half_milimeter); - F32 radius = 0.5f * (max_edge - min_edge); - LLVector3 center = first_sphere.mCenter + (0.5f * (max_edge + min_edge)) * direction; - return LLSphere(center, radius); + LLVector3 direction = second_sphere.mCenter - first_sphere.mCenter; + + // HACK -- it is possible to get enough floating point error in the + // other getBoundingSphere() method that we have to add some slop + // at the end. Unfortunately, this breaks the link-order invarience + // for the linkability tests... unless we also apply the same slop + // here. + F32 half_milimeter = 0.0005f; + + F32 distance = direction.length(); + if (0.f == distance) + { + direction.setVec(1.f, 0.f, 0.f); + } + else + { + direction.normVec(); + } + // the 'edge' is measured from the first_sphere's center + F32 max_edge = 0.f; + F32 min_edge = 0.f; + + max_edge = llmax(max_edge + first_sphere.getRadius(), max_edge + distance + second_sphere.getRadius() + half_milimeter); + min_edge = llmin(min_edge - first_sphere.getRadius(), min_edge + distance - second_sphere.getRadius() - half_milimeter); + F32 radius = 0.5f * (max_edge - min_edge); + LLVector3 center = first_sphere.mCenter + (0.5f * (max_edge + min_edge)) * direction; + return LLSphere(center, radius); } // static // returns the bounding sphere that contains an arbitrary set of spheres LLSphere LLSphere::getBoundingSphere(const std::vector<LLSphere>& sphere_list) { - // this algorithm can get relatively inaccurate when the sphere - // collection is 'small' (contained within a bounding sphere of about - // 2 meters or less) - // TODO -- improve the accuracy for small collections of spheres - - LLSphere bounding_sphere( LLVector3(0.f, 0.f, 0.f), 0.f ); - S32 sphere_count = sphere_list.size(); - if (1 == sphere_count) - { - // trivial case -- single sphere - std::vector<LLSphere>::const_iterator sphere_itr = sphere_list.begin(); - bounding_sphere = *sphere_itr; - } - else if (2 == sphere_count) - { - // trivial case -- two spheres - std::vector<LLSphere>::const_iterator first_sphere = sphere_list.begin(); - std::vector<LLSphere>::const_iterator second_sphere = first_sphere; - ++second_sphere; - bounding_sphere = LLSphere::getBoundingSphere(*first_sphere, *second_sphere); - } - else if (sphere_count > 0) - { - // non-trivial case -- we will approximate the solution - // - // NOTE -- there is a fancy/fast way to do this for large - // numbers of arbirary N-dimensional spheres -- you can look it - // up on the net. We're dealing with 3D spheres at collection - // sizes of 256 spheres or smaller, so we just use this - // brute force method. - - // TODO -- perhaps would be worthwile to test for the solution where - // the largest spanning radius just happens to work. That is, where - // there are really two spheres that determine the bounding sphere, - // and all others are contained therein. - - // compute the AABB - std::vector<LLSphere>::const_iterator first_itr = sphere_list.begin(); - LLVector3 max_corner = first_itr->getCenter() + first_itr->getRadius() * LLVector3(1.f, 1.f, 1.f); - LLVector3 min_corner = first_itr->getCenter() - first_itr->getRadius() * LLVector3(1.f, 1.f, 1.f); - { - std::vector<LLSphere>::const_iterator sphere_itr = sphere_list.begin(); - for (++sphere_itr; sphere_itr != sphere_list.end(); ++sphere_itr) - { - LLVector3 center = sphere_itr->getCenter(); - F32 radius = sphere_itr->getRadius(); - for (S32 i=0; i<3; ++i) - { - if (center.mV[i] + radius > max_corner.mV[i]) - { - max_corner.mV[i] = center.mV[i] + radius; - } - if (center.mV[i] - radius < min_corner.mV[i]) - { - min_corner.mV[i] = center.mV[i] - radius; - } - } - } - } - - // get the starting center and radius from the AABB - LLVector3 diagonal = max_corner - min_corner; - F32 bounding_radius = 0.5f * diagonal.length(); - LLVector3 bounding_center = 0.5f * (max_corner + min_corner); - - // compute the starting step-size - F32 minimum_radius = 0.5f * llmin(diagonal.mV[VX], llmin(diagonal.mV[VY], diagonal.mV[VZ])); - F32 step_length = bounding_radius - minimum_radius; - //S32 step_count = 0; - //S32 max_step_count = 12; - F32 half_milimeter = 0.0005f; - - // wander the center around in search of tighter solutions - S32 last_dx = 2; // 2 is out of bounds --> no match - S32 last_dy = 2; - S32 last_dz = 2; - - while (step_length > half_milimeter - /*&& step_count < max_step_count*/) - { - // the algorithm for testing the maximum radius could be expensive enough - // that it makes sense to NOT duplicate testing when possible, so we keep - // track of where we last tested, and only test the new points - - S32 best_dx = 0; - S32 best_dy = 0; - S32 best_dz = 0; - - // sample near the center of the box - bool found_better_center = false; - for (S32 dx = -1; dx < 2; ++dx) - { - for (S32 dy = -1; dy < 2; ++dy) - { - for (S32 dz = -1; dz < 2; ++dz) - { - if (dx == 0 && dy == 0 && dz == 0) - { - continue; - } - - // count the number of indecies that match the last_*'s - S32 match_count = 0; - if (last_dx == dx) ++match_count; - if (last_dy == dy) ++match_count; - if (last_dz == dz) ++match_count; - if (match_count == 2) - { - // we've already tested this point - continue; - } - - LLVector3 center = bounding_center; - center.mV[VX] += (F32) dx * step_length; - center.mV[VY] += (F32) dy * step_length; - center.mV[VZ] += (F32) dz * step_length; - - // compute the radius of the bounding sphere - F32 max_radius = 0.f; - std::vector<LLSphere>::const_iterator sphere_itr; - for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr) - { - F32 radius = (sphere_itr->getCenter() - center).length() + sphere_itr->getRadius(); - if (radius > max_radius) - { - max_radius = radius; - } - } - if (max_radius < bounding_radius) - { - best_dx = dx; - best_dy = dy; - best_dz = dz; - bounding_center = center; - bounding_radius = max_radius; - found_better_center = true; - } - } - } - } - if (found_better_center) - { - // remember where we came from so we can avoid retesting - last_dx = -best_dx; - last_dy = -best_dy; - last_dz = -best_dz; - } - else - { - // reduce the step size - step_length *= 0.5f; - //++step_count; - // reset the last_*'s - last_dx = 2; // 2 is out of bounds --> no match - last_dy = 2; - last_dz = 2; - } - } - - // HACK -- it is possible to get enough floating point error for the - // bounding sphere to too small on the order of 10e-6, but we only need - // it to be accurate to within about half a millimeter - bounding_radius += half_milimeter; - - // this algorithm can get relatively inaccurate when the sphere - // collection is 'small' (contained within a bounding sphere of about - // 2 meters or less) - // TODO -- fix this - /* debug code - { - std::vector<LLSphere>::const_iterator sphere_itr; - for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr) - { - F32 radius = (sphere_itr->getCenter() - bounding_center).length() + sphere_itr->getRadius(); - if (radius + 0.1f > bounding_radius) - { - std::cout << " rad = " << radius << " bounding - rad = " << (bounding_radius - radius) << std::endl; - } - } - std::cout << "\n" << std::endl; - } - */ - - bounding_sphere.set(bounding_center, bounding_radius); - } - return bounding_sphere; + // this algorithm can get relatively inaccurate when the sphere + // collection is 'small' (contained within a bounding sphere of about + // 2 meters or less) + // TODO -- improve the accuracy for small collections of spheres + + LLSphere bounding_sphere( LLVector3(0.f, 0.f, 0.f), 0.f ); + S32 sphere_count = sphere_list.size(); + if (1 == sphere_count) + { + // trivial case -- single sphere + std::vector<LLSphere>::const_iterator sphere_itr = sphere_list.begin(); + bounding_sphere = *sphere_itr; + } + else if (2 == sphere_count) + { + // trivial case -- two spheres + std::vector<LLSphere>::const_iterator first_sphere = sphere_list.begin(); + std::vector<LLSphere>::const_iterator second_sphere = first_sphere; + ++second_sphere; + bounding_sphere = LLSphere::getBoundingSphere(*first_sphere, *second_sphere); + } + else if (sphere_count > 0) + { + // non-trivial case -- we will approximate the solution + // + // NOTE -- there is a fancy/fast way to do this for large + // numbers of arbirary N-dimensional spheres -- you can look it + // up on the net. We're dealing with 3D spheres at collection + // sizes of 256 spheres or smaller, so we just use this + // brute force method. + + // TODO -- perhaps would be worthwile to test for the solution where + // the largest spanning radius just happens to work. That is, where + // there are really two spheres that determine the bounding sphere, + // and all others are contained therein. + + // compute the AABB + std::vector<LLSphere>::const_iterator first_itr = sphere_list.begin(); + LLVector3 max_corner = first_itr->getCenter() + first_itr->getRadius() * LLVector3(1.f, 1.f, 1.f); + LLVector3 min_corner = first_itr->getCenter() - first_itr->getRadius() * LLVector3(1.f, 1.f, 1.f); + { + std::vector<LLSphere>::const_iterator sphere_itr = sphere_list.begin(); + for (++sphere_itr; sphere_itr != sphere_list.end(); ++sphere_itr) + { + LLVector3 center = sphere_itr->getCenter(); + F32 radius = sphere_itr->getRadius(); + for (S32 i=0; i<3; ++i) + { + if (center.mV[i] + radius > max_corner.mV[i]) + { + max_corner.mV[i] = center.mV[i] + radius; + } + if (center.mV[i] - radius < min_corner.mV[i]) + { + min_corner.mV[i] = center.mV[i] - radius; + } + } + } + } + + // get the starting center and radius from the AABB + LLVector3 diagonal = max_corner - min_corner; + F32 bounding_radius = 0.5f * diagonal.length(); + LLVector3 bounding_center = 0.5f * (max_corner + min_corner); + + // compute the starting step-size + F32 minimum_radius = 0.5f * llmin(diagonal.mV[VX], llmin(diagonal.mV[VY], diagonal.mV[VZ])); + F32 step_length = bounding_radius - minimum_radius; + //S32 step_count = 0; + //S32 max_step_count = 12; + F32 half_milimeter = 0.0005f; + + // wander the center around in search of tighter solutions + S32 last_dx = 2; // 2 is out of bounds --> no match + S32 last_dy = 2; + S32 last_dz = 2; + + while (step_length > half_milimeter + /*&& step_count < max_step_count*/) + { + // the algorithm for testing the maximum radius could be expensive enough + // that it makes sense to NOT duplicate testing when possible, so we keep + // track of where we last tested, and only test the new points + + S32 best_dx = 0; + S32 best_dy = 0; + S32 best_dz = 0; + + // sample near the center of the box + bool found_better_center = false; + for (S32 dx = -1; dx < 2; ++dx) + { + for (S32 dy = -1; dy < 2; ++dy) + { + for (S32 dz = -1; dz < 2; ++dz) + { + if (dx == 0 && dy == 0 && dz == 0) + { + continue; + } + + // count the number of indecies that match the last_*'s + S32 match_count = 0; + if (last_dx == dx) ++match_count; + if (last_dy == dy) ++match_count; + if (last_dz == dz) ++match_count; + if (match_count == 2) + { + // we've already tested this point + continue; + } + + LLVector3 center = bounding_center; + center.mV[VX] += (F32) dx * step_length; + center.mV[VY] += (F32) dy * step_length; + center.mV[VZ] += (F32) dz * step_length; + + // compute the radius of the bounding sphere + F32 max_radius = 0.f; + std::vector<LLSphere>::const_iterator sphere_itr; + for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr) + { + F32 radius = (sphere_itr->getCenter() - center).length() + sphere_itr->getRadius(); + if (radius > max_radius) + { + max_radius = radius; + } + } + if (max_radius < bounding_radius) + { + best_dx = dx; + best_dy = dy; + best_dz = dz; + bounding_center = center; + bounding_radius = max_radius; + found_better_center = true; + } + } + } + } + if (found_better_center) + { + // remember where we came from so we can avoid retesting + last_dx = -best_dx; + last_dy = -best_dy; + last_dz = -best_dz; + } + else + { + // reduce the step size + step_length *= 0.5f; + //++step_count; + // reset the last_*'s + last_dx = 2; // 2 is out of bounds --> no match + last_dy = 2; + last_dz = 2; + } + } + + // HACK -- it is possible to get enough floating point error for the + // bounding sphere to too small on the order of 10e-6, but we only need + // it to be accurate to within about half a millimeter + bounding_radius += half_milimeter; + + // this algorithm can get relatively inaccurate when the sphere + // collection is 'small' (contained within a bounding sphere of about + // 2 meters or less) + // TODO -- fix this + /* debug code + { + std::vector<LLSphere>::const_iterator sphere_itr; + for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr) + { + F32 radius = (sphere_itr->getCenter() - bounding_center).length() + sphere_itr->getRadius(); + if (radius + 0.1f > bounding_radius) + { + std::cout << " rad = " << radius << " bounding - rad = " << (bounding_radius - radius) << std::endl; + } + } + std::cout << "\n" << std::endl; + } + */ + + bounding_sphere.set(bounding_center, bounding_radius); + } + return bounding_sphere; } diff --git a/indra/llmath/llsphere.h b/indra/llmath/llsphere.h index ba8e437ecf..cb923dcd3c 100644 --- a/indra/llmath/llsphere.h +++ b/indra/llmath/llsphere.h @@ -7,21 +7,21 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -37,40 +37,40 @@ class LLSphere { public: - LLSphere(); - LLSphere( const LLVector3& center, F32 radius ); + LLSphere(); + LLSphere( const LLVector3& center, F32 radius ); - void set( const LLVector3& center, F32 radius ); - void setCenter( const LLVector3& center ); - void setRadius( F32 radius ); + void set( const LLVector3& center, F32 radius ); + void setCenter( const LLVector3& center ); + void setRadius( F32 radius ); - const LLVector3& getCenter() const; - F32 getRadius() const; + const LLVector3& getCenter() const; + F32 getRadius() const; - // returns true if this sphere completely contains other_sphere - bool contains(const LLSphere& other_sphere) const; + // returns true if this sphere completely contains other_sphere + bool contains(const LLSphere& other_sphere) const; - // returns true if this sphere overlaps other_sphere - bool overlaps(const LLSphere& other_sphere) const; + // returns true if this sphere overlaps other_sphere + bool overlaps(const LLSphere& other_sphere) const; - // returns overlap distance - // negative overlap is closest approach - F32 getOverlap(const LLSphere& other_sphere) const; + // returns overlap distance + // negative overlap is closest approach + F32 getOverlap(const LLSphere& other_sphere) const; - // removes any spheres that are contained in others - static void collapse(std::vector<LLSphere>& sphere_list); + // removes any spheres that are contained in others + static void collapse(std::vector<LLSphere>& sphere_list); - // returns minimum sphere bounding sphere for a set of spheres - static LLSphere getBoundingSphere(const LLSphere& first_sphere, const LLSphere& second_sphere); - static LLSphere getBoundingSphere(const std::vector<LLSphere>& sphere_list); + // returns minimum sphere bounding sphere for a set of spheres + static LLSphere getBoundingSphere(const LLSphere& first_sphere, const LLSphere& second_sphere); + static LLSphere getBoundingSphere(const std::vector<LLSphere>& sphere_list); - bool operator==(const LLSphere& rhs) const; + bool operator==(const LLSphere& rhs) const; - friend std::ostream& operator<<( std::ostream& output_stream, const LLSphere& line ); + friend std::ostream& operator<<( std::ostream& output_stream, const LLSphere& line ); protected: - LLVector3 mCenter; - F32 mRadius; + LLVector3 mCenter; + F32 mRadius; }; diff --git a/indra/llmath/lltreenode.h b/indra/llmath/lltreenode.h index ce104b88a0..f648a114ca 100644 --- a/indra/llmath/lltreenode.h +++ b/indra/llmath/lltreenode.h @@ -1,24 +1,24 @@ -/** +/** * @file lltreenode.h * * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -41,85 +41,85 @@ template <class T> class LLTreeListener: public LLRefCount { public: - virtual void handleInsertion(const LLTreeNode<T>* node, T* data) = 0; - virtual void handleRemoval(const LLTreeNode<T>* node, T* data) = 0; - virtual void handleDestruction(const LLTreeNode<T>* node) = 0; - virtual void handleStateChange(const LLTreeNode<T>* node) = 0; + virtual void handleInsertion(const LLTreeNode<T>* node, T* data) = 0; + virtual void handleRemoval(const LLTreeNode<T>* node, T* data) = 0; + virtual void handleDestruction(const LLTreeNode<T>* node) = 0; + virtual void handleStateChange(const LLTreeNode<T>* node) = 0; }; template <class T> -class LLTreeNode +class LLTreeNode { public: - virtual ~LLTreeNode(); - - virtual bool insert(T* data); - virtual bool remove(T* data); - virtual void notifyRemoval(T* data); - virtual U32 hasListeners() const { return !mListeners.empty(); } - virtual U32 getListenerCount() const { return mListeners.size(); } - virtual LLTreeListener<T>* getListener(U32 index) const - { - if (index < mListeners.size()) - { - return mListeners[index]; - } - return NULL; - } - virtual void addListener(LLTreeListener<T>* listener) { mListeners.push_back(listener); } + virtual ~LLTreeNode(); + + virtual bool insert(T* data); + virtual bool remove(T* data); + virtual void notifyRemoval(T* data); + virtual U32 hasListeners() const { return !mListeners.empty(); } + virtual U32 getListenerCount() const { return mListeners.size(); } + virtual LLTreeListener<T>* getListener(U32 index) const + { + if (index < mListeners.size()) + { + return mListeners[index]; + } + return NULL; + } + virtual void addListener(LLTreeListener<T>* listener) { mListeners.push_back(listener); } protected: - void destroyListeners() - { - for (U32 i = 0; i < mListeners.size(); i++) - { - mListeners[i]->handleDestruction(this); - } - mListeners.clear(); - } - + void destroyListeners() + { + for (U32 i = 0; i < mListeners.size(); i++) + { + mListeners[i]->handleDestruction(this); + } + mListeners.clear(); + } + public: - std::vector<LLPointer<LLTreeListener<T> > > mListeners; + std::vector<LLPointer<LLTreeListener<T> > > mListeners; }; template <class T> class LLTreeTraveler { public: - virtual ~LLTreeTraveler() { }; - virtual void traverse(const LLTreeNode<T>* node) = 0; - virtual void visit(const LLTreeNode<T>* node) = 0; + virtual ~LLTreeTraveler() { }; + virtual void traverse(const LLTreeNode<T>* node) = 0; + virtual void visit(const LLTreeNode<T>* node) = 0; }; template <class T> LLTreeNode<T>::~LLTreeNode() -{ - destroyListeners(); +{ + destroyListeners(); }; template <class T> bool LLTreeNode<T>::insert(T* data) -{ - for (U32 i = 0; i < mListeners.size(); i++) - { - mListeners[i]->handleInsertion(this, data); - } - return true; +{ + for (U32 i = 0; i < mListeners.size(); i++) + { + mListeners[i]->handleInsertion(this, data); + } + return true; }; template <class T> bool LLTreeNode<T>::remove(T* data) { - return true; + return true; }; template <class T> void LLTreeNode<T>::notifyRemoval(T* data) { - for (U32 i = 0; i < mListeners.size(); i++) - { - mListeners[i]->handleRemoval(this, data); - } + for (U32 i = 0; i < mListeners.size(); i++) + { + mListeners[i]->handleRemoval(this, data); + } } #endif diff --git a/indra/llmath/llvector4a.cpp b/indra/llmath/llvector4a.cpp index 570fa41a43..0ac91366b6 100644 --- a/indra/llmath/llvector4a.cpp +++ b/indra/llmath/llvector4a.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llvector4a.cpp * @brief SIMD vector implementation * * $LicenseInfo:firstyear=2010&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -28,12 +28,12 @@ #include "llmath.h" #include "llquantize.h" -extern const LLQuad F_ZERO_4A = { 0, 0, 0, 0 }; -extern const LLQuad F_APPROXIMATELY_ZERO_4A = { - F_APPROXIMATELY_ZERO, - F_APPROXIMATELY_ZERO, - F_APPROXIMATELY_ZERO, - F_APPROXIMATELY_ZERO +extern const LLQuad F_ZERO_4A = { 0, 0, 0, 0 }; +extern const LLQuad F_APPROXIMATELY_ZERO_4A = { + F_APPROXIMATELY_ZERO, + F_APPROXIMATELY_ZERO, + F_APPROXIMATELY_ZERO, + F_APPROXIMATELY_ZERO }; extern const LLVector4a LL_V4A_ZERO = reinterpret_cast<const LLVector4a&> ( F_ZERO_4A ); @@ -46,135 +46,135 @@ extern const LLVector4a LL_V4A_EPSILON = reinterpret_cast<const LLVector4a&> ( F void LLVector4a::setRotated( const LLRotation& rot, const LLVector4a& vec ) { - const LLVector4a col0 = rot.getColumn(0); - const LLVector4a col1 = rot.getColumn(1); - const LLVector4a col2 = rot.getColumn(2); - - LLVector4a result = _mm_load_ss( vec.getF32ptr() ); - result.splat<0>( result ); - result.mul( col0 ); - - { - LLVector4a yyyy = _mm_load_ss( vec.getF32ptr() + 1 ); - yyyy.splat<0>( yyyy ); - yyyy.mul( col1 ); - result.add( yyyy ); - } - - { - LLVector4a zzzz = _mm_load_ss( vec.getF32ptr() + 2 ); - zzzz.splat<0>( zzzz ); - zzzz.mul( col2 ); - result.add( zzzz ); - } - - *this = result; + const LLVector4a col0 = rot.getColumn(0); + const LLVector4a col1 = rot.getColumn(1); + const LLVector4a col2 = rot.getColumn(2); + + LLVector4a result = _mm_load_ss( vec.getF32ptr() ); + result.splat<0>( result ); + result.mul( col0 ); + + { + LLVector4a yyyy = _mm_load_ss( vec.getF32ptr() + 1 ); + yyyy.splat<0>( yyyy ); + yyyy.mul( col1 ); + result.add( yyyy ); + } + + { + LLVector4a zzzz = _mm_load_ss( vec.getF32ptr() + 2 ); + zzzz.splat<0>( zzzz ); + zzzz.mul( col2 ); + result.add( zzzz ); + } + + *this = result; } void LLVector4a::setRotated( const LLQuaternion2& quat, const LLVector4a& vec ) { - const LLVector4a& quatVec = quat.getVector4a(); - LLVector4a temp; temp.setCross3(quatVec, vec); - temp.add( temp ); - - const LLVector4a realPart( quatVec.getScalarAt<3>() ); - LLVector4a tempTimesReal; tempTimesReal.setMul( temp, realPart ); - - mQ = vec; - add( tempTimesReal ); - - LLVector4a imagCrossTemp; imagCrossTemp.setCross3( quatVec, temp ); - add(imagCrossTemp); + const LLVector4a& quatVec = quat.getVector4a(); + LLVector4a temp; temp.setCross3(quatVec, vec); + temp.add( temp ); + + const LLVector4a realPart( quatVec.getScalarAt<3>() ); + LLVector4a tempTimesReal; tempTimesReal.setMul( temp, realPart ); + + mQ = vec; + add( tempTimesReal ); + + LLVector4a imagCrossTemp; imagCrossTemp.setCross3( quatVec, temp ); + add(imagCrossTemp); } void LLVector4a::quantize8( const LLVector4a& low, const LLVector4a& high ) { - LLVector4a val(mQ); - LLVector4a delta; delta.setSub( high, low ); - - { - val.clamp(low, high); - val.sub(low); - - // 8-bit quantization means we can do with just 12 bits of reciprocal accuracy - const LLVector4a oneOverDelta = _mm_rcp_ps(delta.mQ); -// { -// static LL_ALIGN_16( const F32 F_TWO_4A[4] ) = { 2.f, 2.f, 2.f, 2.f }; -// LLVector4a two; two.load4a( F_TWO_4A ); -// -// // Here we use _mm_rcp_ps plus one round of newton-raphson -// // We wish to find 'x' such that x = 1/delta -// // As a first approximation, we take x0 = _mm_rcp_ps(delta) -// // Then x1 = 2 * x0 - a * x0^2 or x1 = x0 * ( 2 - a * x0 ) -// // See Intel AP-803 http://ompf.org/!/Intel_application_note_AP-803.pdf -// const LLVector4a recipApprox = _mm_rcp_ps(delta.mQ); -// oneOverDelta.setMul( delta, recipApprox ); -// oneOverDelta.setSub( two, oneOverDelta ); -// oneOverDelta.mul( recipApprox ); -// } - - val.mul(oneOverDelta); - val.mul(*reinterpret_cast<const LLVector4a*>(F_U8MAX_4A)); - } - - val = _mm_cvtepi32_ps(_mm_cvtps_epi32( val.mQ )); - - { - val.mul(*reinterpret_cast<const LLVector4a*>(F_OOU8MAX_4A)); - val.mul(delta); - val.add(low); - } - - { - LLVector4a maxError; maxError.setMul(delta, *reinterpret_cast<const LLVector4a*>(F_OOU8MAX_4A)); - LLVector4a absVal; absVal.setAbs( val ); - setSelectWithMask( absVal.lessThan( maxError ), F_ZERO_4A, val ); - } + LLVector4a val(mQ); + LLVector4a delta; delta.setSub( high, low ); + + { + val.clamp(low, high); + val.sub(low); + + // 8-bit quantization means we can do with just 12 bits of reciprocal accuracy + const LLVector4a oneOverDelta = _mm_rcp_ps(delta.mQ); +// { +// static LL_ALIGN_16( const F32 F_TWO_4A[4] ) = { 2.f, 2.f, 2.f, 2.f }; +// LLVector4a two; two.load4a( F_TWO_4A ); +// +// // Here we use _mm_rcp_ps plus one round of newton-raphson +// // We wish to find 'x' such that x = 1/delta +// // As a first approximation, we take x0 = _mm_rcp_ps(delta) +// // Then x1 = 2 * x0 - a * x0^2 or x1 = x0 * ( 2 - a * x0 ) +// // See Intel AP-803 http://ompf.org/!/Intel_application_note_AP-803.pdf +// const LLVector4a recipApprox = _mm_rcp_ps(delta.mQ); +// oneOverDelta.setMul( delta, recipApprox ); +// oneOverDelta.setSub( two, oneOverDelta ); +// oneOverDelta.mul( recipApprox ); +// } + + val.mul(oneOverDelta); + val.mul(*reinterpret_cast<const LLVector4a*>(F_U8MAX_4A)); + } + + val = _mm_cvtepi32_ps(_mm_cvtps_epi32( val.mQ )); + + { + val.mul(*reinterpret_cast<const LLVector4a*>(F_OOU8MAX_4A)); + val.mul(delta); + val.add(low); + } + + { + LLVector4a maxError; maxError.setMul(delta, *reinterpret_cast<const LLVector4a*>(F_OOU8MAX_4A)); + LLVector4a absVal; absVal.setAbs( val ); + setSelectWithMask( absVal.lessThan( maxError ), F_ZERO_4A, val ); + } } void LLVector4a::quantize16( const LLVector4a& low, const LLVector4a& high ) { - LLVector4a val(mQ); - LLVector4a delta; delta.setSub( high, low ); - - { - val.clamp(low, high); - val.sub(low); - - // 16-bit quantization means we need a round of Newton-Raphson - LLVector4a oneOverDelta; - { - static LL_ALIGN_16( const F32 F_TWO_4A[4] ) = { 2.f, 2.f, 2.f, 2.f }; - ll_assert_aligned(F_TWO_4A,16); - - LLVector4a two; two.load4a( F_TWO_4A ); - - // Here we use _mm_rcp_ps plus one round of newton-raphson - // We wish to find 'x' such that x = 1/delta - // As a first approximation, we take x0 = _mm_rcp_ps(delta) - // Then x1 = 2 * x0 - a * x0^2 or x1 = x0 * ( 2 - a * x0 ) - // See Intel AP-803 http://ompf.org/!/Intel_application_note_AP-803.pdf - const LLVector4a recipApprox = _mm_rcp_ps(delta.mQ); - oneOverDelta.setMul( delta, recipApprox ); - oneOverDelta.setSub( two, oneOverDelta ); - oneOverDelta.mul( recipApprox ); - } - - val.mul(oneOverDelta); - val.mul(*reinterpret_cast<const LLVector4a*>(F_U16MAX_4A)); - } - - val = _mm_cvtepi32_ps(_mm_cvtps_epi32( val.mQ )); - - { - val.mul(*reinterpret_cast<const LLVector4a*>(F_OOU16MAX_4A)); - val.mul(delta); - val.add(low); - } - - { - LLVector4a maxError; maxError.setMul(delta, *reinterpret_cast<const LLVector4a*>(F_OOU16MAX_4A)); - LLVector4a absVal; absVal.setAbs( val ); - setSelectWithMask( absVal.lessThan( maxError ), F_ZERO_4A, val ); - } + LLVector4a val(mQ); + LLVector4a delta; delta.setSub( high, low ); + + { + val.clamp(low, high); + val.sub(low); + + // 16-bit quantization means we need a round of Newton-Raphson + LLVector4a oneOverDelta; + { + static LL_ALIGN_16( const F32 F_TWO_4A[4] ) = { 2.f, 2.f, 2.f, 2.f }; + ll_assert_aligned(F_TWO_4A,16); + + LLVector4a two; two.load4a( F_TWO_4A ); + + // Here we use _mm_rcp_ps plus one round of newton-raphson + // We wish to find 'x' such that x = 1/delta + // As a first approximation, we take x0 = _mm_rcp_ps(delta) + // Then x1 = 2 * x0 - a * x0^2 or x1 = x0 * ( 2 - a * x0 ) + // See Intel AP-803 http://ompf.org/!/Intel_application_note_AP-803.pdf + const LLVector4a recipApprox = _mm_rcp_ps(delta.mQ); + oneOverDelta.setMul( delta, recipApprox ); + oneOverDelta.setSub( two, oneOverDelta ); + oneOverDelta.mul( recipApprox ); + } + + val.mul(oneOverDelta); + val.mul(*reinterpret_cast<const LLVector4a*>(F_U16MAX_4A)); + } + + val = _mm_cvtepi32_ps(_mm_cvtps_epi32( val.mQ )); + + { + val.mul(*reinterpret_cast<const LLVector4a*>(F_OOU16MAX_4A)); + val.mul(delta); + val.add(low); + } + + { + LLVector4a maxError; maxError.setMul(delta, *reinterpret_cast<const LLVector4a*>(F_OOU16MAX_4A)); + LLVector4a absVal; absVal.setAbs( val ); + setSelectWithMask( absVal.lessThan( maxError ), F_ZERO_4A, val ); + } } diff --git a/indra/llmath/llvector4a.h b/indra/llmath/llvector4a.h index 53c8f604f6..8f0ee4b739 100644 --- a/indra/llmath/llvector4a.h +++ b/indra/llmath/llvector4a.h @@ -1,31 +1,31 @@ -/** +/** * @file llvector4a.h * @brief LLVector4a class header file - memory aligned and vectorized 4 component vector * * $LicenseInfo:firstyear=2010&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ -#ifndef LL_LLVECTOR4A_H -#define LL_LLVECTOR4A_H +#ifndef LL_LLVECTOR4A_H +#define LL_LLVECTOR4A_H class LLRotation; @@ -40,11 +40,11 @@ class LLRotation; // This is just the beginning of LLVector4a. There are many more useful functions // yet to be implemented. For example, setNeg to negate a vector, rotate() to apply // a matrix rotation, various functions to manipulate only the X, Y, and Z elements -// and many others (including a whole variety of accessors). So if you don't see a -// function here that you need, please contact Falcon or someone else with SSE -// experience (Richard, I think, has some and davep has a little as of the time +// and many others (including a whole variety of accessors). So if you don't see a +// function here that you need, please contact Falcon or someone else with SSE +// experience (Richard, I think, has some and davep has a little as of the time // of this writing, July 08, 2010) about getting it implemented before you resort to -// LLVector3/LLVector4. +// LLVector3/LLVector4. ///////////////////////////////// class alignas(16) LLVector4a @@ -52,283 +52,283 @@ class alignas(16) LLVector4a LL_ALIGN_NEW public: - /////////////////////////////////// - // STATIC METHODS - /////////////////////////////////// - - // Call initClass() at startup to avoid 15,000+ cycle penalties from denormalized numbers - static void initClass() - { - _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); - _MM_SET_ROUNDING_MODE(_MM_ROUND_NEAREST); - } - - // Return a vector of all zeros - static inline const LLVector4a& getZero() - { - extern const LLVector4a LL_V4A_ZERO; - return LL_V4A_ZERO; - } - - // Return a vector of all epsilon, where epsilon is a small float suitable for approximate equality checks - static inline const LLVector4a& getEpsilon() - { - extern const LLVector4a LL_V4A_EPSILON; - return LL_V4A_EPSILON; - } - - // Copy 16 bytes from src to dst. Source and destination must be 16-byte aligned - static inline void copy4a(F32* dst, const F32* src) - { - _mm_store_ps(dst, _mm_load_ps(src)); - } - - // Copy words 16-byte blocks from src to dst. Source and destination must not overlap. - // Source and dest must be 16-byte aligned and size must be multiple of 16. - static void memcpyNonAliased16(F32* __restrict dst, const F32* __restrict src, size_t bytes); - - //////////////////////////////////// - // CONSTRUCTORS - //////////////////////////////////// - - //LLVector4a is plain data which should never have a default constructor or destructor(malloc&free won't trigger it) - LLVector4a() - { //DO NOT INITIALIZE -- The overhead is completely unnecessary - ll_assert_aligned(this,16); - } - - LLVector4a(F32 x, F32 y, F32 z, F32 w = 0.f) - { - set(x,y,z,w); - } - - LLVector4a(F32 x) - { - splat(x); - } - - LLVector4a(const LLSimdScalar& x) - { - splat(x); - } - - LLVector4a(LLQuad q) - { - mQ = q; - } - - //////////////////////////////////// - // LOAD/STORE - //////////////////////////////////// - - // Load from 16-byte aligned src array (preferred method of loading) - inline void load4a(const F32* src); - - // Load from unaligned src array (NB: Significantly slower than load4a) - inline void loadua(const F32* src); - - // Load only three floats beginning at address 'src'. Slowest method. - inline void load3(const F32* src); - - // Store to a 16-byte aligned memory address - inline void store4a(F32* dst) const; - - //////////////////////////////////// - // BASIC GET/SET - //////////////////////////////////// - - // Return a "this" as an F32 pointer. - inline F32* getF32ptr(); - - // Return a "this" as a const F32 pointer. - inline const F32* const getF32ptr() const; - - // Read-only access a single float in this vector. Do not use in proximity to any function call that manipulates - // the data at the whole vector level or you will incur a substantial penalty. Consider using the splat functions instead - inline F32 operator[](const S32 idx) const; - - // Prefer this method for read-only access to a single element. Prefer the templated version if the elem is known at compile time. - inline LLSimdScalar getScalarAt(const S32 idx) const; - - // Prefer this method for read-only access to a single element. Prefer the templated version if the elem is known at compile time. - template <int N> LL_FORCE_INLINE LLSimdScalar getScalarAt() const; - - // Set to an x, y, z and optional w provided - inline void set(F32 x, F32 y, F32 z, F32 w = 0.f); - - // Set to all zeros. This is preferred to using ::getZero() - inline void clear(); - - // Set all elements to 'x' - inline void splat(const F32 x); - - // Set all elements to 'x' - inline void splat(const LLSimdScalar& x); - - // Set all 4 elements to element N of src, with N known at compile time - template <int N> void splat(const LLVector4a& src); - - // Set all 4 elements to element i of v, with i NOT known at compile time - inline void splat(const LLVector4a& v, U32 i); - - // Select bits from sourceIfTrue and sourceIfFalse according to bits in mask - inline void setSelectWithMask( const LLVector4Logical& mask, const LLVector4a& sourceIfTrue, const LLVector4a& sourceIfFalse ); - - //////////////////////////////////// - // ALGEBRAIC - //////////////////////////////////// - - // Set this to the element-wise (a + b) - inline void setAdd(const LLVector4a& a, const LLVector4a& b); - - // Set this to element-wise (a - b) - inline void setSub(const LLVector4a& a, const LLVector4a& b); - - // Set this to element-wise multiply (a * b) - inline void setMul(const LLVector4a& a, const LLVector4a& b); - - // Set this to element-wise quotient (a / b) - inline void setDiv(const LLVector4a& a, const LLVector4a& b); - - // Set this to the element-wise absolute value of src - inline void setAbs(const LLVector4a& src); - - // Add to each component in this vector the corresponding component in rhs - inline void add(const LLVector4a& rhs); - - // Subtract from each component in this vector the corresponding component in rhs - inline void sub(const LLVector4a& rhs); - - // Multiply each component in this vector by the corresponding component in rhs - inline void mul(const LLVector4a& rhs); - - // Divide each component in this vector by the corresponding component in rhs - inline void div(const LLVector4a& rhs); - - // Multiply this vector by x in a scalar fashion - inline void mul(const F32 x); - - // Set this to (a x b) (geometric cross-product) - inline void setCross3(const LLVector4a& a, const LLVector4a& b); - - // Set all elements to the dot product of the x, y, and z elements in a and b - inline void setAllDot3(const LLVector4a& a, const LLVector4a& b); - - // Set all elements to the dot product of the x, y, z, and w elements in a and b - inline void setAllDot4(const LLVector4a& a, const LLVector4a& b); - - // Return the 3D dot product of this vector and b - inline LLSimdScalar dot3(const LLVector4a& b) const; - - // Return the 4D dot product of this vector and b - inline LLSimdScalar dot4(const LLVector4a& b) const; - - // Normalize this vector with respect to the x, y, and z components only. Accurate to 22 bites of precision. W component is destroyed - // Note that this does not consider zero length vectors! - inline void normalize3(); - - // Same as normalize3() but with respect to all 4 components - inline void normalize4(); - - // Same as normalize3(), but returns length as a SIMD scalar - inline LLSimdScalar normalize3withLength(); - - // Normalize this vector with respect to the x, y, and z components only. Accurate only to 10-12 bits of precision. W component is destroyed - // Note that this does not consider zero length vectors! - inline void normalize3fast(); - - // Normalize this vector with respect to the x, y, and z components only. Accurate only to 10-12 bits of precision. W component is destroyed - // Same as above except substitutes default vector contents if the vector is non-finite or degenerate due to zero length. - // - inline void normalize3fast_checked(LLVector4a* d = 0); - - // Return true if this vector is normalized with respect to x,y,z up to tolerance - inline LLBool32 isNormalized3( F32 tolerance = 1e-3 ) const; - - // Return true if this vector is normalized with respect to all components up to tolerance - inline LLBool32 isNormalized4( F32 tolerance = 1e-3 ) const; - - // Set all elements to the length of vector 'v' - inline void setAllLength3( const LLVector4a& v ); - - // Get this vector's length - inline LLSimdScalar getLength3() const; - - // Set the components of this vector to the minimum of the corresponding components of lhs and rhs - inline void setMin(const LLVector4a& lhs, const LLVector4a& rhs); - - // Set the components of this vector to the maximum of the corresponding components of lhs and rhs - inline void setMax(const LLVector4a& lhs, const LLVector4a& rhs); - - // Clamps this vector to be within the component-wise range low to high (inclusive) - inline void clamp( const LLVector4a& low, const LLVector4a& high ); - - // Set this to (c * lhs) + rhs * ( 1 - c) - inline void setLerp(const LLVector4a& lhs, const LLVector4a& rhs, F32 c); - - // Return true (nonzero) if x, y, z (and w for Finite4) are all finite floats - inline LLBool32 isFinite3() const; - inline LLBool32 isFinite4() const; - - // Set this vector to 'vec' rotated by the LLRotation or LLQuaternion2 provided - void setRotated( const LLRotation& rot, const LLVector4a& vec ); - void setRotated( const class LLQuaternion2& quat, const LLVector4a& vec ); - - // Set this vector to 'vec' rotated by the INVERSE of the LLRotation or LLQuaternion2 provided - inline void setRotatedInv( const LLRotation& rot, const LLVector4a& vec ); - inline void setRotatedInv( const class LLQuaternion2& quat, const LLVector4a& vec ); - - // Quantize this vector to 8 or 16 bit precision - void quantize8( const LLVector4a& low, const LLVector4a& high ); - void quantize16( const LLVector4a& low, const LLVector4a& high ); - - //////////////////////////////////// - // LOGICAL - //////////////////////////////////// - // The functions in this section will compare the elements in this vector - // to those in rhs and return an LLVector4Logical with all bits set in elements - // where the comparison was true and all bits unset in elements where the comparison - // was false. See llvector4logica.h - //////////////////////////////////// - // WARNING: Other than equals3 and equals4, these functions do NOT account - // for floating point tolerance. You should include the appropriate tolerance - // in the inputs. - //////////////////////////////////// - - inline LLVector4Logical greaterThan(const LLVector4a& rhs) const; - - inline LLVector4Logical lessThan(const LLVector4a& rhs) const; - - inline LLVector4Logical greaterEqual(const LLVector4a& rhs) const; - - inline LLVector4Logical lessEqual(const LLVector4a& rhs) const; - - inline LLVector4Logical equal(const LLVector4a& rhs) const; - - // Returns true if this and rhs are componentwise equal up to the specified absolute tolerance - inline bool equals4(const LLVector4a& rhs, F32 tolerance = F_APPROXIMATELY_ZERO ) const; - - inline bool equals3(const LLVector4a& rhs, F32 tolerance = F_APPROXIMATELY_ZERO ) const; - - //////////////////////////////////// - // OPERATORS - //////////////////////////////////// - - // Do NOT add aditional operators without consulting someone with SSE experience - inline const LLVector4a& operator= ( const LLVector4a& rhs ); - - inline const LLVector4a& operator= ( const LLQuad& rhs ); - - inline operator LLQuad() const; - + /////////////////////////////////// + // STATIC METHODS + /////////////////////////////////// + + // Call initClass() at startup to avoid 15,000+ cycle penalties from denormalized numbers + static void initClass() + { + _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); + _MM_SET_ROUNDING_MODE(_MM_ROUND_NEAREST); + } + + // Return a vector of all zeros + static inline const LLVector4a& getZero() + { + extern const LLVector4a LL_V4A_ZERO; + return LL_V4A_ZERO; + } + + // Return a vector of all epsilon, where epsilon is a small float suitable for approximate equality checks + static inline const LLVector4a& getEpsilon() + { + extern const LLVector4a LL_V4A_EPSILON; + return LL_V4A_EPSILON; + } + + // Copy 16 bytes from src to dst. Source and destination must be 16-byte aligned + static inline void copy4a(F32* dst, const F32* src) + { + _mm_store_ps(dst, _mm_load_ps(src)); + } + + // Copy words 16-byte blocks from src to dst. Source and destination must not overlap. + // Source and dest must be 16-byte aligned and size must be multiple of 16. + static void memcpyNonAliased16(F32* __restrict dst, const F32* __restrict src, size_t bytes); + + //////////////////////////////////// + // CONSTRUCTORS + //////////////////////////////////// + + //LLVector4a is plain data which should never have a default constructor or destructor(malloc&free won't trigger it) + LLVector4a() + { //DO NOT INITIALIZE -- The overhead is completely unnecessary + ll_assert_aligned(this,16); + } + + LLVector4a(F32 x, F32 y, F32 z, F32 w = 0.f) + { + set(x,y,z,w); + } + + LLVector4a(F32 x) + { + splat(x); + } + + LLVector4a(const LLSimdScalar& x) + { + splat(x); + } + + LLVector4a(LLQuad q) + { + mQ = q; + } + + //////////////////////////////////// + // LOAD/STORE + //////////////////////////////////// + + // Load from 16-byte aligned src array (preferred method of loading) + inline void load4a(const F32* src); + + // Load from unaligned src array (NB: Significantly slower than load4a) + inline void loadua(const F32* src); + + // Load only three floats beginning at address 'src'. Slowest method. + inline void load3(const F32* src); + + // Store to a 16-byte aligned memory address + inline void store4a(F32* dst) const; + + //////////////////////////////////// + // BASIC GET/SET + //////////////////////////////////// + + // Return a "this" as an F32 pointer. + inline F32* getF32ptr(); + + // Return a "this" as a const F32 pointer. + inline const F32* const getF32ptr() const; + + // Read-only access a single float in this vector. Do not use in proximity to any function call that manipulates + // the data at the whole vector level or you will incur a substantial penalty. Consider using the splat functions instead + inline F32 operator[](const S32 idx) const; + + // Prefer this method for read-only access to a single element. Prefer the templated version if the elem is known at compile time. + inline LLSimdScalar getScalarAt(const S32 idx) const; + + // Prefer this method for read-only access to a single element. Prefer the templated version if the elem is known at compile time. + template <int N> LL_FORCE_INLINE LLSimdScalar getScalarAt() const; + + // Set to an x, y, z and optional w provided + inline void set(F32 x, F32 y, F32 z, F32 w = 0.f); + + // Set to all zeros. This is preferred to using ::getZero() + inline void clear(); + + // Set all elements to 'x' + inline void splat(const F32 x); + + // Set all elements to 'x' + inline void splat(const LLSimdScalar& x); + + // Set all 4 elements to element N of src, with N known at compile time + template <int N> void splat(const LLVector4a& src); + + // Set all 4 elements to element i of v, with i NOT known at compile time + inline void splat(const LLVector4a& v, U32 i); + + // Select bits from sourceIfTrue and sourceIfFalse according to bits in mask + inline void setSelectWithMask( const LLVector4Logical& mask, const LLVector4a& sourceIfTrue, const LLVector4a& sourceIfFalse ); + + //////////////////////////////////// + // ALGEBRAIC + //////////////////////////////////// + + // Set this to the element-wise (a + b) + inline void setAdd(const LLVector4a& a, const LLVector4a& b); + + // Set this to element-wise (a - b) + inline void setSub(const LLVector4a& a, const LLVector4a& b); + + // Set this to element-wise multiply (a * b) + inline void setMul(const LLVector4a& a, const LLVector4a& b); + + // Set this to element-wise quotient (a / b) + inline void setDiv(const LLVector4a& a, const LLVector4a& b); + + // Set this to the element-wise absolute value of src + inline void setAbs(const LLVector4a& src); + + // Add to each component in this vector the corresponding component in rhs + inline void add(const LLVector4a& rhs); + + // Subtract from each component in this vector the corresponding component in rhs + inline void sub(const LLVector4a& rhs); + + // Multiply each component in this vector by the corresponding component in rhs + inline void mul(const LLVector4a& rhs); + + // Divide each component in this vector by the corresponding component in rhs + inline void div(const LLVector4a& rhs); + + // Multiply this vector by x in a scalar fashion + inline void mul(const F32 x); + + // Set this to (a x b) (geometric cross-product) + inline void setCross3(const LLVector4a& a, const LLVector4a& b); + + // Set all elements to the dot product of the x, y, and z elements in a and b + inline void setAllDot3(const LLVector4a& a, const LLVector4a& b); + + // Set all elements to the dot product of the x, y, z, and w elements in a and b + inline void setAllDot4(const LLVector4a& a, const LLVector4a& b); + + // Return the 3D dot product of this vector and b + inline LLSimdScalar dot3(const LLVector4a& b) const; + + // Return the 4D dot product of this vector and b + inline LLSimdScalar dot4(const LLVector4a& b) const; + + // Normalize this vector with respect to the x, y, and z components only. Accurate to 22 bites of precision. W component is destroyed + // Note that this does not consider zero length vectors! + inline void normalize3(); + + // Same as normalize3() but with respect to all 4 components + inline void normalize4(); + + // Same as normalize3(), but returns length as a SIMD scalar + inline LLSimdScalar normalize3withLength(); + + // Normalize this vector with respect to the x, y, and z components only. Accurate only to 10-12 bits of precision. W component is destroyed + // Note that this does not consider zero length vectors! + inline void normalize3fast(); + + // Normalize this vector with respect to the x, y, and z components only. Accurate only to 10-12 bits of precision. W component is destroyed + // Same as above except substitutes default vector contents if the vector is non-finite or degenerate due to zero length. + // + inline void normalize3fast_checked(LLVector4a* d = 0); + + // Return true if this vector is normalized with respect to x,y,z up to tolerance + inline LLBool32 isNormalized3( F32 tolerance = 1e-3 ) const; + + // Return true if this vector is normalized with respect to all components up to tolerance + inline LLBool32 isNormalized4( F32 tolerance = 1e-3 ) const; + + // Set all elements to the length of vector 'v' + inline void setAllLength3( const LLVector4a& v ); + + // Get this vector's length + inline LLSimdScalar getLength3() const; + + // Set the components of this vector to the minimum of the corresponding components of lhs and rhs + inline void setMin(const LLVector4a& lhs, const LLVector4a& rhs); + + // Set the components of this vector to the maximum of the corresponding components of lhs and rhs + inline void setMax(const LLVector4a& lhs, const LLVector4a& rhs); + + // Clamps this vector to be within the component-wise range low to high (inclusive) + inline void clamp( const LLVector4a& low, const LLVector4a& high ); + + // Set this to (c * lhs) + rhs * ( 1 - c) + inline void setLerp(const LLVector4a& lhs, const LLVector4a& rhs, F32 c); + + // Return true (nonzero) if x, y, z (and w for Finite4) are all finite floats + inline LLBool32 isFinite3() const; + inline LLBool32 isFinite4() const; + + // Set this vector to 'vec' rotated by the LLRotation or LLQuaternion2 provided + void setRotated( const LLRotation& rot, const LLVector4a& vec ); + void setRotated( const class LLQuaternion2& quat, const LLVector4a& vec ); + + // Set this vector to 'vec' rotated by the INVERSE of the LLRotation or LLQuaternion2 provided + inline void setRotatedInv( const LLRotation& rot, const LLVector4a& vec ); + inline void setRotatedInv( const class LLQuaternion2& quat, const LLVector4a& vec ); + + // Quantize this vector to 8 or 16 bit precision + void quantize8( const LLVector4a& low, const LLVector4a& high ); + void quantize16( const LLVector4a& low, const LLVector4a& high ); + + //////////////////////////////////// + // LOGICAL + //////////////////////////////////// + // The functions in this section will compare the elements in this vector + // to those in rhs and return an LLVector4Logical with all bits set in elements + // where the comparison was true and all bits unset in elements where the comparison + // was false. See llvector4logica.h + //////////////////////////////////// + // WARNING: Other than equals3 and equals4, these functions do NOT account + // for floating point tolerance. You should include the appropriate tolerance + // in the inputs. + //////////////////////////////////// + + inline LLVector4Logical greaterThan(const LLVector4a& rhs) const; + + inline LLVector4Logical lessThan(const LLVector4a& rhs) const; + + inline LLVector4Logical greaterEqual(const LLVector4a& rhs) const; + + inline LLVector4Logical lessEqual(const LLVector4a& rhs) const; + + inline LLVector4Logical equal(const LLVector4a& rhs) const; + + // Returns true if this and rhs are componentwise equal up to the specified absolute tolerance + inline bool equals4(const LLVector4a& rhs, F32 tolerance = F_APPROXIMATELY_ZERO ) const; + + inline bool equals3(const LLVector4a& rhs, F32 tolerance = F_APPROXIMATELY_ZERO ) const; + + //////////////////////////////////// + // OPERATORS + //////////////////////////////////// + + // Do NOT add aditional operators without consulting someone with SSE experience + inline const LLVector4a& operator= ( const LLVector4a& rhs ); + + inline const LLVector4a& operator= ( const LLQuad& rhs ); + + inline operator LLQuad() const; + private: - LLQuad mQ; + LLQuad mQ; }; inline void update_min_max(LLVector4a& min, LLVector4a& max, const LLVector4a& p) { - min.setMin(min, p); - max.setMax(max, p); + min.setMin(min, p); + max.setMax(max, p); } inline std::ostream& operator<<(std::ostream& s, const LLVector4a& v) diff --git a/indra/llmath/llvector4a.inl b/indra/llmath/llvector4a.inl index 8be1c1b114..36dbec078c 100644 --- a/indra/llmath/llvector4a.inl +++ b/indra/llmath/llvector4a.inl @@ -1,25 +1,25 @@ -/** +/** * @file llvector4a.inl * @brief LLVector4a inline function implementations * * $LicenseInfo:firstyear=2010&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -31,138 +31,138 @@ // Load from 16-byte aligned src array (preferred method of loading) inline void LLVector4a::load4a(const F32* src) { - mQ = _mm_load_ps(src); + mQ = _mm_load_ps(src); } // Load from unaligned src array (NB: Significantly slower than load4a) inline void LLVector4a::loadua(const F32* src) { - mQ = _mm_loadu_ps(src); + mQ = _mm_loadu_ps(src); } // Load only three floats beginning at address 'src'. Slowest method. inline void LLVector4a::load3(const F32* src) { - // mQ = { 0.f, src[2], src[1], src[0] } = { W, Z, Y, X } - // NB: This differs from the convention of { Z, Y, X, W } - mQ = _mm_set_ps(0.f, src[2], src[1], src[0]); -} + // mQ = { 0.f, src[2], src[1], src[0] } = { W, Z, Y, X } + // NB: This differs from the convention of { Z, Y, X, W } + mQ = _mm_set_ps(0.f, src[2], src[1], src[0]); +} // Store to a 16-byte aligned memory address inline void LLVector4a::store4a(F32* dst) const { - _mm_store_ps(dst, mQ); + _mm_store_ps(dst, mQ); } //////////////////////////////////// -// BASIC GET/SET +// BASIC GET/SET //////////////////////////////////// // Return a "this" as an F32 pointer. F32* LLVector4a::getF32ptr() { - return (F32*) &mQ; + return (F32*) &mQ; } // Return a "this" as a const F32 pointer. const F32* const LLVector4a::getF32ptr() const { - return (const F32* const) &mQ; + return (const F32* const) &mQ; } // Read-only access a single float in this vector. Do not use in proximity to any function call that manipulates // the data at the whole vector level or you will incur a substantial penalty. Consider using the splat functions instead inline F32 LLVector4a::operator[](const S32 idx) const { - return ((F32*)&mQ)[idx]; -} + return ((F32*)&mQ)[idx]; +} // Prefer this method for read-only access to a single element. Prefer the templated version if the elem is known at compile time. inline LLSimdScalar LLVector4a::getScalarAt(const S32 idx) const { - // Return appropriate LLQuad. It will be cast to LLSimdScalar automatically (should be effectively a nop) - switch (idx) - { - case 0: - return mQ; - case 1: - return _mm_shuffle_ps(mQ, mQ, _MM_SHUFFLE(1, 1, 1, 1)); - case 2: - return _mm_shuffle_ps(mQ, mQ, _MM_SHUFFLE(2, 2, 2, 2)); - case 3: - default: - return _mm_shuffle_ps(mQ, mQ, _MM_SHUFFLE(3, 3, 3, 3)); - } + // Return appropriate LLQuad. It will be cast to LLSimdScalar automatically (should be effectively a nop) + switch (idx) + { + case 0: + return mQ; + case 1: + return _mm_shuffle_ps(mQ, mQ, _MM_SHUFFLE(1, 1, 1, 1)); + case 2: + return _mm_shuffle_ps(mQ, mQ, _MM_SHUFFLE(2, 2, 2, 2)); + case 3: + default: + return _mm_shuffle_ps(mQ, mQ, _MM_SHUFFLE(3, 3, 3, 3)); + } } // Prefer this method for read-only access to a single element. Prefer the templated version if the elem is known at compile time. template <int N> LL_FORCE_INLINE LLSimdScalar LLVector4a::getScalarAt() const { - return _mm_shuffle_ps(mQ, mQ, _MM_SHUFFLE(N, N, N, N)); + return _mm_shuffle_ps(mQ, mQ, _MM_SHUFFLE(N, N, N, N)); } template<> LL_FORCE_INLINE LLSimdScalar LLVector4a::getScalarAt<0>() const { - return mQ; + return mQ; } // Set to an x, y, z and optional w provided inline void LLVector4a::set(F32 x, F32 y, F32 z, F32 w) { - mQ = _mm_set_ps(w, z, y, x); + mQ = _mm_set_ps(w, z, y, x); } // Set to all zeros inline void LLVector4a::clear() { - mQ = LLVector4a::getZero().mQ; + mQ = LLVector4a::getZero().mQ; } inline void LLVector4a::splat(const F32 x) { - mQ = _mm_set1_ps(x); + mQ = _mm_set1_ps(x); } inline void LLVector4a::splat(const LLSimdScalar& x) { - mQ = _mm_shuffle_ps( x.getQuad(), x.getQuad(), _MM_SHUFFLE(0,0,0,0) ); + mQ = _mm_shuffle_ps( x.getQuad(), x.getQuad(), _MM_SHUFFLE(0,0,0,0) ); } // Set all 4 elements to element N of src, with N known at compile time template <int N> void LLVector4a::splat(const LLVector4a& src) { - mQ = _mm_shuffle_ps(src.mQ, src.mQ, _MM_SHUFFLE(N, N, N, N) ); + mQ = _mm_shuffle_ps(src.mQ, src.mQ, _MM_SHUFFLE(N, N, N, N) ); } // Set all 4 elements to element i of v, with i NOT known at compile time inline void LLVector4a::splat(const LLVector4a& v, U32 i) { - switch (i) - { - case 0: - mQ = _mm_shuffle_ps(v.mQ, v.mQ, _MM_SHUFFLE(0, 0, 0, 0)); - break; - case 1: - mQ = _mm_shuffle_ps(v.mQ, v.mQ, _MM_SHUFFLE(1, 1, 1, 1)); - break; - case 2: - mQ = _mm_shuffle_ps(v.mQ, v.mQ, _MM_SHUFFLE(2, 2, 2, 2)); - break; - case 3: - mQ = _mm_shuffle_ps(v.mQ, v.mQ, _MM_SHUFFLE(3, 3, 3, 3)); - break; - } + switch (i) + { + case 0: + mQ = _mm_shuffle_ps(v.mQ, v.mQ, _MM_SHUFFLE(0, 0, 0, 0)); + break; + case 1: + mQ = _mm_shuffle_ps(v.mQ, v.mQ, _MM_SHUFFLE(1, 1, 1, 1)); + break; + case 2: + mQ = _mm_shuffle_ps(v.mQ, v.mQ, _MM_SHUFFLE(2, 2, 2, 2)); + break; + case 3: + mQ = _mm_shuffle_ps(v.mQ, v.mQ, _MM_SHUFFLE(3, 3, 3, 3)); + break; + } } // Select bits from sourceIfTrue and sourceIfFalse according to bits in mask inline void LLVector4a::setSelectWithMask( const LLVector4Logical& mask, const LLVector4a& sourceIfTrue, const LLVector4a& sourceIfFalse ) { - // ((( sourceIfTrue ^ sourceIfFalse ) & mask) ^ sourceIfFalse ) - // E.g., sourceIfFalse = 1010b, sourceIfTrue = 0101b, mask = 1100b - // (sourceIfTrue ^ sourceIfFalse) = 1111b --> & mask = 1100b --> ^ sourceIfFalse = 0110b, - // as expected (01 from sourceIfTrue, 10 from sourceIfFalse) - // Courtesy of Mark++, http://markplusplus.wordpress.com/2007/03/14/fast-sse-select-operation/ - mQ = _mm_xor_ps( sourceIfFalse, _mm_and_ps( mask, _mm_xor_ps( sourceIfTrue, sourceIfFalse ) ) ); + // ((( sourceIfTrue ^ sourceIfFalse ) & mask) ^ sourceIfFalse ) + // E.g., sourceIfFalse = 1010b, sourceIfTrue = 0101b, mask = 1100b + // (sourceIfTrue ^ sourceIfFalse) = 1111b --> & mask = 1100b --> ^ sourceIfFalse = 0110b, + // as expected (01 from sourceIfTrue, 10 from sourceIfFalse) + // Courtesy of Mark++, http://markplusplus.wordpress.com/2007/03/14/fast-sse-select-operation/ + mQ = _mm_xor_ps( sourceIfFalse, _mm_and_ps( mask, _mm_xor_ps( sourceIfTrue, sourceIfFalse ) ) ); } //////////////////////////////////// @@ -172,84 +172,84 @@ inline void LLVector4a::setSelectWithMask( const LLVector4Logical& mask, const L // Set this to the element-wise (a + b) inline void LLVector4a::setAdd(const LLVector4a& a, const LLVector4a& b) { - mQ = _mm_add_ps(a.mQ, b.mQ); + mQ = _mm_add_ps(a.mQ, b.mQ); } // Set this to element-wise (a - b) inline void LLVector4a::setSub(const LLVector4a& a, const LLVector4a& b) { - mQ = _mm_sub_ps(a.mQ, b.mQ); + mQ = _mm_sub_ps(a.mQ, b.mQ); } // Set this to element-wise multiply (a * b) inline void LLVector4a::setMul(const LLVector4a& a, const LLVector4a& b) { - mQ = _mm_mul_ps(a.mQ, b.mQ); + mQ = _mm_mul_ps(a.mQ, b.mQ); } // Set this to element-wise quotient (a / b) inline void LLVector4a::setDiv(const LLVector4a& a, const LLVector4a& b) { - mQ = _mm_div_ps( a.mQ, b.mQ ); + mQ = _mm_div_ps( a.mQ, b.mQ ); } // Set this to the element-wise absolute value of src inline void LLVector4a::setAbs(const LLVector4a& src) { - static const LL_ALIGN_16(U32 F_ABS_MASK_4A[4]) = { 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF }; - mQ = _mm_and_ps(src.mQ, *reinterpret_cast<const LLQuad*>(F_ABS_MASK_4A)); + static const LL_ALIGN_16(U32 F_ABS_MASK_4A[4]) = { 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF }; + mQ = _mm_and_ps(src.mQ, *reinterpret_cast<const LLQuad*>(F_ABS_MASK_4A)); } // Add to each component in this vector the corresponding component in rhs inline void LLVector4a::add(const LLVector4a& rhs) { - mQ = _mm_add_ps(mQ, rhs.mQ); + mQ = _mm_add_ps(mQ, rhs.mQ); } // Subtract from each component in this vector the corresponding component in rhs inline void LLVector4a::sub(const LLVector4a& rhs) { - mQ = _mm_sub_ps(mQ, rhs.mQ); + mQ = _mm_sub_ps(mQ, rhs.mQ); } // Multiply each component in this vector by the corresponding component in rhs inline void LLVector4a::mul(const LLVector4a& rhs) { - mQ = _mm_mul_ps(mQ, rhs.mQ); + mQ = _mm_mul_ps(mQ, rhs.mQ); } // Divide each component in this vector by the corresponding component in rhs inline void LLVector4a::div(const LLVector4a& rhs) { - // TODO: Check accuracy, maybe add divFast - mQ = _mm_div_ps(mQ, rhs.mQ); + // TODO: Check accuracy, maybe add divFast + mQ = _mm_div_ps(mQ, rhs.mQ); } // Multiply this vector by x in a scalar fashion -inline void LLVector4a::mul(const F32 x) +inline void LLVector4a::mul(const F32 x) { - LLVector4a t; - t.splat(x); - - mQ = _mm_mul_ps(mQ, t.mQ); + LLVector4a t; + t.splat(x); + + mQ = _mm_mul_ps(mQ, t.mQ); } // Set this to (a x b) (geometric cross-product) inline void LLVector4a::setCross3(const LLVector4a& a, const LLVector4a& b) { - // Vectors are stored in memory in w, z, y, x order from high to low - // Set vector1 = { a[W], a[X], a[Z], a[Y] } - const LLQuad vector1 = _mm_shuffle_ps( a.mQ, a.mQ, _MM_SHUFFLE( 3, 0, 2, 1 )); - // Set vector2 = { b[W], b[Y], b[X], b[Z] } - const LLQuad vector2 = _mm_shuffle_ps( b.mQ, b.mQ, _MM_SHUFFLE( 3, 1, 0, 2 )); - // mQ = { a[W]*b[W], a[X]*b[Y], a[Z]*b[X], a[Y]*b[Z] } - mQ = _mm_mul_ps( vector1, vector2 ); - // vector3 = { a[W], a[Y], a[X], a[Z] } - const LLQuad vector3 = _mm_shuffle_ps( a.mQ, a.mQ, _MM_SHUFFLE( 3, 1, 0, 2 )); - // vector4 = { b[W], b[X], b[Z], b[Y] } - const LLQuad vector4 = _mm_shuffle_ps( b.mQ, b.mQ, _MM_SHUFFLE( 3, 0, 2, 1 )); - // mQ = { 0, a[X]*b[Y] - a[Y]*b[X], a[Z]*b[X] - a[X]*b[Z], a[Y]*b[Z] - a[Z]*b[Y] } - mQ = _mm_sub_ps( mQ, _mm_mul_ps( vector3, vector4 )); + // Vectors are stored in memory in w, z, y, x order from high to low + // Set vector1 = { a[W], a[X], a[Z], a[Y] } + const LLQuad vector1 = _mm_shuffle_ps( a.mQ, a.mQ, _MM_SHUFFLE( 3, 0, 2, 1 )); + // Set vector2 = { b[W], b[Y], b[X], b[Z] } + const LLQuad vector2 = _mm_shuffle_ps( b.mQ, b.mQ, _MM_SHUFFLE( 3, 1, 0, 2 )); + // mQ = { a[W]*b[W], a[X]*b[Y], a[Z]*b[X], a[Y]*b[Z] } + mQ = _mm_mul_ps( vector1, vector2 ); + // vector3 = { a[W], a[Y], a[X], a[Z] } + const LLQuad vector3 = _mm_shuffle_ps( a.mQ, a.mQ, _MM_SHUFFLE( 3, 1, 0, 2 )); + // vector4 = { b[W], b[X], b[Z], b[Y] } + const LLQuad vector4 = _mm_shuffle_ps( b.mQ, b.mQ, _MM_SHUFFLE( 3, 0, 2, 1 )); + // mQ = { 0, a[X]*b[Y] - a[Y]*b[X], a[Z]*b[X] - a[X]*b[Z], a[Y]*b[Z] - a[Z]*b[Y] } + mQ = _mm_sub_ps( mQ, _mm_mul_ps( vector3, vector4 )); } /* This function works, but may be slightly slower than the one below on older machines @@ -261,7 +261,7 @@ inline void LLVector4a::setCross3(const LLVector4a& a, const LLVector4a& b) const LLQuad wzxy = _mm_shuffle_ps( ab, ab, _MM_SHUFFLE(3, 2, 0, 1 )); // xPlusY = { 2*a[W]*b[W], 2 * a[Z] * b[Z], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } const LLQuad xPlusY = _mm_add_ps(ab, wzxy); - // xPlusYSplat = { a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } + // xPlusYSplat = { a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } const LLQuad xPlusYSplat = _mm_movelh_ps(xPlusY, xPlusY); // zSplat = { a[Z]*b[Z], a[Z]*b[Z], a[Z]*b[Z], a[Z]*b[Z] } const LLQuad zSplat = _mm_shuffle_ps( ab, ab, _MM_SHUFFLE( 2, 2, 2, 2 )); @@ -272,267 +272,267 @@ inline void LLVector4a::setCross3(const LLVector4a& a, const LLVector4a& b) // Set all elements to the dot product of the x, y, and z elements in a and b inline void LLVector4a::setAllDot3(const LLVector4a& a, const LLVector4a& b) { - // ab = { a[W]*b[W], a[Z]*b[Z], a[Y]*b[Y], a[X]*b[X] } - const LLQuad ab = _mm_mul_ps( a.mQ, b.mQ ); - // yzxw = { a[W]*b[W], a[Z]*b[Z], a[X]*b[X], a[Y]*b[Y] } - const __m128i wzxy = _mm_shuffle_epi32(_mm_castps_si128(ab), _MM_SHUFFLE(3, 2, 0, 1 )); - // xPlusY = { 2*a[W]*b[W], 2 * a[Z] * b[Z], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } - const LLQuad xPlusY = _mm_add_ps(ab, _mm_castsi128_ps(wzxy)); - // xPlusYSplat = { a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } - const LLQuad xPlusYSplat = _mm_movelh_ps(xPlusY, xPlusY); - // zSplat = { a[Z]*b[Z], a[Z]*b[Z], a[Z]*b[Z], a[Z]*b[Z] } - const __m128i zSplat = _mm_shuffle_epi32(_mm_castps_si128(ab), _MM_SHUFFLE( 2, 2, 2, 2 )); - // mQ = { a[Z] * b[Z] + a[Y] * b[Y] + a[X] * b[X], same, same, same } - mQ = _mm_add_ps(_mm_castsi128_ps(zSplat), xPlusYSplat); + // ab = { a[W]*b[W], a[Z]*b[Z], a[Y]*b[Y], a[X]*b[X] } + const LLQuad ab = _mm_mul_ps( a.mQ, b.mQ ); + // yzxw = { a[W]*b[W], a[Z]*b[Z], a[X]*b[X], a[Y]*b[Y] } + const __m128i wzxy = _mm_shuffle_epi32(_mm_castps_si128(ab), _MM_SHUFFLE(3, 2, 0, 1 )); + // xPlusY = { 2*a[W]*b[W], 2 * a[Z] * b[Z], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } + const LLQuad xPlusY = _mm_add_ps(ab, _mm_castsi128_ps(wzxy)); + // xPlusYSplat = { a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } + const LLQuad xPlusYSplat = _mm_movelh_ps(xPlusY, xPlusY); + // zSplat = { a[Z]*b[Z], a[Z]*b[Z], a[Z]*b[Z], a[Z]*b[Z] } + const __m128i zSplat = _mm_shuffle_epi32(_mm_castps_si128(ab), _MM_SHUFFLE( 2, 2, 2, 2 )); + // mQ = { a[Z] * b[Z] + a[Y] * b[Y] + a[X] * b[X], same, same, same } + mQ = _mm_add_ps(_mm_castsi128_ps(zSplat), xPlusYSplat); } // Set all elements to the dot product of the x, y, z, and w elements in a and b inline void LLVector4a::setAllDot4(const LLVector4a& a, const LLVector4a& b) { - // ab = { a[W]*b[W], a[Z]*b[Z], a[Y]*b[Y], a[X]*b[X] } - const LLQuad ab = _mm_mul_ps( a.mQ, b.mQ ); - // yzxw = { a[W]*b[W], a[Z]*b[Z], a[X]*b[X], a[Y]*b[Y] } - const __m128i zwxy = _mm_shuffle_epi32(_mm_castps_si128(ab), _MM_SHUFFLE(2, 3, 0, 1 )); - // zPlusWandXplusY = { a[W]*b[W] + a[Z]*b[Z], a[Z] * b[Z] + a[W]*b[W], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } - const LLQuad zPlusWandXplusY = _mm_add_ps(ab, _mm_castsi128_ps(zwxy)); - // xPlusYSplat = { a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } - const LLQuad xPlusYSplat = _mm_movelh_ps(zPlusWandXplusY, zPlusWandXplusY); - const LLQuad zPlusWSplat = _mm_movehl_ps(zPlusWandXplusY, zPlusWandXplusY); + // ab = { a[W]*b[W], a[Z]*b[Z], a[Y]*b[Y], a[X]*b[X] } + const LLQuad ab = _mm_mul_ps( a.mQ, b.mQ ); + // yzxw = { a[W]*b[W], a[Z]*b[Z], a[X]*b[X], a[Y]*b[Y] } + const __m128i zwxy = _mm_shuffle_epi32(_mm_castps_si128(ab), _MM_SHUFFLE(2, 3, 0, 1 )); + // zPlusWandXplusY = { a[W]*b[W] + a[Z]*b[Z], a[Z] * b[Z] + a[W]*b[W], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } + const LLQuad zPlusWandXplusY = _mm_add_ps(ab, _mm_castsi128_ps(zwxy)); + // xPlusYSplat = { a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } + const LLQuad xPlusYSplat = _mm_movelh_ps(zPlusWandXplusY, zPlusWandXplusY); + const LLQuad zPlusWSplat = _mm_movehl_ps(zPlusWandXplusY, zPlusWandXplusY); - // mQ = { a[W]*b[W] + a[Z] * b[Z] + a[Y] * b[Y] + a[X] * b[X], same, same, same } - mQ = _mm_add_ps(xPlusYSplat, zPlusWSplat); + // mQ = { a[W]*b[W] + a[Z] * b[Z] + a[Y] * b[Y] + a[X] * b[X], same, same, same } + mQ = _mm_add_ps(xPlusYSplat, zPlusWSplat); } // Return the 3D dot product of this vector and b inline LLSimdScalar LLVector4a::dot3(const LLVector4a& b) const { - const LLQuad ab = _mm_mul_ps( mQ, b.mQ ); - const LLQuad splatY = _mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128(ab), _MM_SHUFFLE(1, 1, 1, 1) ) ); - const LLQuad splatZ = _mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128(ab), _MM_SHUFFLE(2, 2, 2, 2) ) ); - const LLQuad xPlusY = _mm_add_ps( ab, splatY ); - return _mm_add_ps( xPlusY, splatZ ); + const LLQuad ab = _mm_mul_ps( mQ, b.mQ ); + const LLQuad splatY = _mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128(ab), _MM_SHUFFLE(1, 1, 1, 1) ) ); + const LLQuad splatZ = _mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128(ab), _MM_SHUFFLE(2, 2, 2, 2) ) ); + const LLQuad xPlusY = _mm_add_ps( ab, splatY ); + return _mm_add_ps( xPlusY, splatZ ); } // Return the 4D dot product of this vector and b inline LLSimdScalar LLVector4a::dot4(const LLVector4a& b) const { - // ab = { w, z, y, x } - const LLQuad ab = _mm_mul_ps( mQ, b.mQ ); - // upperProdsInLowerElems = { y, x, y, x } - const LLQuad upperProdsInLowerElems = _mm_movehl_ps( ab, ab ); - // sumOfPairs = { w+y, z+x, 2y, 2x } - const LLQuad sumOfPairs = _mm_add_ps( upperProdsInLowerElems, ab ); - // shuffled = { z+x, z+x, z+x, z+x } - const LLQuad shuffled = _mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( sumOfPairs ), _MM_SHUFFLE(1, 1, 1, 1) ) ); - return _mm_add_ss( sumOfPairs, shuffled ); + // ab = { w, z, y, x } + const LLQuad ab = _mm_mul_ps( mQ, b.mQ ); + // upperProdsInLowerElems = { y, x, y, x } + const LLQuad upperProdsInLowerElems = _mm_movehl_ps( ab, ab ); + // sumOfPairs = { w+y, z+x, 2y, 2x } + const LLQuad sumOfPairs = _mm_add_ps( upperProdsInLowerElems, ab ); + // shuffled = { z+x, z+x, z+x, z+x } + const LLQuad shuffled = _mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( sumOfPairs ), _MM_SHUFFLE(1, 1, 1, 1) ) ); + return _mm_add_ss( sumOfPairs, shuffled ); } // Normalize this vector with respect to the x, y, and z components only. Accurate to 22 bites of precision. W component is destroyed // Note that this does not consider zero length vectors! inline void LLVector4a::normalize3() { - // lenSqrd = a dot a - LLVector4a lenSqrd; lenSqrd.setAllDot3( *this, *this ); - // rsqrt = approximate reciprocal square (i.e., { ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2 } - const LLQuad rsqrt = _mm_rsqrt_ps(lenSqrd.mQ); - static const LLQuad half = { 0.5f, 0.5f, 0.5f, 0.5f }; - static const LLQuad three = {3.f, 3.f, 3.f, 3.f }; - // Now we do one round of Newton-Raphson approximation to get full accuracy - // According to the Newton-Raphson method, given a first 'w' for the root of f(x) = 1/x^2 - a (i.e., x = 1/sqrt(a)) - // the next better approximation w[i+1] = w - f(w)/f'(w) = w - (1/w^2 - a)/(-2*w^(-3)) - // w[i+1] = w + 0.5 * (1/w^2 - a) * w^3 = w + 0.5 * (w - a*w^3) = 1.5 * w - 0.5 * a * w^3 - // = 0.5 * w * (3 - a*w^2) - // Our first approx is w = rsqrt. We need out = a * w[i+1] (this is the input vector 'a', not the 'a' from the above formula - // which is actually lenSqrd). So out = a * [0.5*rsqrt * (3 - lenSqrd*rsqrt*rsqrt)] - const LLQuad AtimesRsqrt = _mm_mul_ps( lenSqrd.mQ, rsqrt ); - const LLQuad AtimesRsqrtTimesRsqrt = _mm_mul_ps( AtimesRsqrt, rsqrt ); - const LLQuad threeMinusAtimesRsqrtTimesRsqrt = _mm_sub_ps(three, AtimesRsqrtTimesRsqrt ); - const LLQuad nrApprox = _mm_mul_ps(half, _mm_mul_ps(rsqrt, threeMinusAtimesRsqrtTimesRsqrt)); - mQ = _mm_mul_ps( mQ, nrApprox ); + // lenSqrd = a dot a + LLVector4a lenSqrd; lenSqrd.setAllDot3( *this, *this ); + // rsqrt = approximate reciprocal square (i.e., { ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2 } + const LLQuad rsqrt = _mm_rsqrt_ps(lenSqrd.mQ); + static const LLQuad half = { 0.5f, 0.5f, 0.5f, 0.5f }; + static const LLQuad three = {3.f, 3.f, 3.f, 3.f }; + // Now we do one round of Newton-Raphson approximation to get full accuracy + // According to the Newton-Raphson method, given a first 'w' for the root of f(x) = 1/x^2 - a (i.e., x = 1/sqrt(a)) + // the next better approximation w[i+1] = w - f(w)/f'(w) = w - (1/w^2 - a)/(-2*w^(-3)) + // w[i+1] = w + 0.5 * (1/w^2 - a) * w^3 = w + 0.5 * (w - a*w^3) = 1.5 * w - 0.5 * a * w^3 + // = 0.5 * w * (3 - a*w^2) + // Our first approx is w = rsqrt. We need out = a * w[i+1] (this is the input vector 'a', not the 'a' from the above formula + // which is actually lenSqrd). So out = a * [0.5*rsqrt * (3 - lenSqrd*rsqrt*rsqrt)] + const LLQuad AtimesRsqrt = _mm_mul_ps( lenSqrd.mQ, rsqrt ); + const LLQuad AtimesRsqrtTimesRsqrt = _mm_mul_ps( AtimesRsqrt, rsqrt ); + const LLQuad threeMinusAtimesRsqrtTimesRsqrt = _mm_sub_ps(three, AtimesRsqrtTimesRsqrt ); + const LLQuad nrApprox = _mm_mul_ps(half, _mm_mul_ps(rsqrt, threeMinusAtimesRsqrtTimesRsqrt)); + mQ = _mm_mul_ps( mQ, nrApprox ); } // Normalize this vector with respect to all components. Accurate to 22 bites of precision. // Note that this does not consider zero length vectors! inline void LLVector4a::normalize4() { - // lenSqrd = a dot a - LLVector4a lenSqrd; lenSqrd.setAllDot4( *this, *this ); - // rsqrt = approximate reciprocal square (i.e., { ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2 } - const LLQuad rsqrt = _mm_rsqrt_ps(lenSqrd.mQ); - static const LLQuad half = { 0.5f, 0.5f, 0.5f, 0.5f }; - static const LLQuad three = {3.f, 3.f, 3.f, 3.f }; - // Now we do one round of Newton-Raphson approximation to get full accuracy - // According to the Newton-Raphson method, given a first 'w' for the root of f(x) = 1/x^2 - a (i.e., x = 1/sqrt(a)) - // the next better approximation w[i+1] = w - f(w)/f'(w) = w - (1/w^2 - a)/(-2*w^(-3)) - // w[i+1] = w + 0.5 * (1/w^2 - a) * w^3 = w + 0.5 * (w - a*w^3) = 1.5 * w - 0.5 * a * w^3 - // = 0.5 * w * (3 - a*w^2) - // Our first approx is w = rsqrt. We need out = a * w[i+1] (this is the input vector 'a', not the 'a' from the above formula - // which is actually lenSqrd). So out = a * [0.5*rsqrt * (3 - lenSqrd*rsqrt*rsqrt)] - const LLQuad AtimesRsqrt = _mm_mul_ps( lenSqrd.mQ, rsqrt ); - const LLQuad AtimesRsqrtTimesRsqrt = _mm_mul_ps( AtimesRsqrt, rsqrt ); - const LLQuad threeMinusAtimesRsqrtTimesRsqrt = _mm_sub_ps(three, AtimesRsqrtTimesRsqrt ); - const LLQuad nrApprox = _mm_mul_ps(half, _mm_mul_ps(rsqrt, threeMinusAtimesRsqrtTimesRsqrt)); - mQ = _mm_mul_ps( mQ, nrApprox ); + // lenSqrd = a dot a + LLVector4a lenSqrd; lenSqrd.setAllDot4( *this, *this ); + // rsqrt = approximate reciprocal square (i.e., { ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2 } + const LLQuad rsqrt = _mm_rsqrt_ps(lenSqrd.mQ); + static const LLQuad half = { 0.5f, 0.5f, 0.5f, 0.5f }; + static const LLQuad three = {3.f, 3.f, 3.f, 3.f }; + // Now we do one round of Newton-Raphson approximation to get full accuracy + // According to the Newton-Raphson method, given a first 'w' for the root of f(x) = 1/x^2 - a (i.e., x = 1/sqrt(a)) + // the next better approximation w[i+1] = w - f(w)/f'(w) = w - (1/w^2 - a)/(-2*w^(-3)) + // w[i+1] = w + 0.5 * (1/w^2 - a) * w^3 = w + 0.5 * (w - a*w^3) = 1.5 * w - 0.5 * a * w^3 + // = 0.5 * w * (3 - a*w^2) + // Our first approx is w = rsqrt. We need out = a * w[i+1] (this is the input vector 'a', not the 'a' from the above formula + // which is actually lenSqrd). So out = a * [0.5*rsqrt * (3 - lenSqrd*rsqrt*rsqrt)] + const LLQuad AtimesRsqrt = _mm_mul_ps( lenSqrd.mQ, rsqrt ); + const LLQuad AtimesRsqrtTimesRsqrt = _mm_mul_ps( AtimesRsqrt, rsqrt ); + const LLQuad threeMinusAtimesRsqrtTimesRsqrt = _mm_sub_ps(three, AtimesRsqrtTimesRsqrt ); + const LLQuad nrApprox = _mm_mul_ps(half, _mm_mul_ps(rsqrt, threeMinusAtimesRsqrtTimesRsqrt)); + mQ = _mm_mul_ps( mQ, nrApprox ); } // Normalize this vector with respect to the x, y, and z components only. Accurate to 22 bites of precision. W component is destroyed // Note that this does not consider zero length vectors! inline LLSimdScalar LLVector4a::normalize3withLength() { - // lenSqrd = a dot a - LLVector4a lenSqrd; lenSqrd.setAllDot3( *this, *this ); - // rsqrt = approximate reciprocal square (i.e., { ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2 } - const LLQuad rsqrt = _mm_rsqrt_ps(lenSqrd.mQ); - static const LLQuad half = { 0.5f, 0.5f, 0.5f, 0.5f }; - static const LLQuad three = {3.f, 3.f, 3.f, 3.f }; - // Now we do one round of Newton-Raphson approximation to get full accuracy - // According to the Newton-Raphson method, given a first 'w' for the root of f(x) = 1/x^2 - a (i.e., x = 1/sqrt(a)) - // the next better approximation w[i+1] = w - f(w)/f'(w) = w - (1/w^2 - a)/(-2*w^(-3)) - // w[i+1] = w + 0.5 * (1/w^2 - a) * w^3 = w + 0.5 * (w - a*w^3) = 1.5 * w - 0.5 * a * w^3 - // = 0.5 * w * (3 - a*w^2) - // Our first approx is w = rsqrt. We need out = a * w[i+1] (this is the input vector 'a', not the 'a' from the above formula - // which is actually lenSqrd). So out = a * [0.5*rsqrt * (3 - lenSqrd*rsqrt*rsqrt)] - const LLQuad AtimesRsqrt = _mm_mul_ps( lenSqrd.mQ, rsqrt ); - const LLQuad AtimesRsqrtTimesRsqrt = _mm_mul_ps( AtimesRsqrt, rsqrt ); - const LLQuad threeMinusAtimesRsqrtTimesRsqrt = _mm_sub_ps(three, AtimesRsqrtTimesRsqrt ); - const LLQuad nrApprox = _mm_mul_ps(half, _mm_mul_ps(rsqrt, threeMinusAtimesRsqrtTimesRsqrt)); - mQ = _mm_mul_ps( mQ, nrApprox ); - return _mm_sqrt_ss(lenSqrd); + // lenSqrd = a dot a + LLVector4a lenSqrd; lenSqrd.setAllDot3( *this, *this ); + // rsqrt = approximate reciprocal square (i.e., { ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2 } + const LLQuad rsqrt = _mm_rsqrt_ps(lenSqrd.mQ); + static const LLQuad half = { 0.5f, 0.5f, 0.5f, 0.5f }; + static const LLQuad three = {3.f, 3.f, 3.f, 3.f }; + // Now we do one round of Newton-Raphson approximation to get full accuracy + // According to the Newton-Raphson method, given a first 'w' for the root of f(x) = 1/x^2 - a (i.e., x = 1/sqrt(a)) + // the next better approximation w[i+1] = w - f(w)/f'(w) = w - (1/w^2 - a)/(-2*w^(-3)) + // w[i+1] = w + 0.5 * (1/w^2 - a) * w^3 = w + 0.5 * (w - a*w^3) = 1.5 * w - 0.5 * a * w^3 + // = 0.5 * w * (3 - a*w^2) + // Our first approx is w = rsqrt. We need out = a * w[i+1] (this is the input vector 'a', not the 'a' from the above formula + // which is actually lenSqrd). So out = a * [0.5*rsqrt * (3 - lenSqrd*rsqrt*rsqrt)] + const LLQuad AtimesRsqrt = _mm_mul_ps( lenSqrd.mQ, rsqrt ); + const LLQuad AtimesRsqrtTimesRsqrt = _mm_mul_ps( AtimesRsqrt, rsqrt ); + const LLQuad threeMinusAtimesRsqrtTimesRsqrt = _mm_sub_ps(three, AtimesRsqrtTimesRsqrt ); + const LLQuad nrApprox = _mm_mul_ps(half, _mm_mul_ps(rsqrt, threeMinusAtimesRsqrtTimesRsqrt)); + mQ = _mm_mul_ps( mQ, nrApprox ); + return _mm_sqrt_ss(lenSqrd); } // Normalize this vector with respect to the x, y, and z components only. Accurate only to 10-12 bits of precision. W component is destroyed // Note that this does not consider zero length vectors! inline void LLVector4a::normalize3fast() { - LLVector4a lenSqrd; lenSqrd.setAllDot3( *this, *this ); - const LLQuad approxRsqrt = _mm_rsqrt_ps(lenSqrd.mQ); - mQ = _mm_mul_ps( mQ, approxRsqrt ); + LLVector4a lenSqrd; lenSqrd.setAllDot3( *this, *this ); + const LLQuad approxRsqrt = _mm_rsqrt_ps(lenSqrd.mQ); + mQ = _mm_mul_ps( mQ, approxRsqrt ); } inline void LLVector4a::normalize3fast_checked(LLVector4a* d) { - if (!isFinite3()) - { - *this = d ? *d : LLVector4a(0,1,0,1); - return; - } + if (!isFinite3()) + { + *this = d ? *d : LLVector4a(0,1,0,1); + return; + } - LLVector4a lenSqrd; lenSqrd.setAllDot3( *this, *this ); + LLVector4a lenSqrd; lenSqrd.setAllDot3( *this, *this ); - if (lenSqrd.getF32ptr()[0] <= FLT_EPSILON) - { - *this = d ? *d : LLVector4a(0,1,0,1); - return; - } + if (lenSqrd.getF32ptr()[0] <= FLT_EPSILON) + { + *this = d ? *d : LLVector4a(0,1,0,1); + return; + } - const LLQuad approxRsqrt = _mm_rsqrt_ps(lenSqrd.mQ); - mQ = _mm_mul_ps( mQ, approxRsqrt ); + const LLQuad approxRsqrt = _mm_rsqrt_ps(lenSqrd.mQ); + mQ = _mm_mul_ps( mQ, approxRsqrt ); } // Return true if this vector is normalized with respect to x,y,z up to tolerance inline LLBool32 LLVector4a::isNormalized3( F32 tolerance ) const { - static LL_ALIGN_16(const U32 ones[4]) = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000 }; - LLSimdScalar tol = _mm_load_ss( &tolerance ); - tol = _mm_mul_ss( tol, tol ); - LLVector4a lenSquared; lenSquared.setAllDot3( *this, *this ); - lenSquared.sub( *reinterpret_cast<const LLVector4a*>(ones) ); - lenSquared.setAbs(lenSquared); - return _mm_comile_ss( lenSquared, tol ); + static LL_ALIGN_16(const U32 ones[4]) = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000 }; + LLSimdScalar tol = _mm_load_ss( &tolerance ); + tol = _mm_mul_ss( tol, tol ); + LLVector4a lenSquared; lenSquared.setAllDot3( *this, *this ); + lenSquared.sub( *reinterpret_cast<const LLVector4a*>(ones) ); + lenSquared.setAbs(lenSquared); + return _mm_comile_ss( lenSquared, tol ); } // Return true if this vector is normalized with respect to all components up to tolerance inline LLBool32 LLVector4a::isNormalized4( F32 tolerance ) const { - static LL_ALIGN_16(const U32 ones[4]) = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000 }; - LLSimdScalar tol = _mm_load_ss( &tolerance ); - tol = _mm_mul_ss( tol, tol ); - LLVector4a lenSquared; lenSquared.setAllDot4( *this, *this ); - lenSquared.sub( *reinterpret_cast<const LLVector4a*>(ones) ); - lenSquared.setAbs(lenSquared); - return _mm_comile_ss( lenSquared, tol ); + static LL_ALIGN_16(const U32 ones[4]) = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000 }; + LLSimdScalar tol = _mm_load_ss( &tolerance ); + tol = _mm_mul_ss( tol, tol ); + LLVector4a lenSquared; lenSquared.setAllDot4( *this, *this ); + lenSquared.sub( *reinterpret_cast<const LLVector4a*>(ones) ); + lenSquared.setAbs(lenSquared); + return _mm_comile_ss( lenSquared, tol ); } -// Set all elements to the length of vector 'v' +// Set all elements to the length of vector 'v' inline void LLVector4a::setAllLength3( const LLVector4a& v ) { - LLVector4a lenSqrd; - lenSqrd.setAllDot3(v, v); - - mQ = _mm_sqrt_ps(lenSqrd.mQ); + LLVector4a lenSqrd; + lenSqrd.setAllDot3(v, v); + + mQ = _mm_sqrt_ps(lenSqrd.mQ); } // Get this vector's length inline LLSimdScalar LLVector4a::getLength3() const { - return _mm_sqrt_ss( dot3( (const LLVector4a)mQ ) ); + return _mm_sqrt_ss( dot3( (const LLVector4a)mQ ) ); } // Set the components of this vector to the minimum of the corresponding components of lhs and rhs inline void LLVector4a::setMin(const LLVector4a& lhs, const LLVector4a& rhs) { - mQ = _mm_min_ps(lhs.mQ, rhs.mQ); + mQ = _mm_min_ps(lhs.mQ, rhs.mQ); } // Set the components of this vector to the maximum of the corresponding components of lhs and rhs inline void LLVector4a::setMax(const LLVector4a& lhs, const LLVector4a& rhs) { - mQ = _mm_max_ps(lhs.mQ, rhs.mQ); + mQ = _mm_max_ps(lhs.mQ, rhs.mQ); } // Set this to lhs + (rhs-lhs)*c inline void LLVector4a::setLerp(const LLVector4a& lhs, const LLVector4a& rhs, F32 c) { - LLVector4a t; - t.setSub(rhs,lhs); - t.mul(c); - setAdd(lhs, t); + LLVector4a t; + t.setSub(rhs,lhs); + t.mul(c); + setAdd(lhs, t); } inline LLBool32 LLVector4a::isFinite3() const { - static LL_ALIGN_16(const U32 nanOrInfMask[4]) = { 0x7f800000, 0x7f800000, 0x7f800000, 0x7f800000 }; - ll_assert_aligned(nanOrInfMask,16); - const __m128i nanOrInfMaskV = *reinterpret_cast<const __m128i*> (nanOrInfMask); - const __m128i maskResult = _mm_and_si128( _mm_castps_si128(mQ), nanOrInfMaskV ); - const LLVector4Logical equalityCheck = _mm_castsi128_ps(_mm_cmpeq_epi32( maskResult, nanOrInfMaskV )); - return !equalityCheck.areAnySet( LLVector4Logical::MASK_XYZ ); + static LL_ALIGN_16(const U32 nanOrInfMask[4]) = { 0x7f800000, 0x7f800000, 0x7f800000, 0x7f800000 }; + ll_assert_aligned(nanOrInfMask,16); + const __m128i nanOrInfMaskV = *reinterpret_cast<const __m128i*> (nanOrInfMask); + const __m128i maskResult = _mm_and_si128( _mm_castps_si128(mQ), nanOrInfMaskV ); + const LLVector4Logical equalityCheck = _mm_castsi128_ps(_mm_cmpeq_epi32( maskResult, nanOrInfMaskV )); + return !equalityCheck.areAnySet( LLVector4Logical::MASK_XYZ ); } - + inline LLBool32 LLVector4a::isFinite4() const { - static LL_ALIGN_16(const U32 nanOrInfMask[4]) = { 0x7f800000, 0x7f800000, 0x7f800000, 0x7f800000 }; - const __m128i nanOrInfMaskV = *reinterpret_cast<const __m128i*> (nanOrInfMask); - const __m128i maskResult = _mm_and_si128( _mm_castps_si128(mQ), nanOrInfMaskV ); - const LLVector4Logical equalityCheck = _mm_castsi128_ps(_mm_cmpeq_epi32( maskResult, nanOrInfMaskV )); - return !equalityCheck.areAnySet( LLVector4Logical::MASK_XYZW ); + static LL_ALIGN_16(const U32 nanOrInfMask[4]) = { 0x7f800000, 0x7f800000, 0x7f800000, 0x7f800000 }; + const __m128i nanOrInfMaskV = *reinterpret_cast<const __m128i*> (nanOrInfMask); + const __m128i maskResult = _mm_and_si128( _mm_castps_si128(mQ), nanOrInfMaskV ); + const LLVector4Logical equalityCheck = _mm_castsi128_ps(_mm_cmpeq_epi32( maskResult, nanOrInfMaskV )); + return !equalityCheck.areAnySet( LLVector4Logical::MASK_XYZW ); } inline void LLVector4a::setRotatedInv( const LLRotation& rot, const LLVector4a& vec ) { - LLRotation inv; inv.setTranspose( rot ); - setRotated( inv, vec ); + LLRotation inv; inv.setTranspose( rot ); + setRotated( inv, vec ); } inline void LLVector4a::setRotatedInv( const LLQuaternion2& quat, const LLVector4a& vec ) { - LLQuaternion2 invRot; invRot.setConjugate( quat ); - setRotated(invRot, vec); + LLQuaternion2 invRot; invRot.setConjugate( quat ); + setRotated(invRot, vec); } inline void LLVector4a::clamp( const LLVector4a& low, const LLVector4a& high ) { - const LLVector4Logical highMask = greaterThan( high ); - const LLVector4Logical lowMask = lessThan( low ); + const LLVector4Logical highMask = greaterThan( high ); + const LLVector4Logical lowMask = lessThan( low ); - setSelectWithMask( highMask, high, *this ); - setSelectWithMask( lowMask, low, *this ); + setSelectWithMask( highMask, high, *this ); + setSelectWithMask( lowMask, low, *this ); } //////////////////////////////////// // LOGICAL -//////////////////////////////////// +//////////////////////////////////// // The functions in this section will compare the elements in this vector // to those in rhs and return an LLVector4Logical with all bits set in elements // where the comparison was true and all bits unset in elements where the comparison @@ -544,68 +544,68 @@ inline void LLVector4a::clamp( const LLVector4a& low, const LLVector4a& high ) //////////////////////////////////// inline LLVector4Logical LLVector4a::greaterThan(const LLVector4a& rhs) const -{ - return _mm_cmpgt_ps(mQ, rhs.mQ); +{ + return _mm_cmpgt_ps(mQ, rhs.mQ); } inline LLVector4Logical LLVector4a::lessThan(const LLVector4a& rhs) const { - return _mm_cmplt_ps(mQ, rhs.mQ); + return _mm_cmplt_ps(mQ, rhs.mQ); } inline LLVector4Logical LLVector4a::greaterEqual(const LLVector4a& rhs) const { - return _mm_cmpge_ps(mQ, rhs.mQ); + return _mm_cmpge_ps(mQ, rhs.mQ); } inline LLVector4Logical LLVector4a::lessEqual(const LLVector4a& rhs) const { - return _mm_cmple_ps(mQ, rhs.mQ); + return _mm_cmple_ps(mQ, rhs.mQ); } inline LLVector4Logical LLVector4a::equal(const LLVector4a& rhs) const { - return _mm_cmpeq_ps(mQ, rhs.mQ); + return _mm_cmpeq_ps(mQ, rhs.mQ); } // Returns true if this and rhs are componentwise equal up to the specified absolute tolerance inline bool LLVector4a::equals4(const LLVector4a& rhs, F32 tolerance ) const { - LLVector4a diff; diff.setSub( *this, rhs ); - diff.setAbs( diff ); - const LLQuad tol = _mm_set1_ps( tolerance ); - const LLQuad cmp = _mm_cmplt_ps( diff, tol ); - return (_mm_movemask_ps( cmp ) & LLVector4Logical::MASK_XYZW) == LLVector4Logical::MASK_XYZW; + LLVector4a diff; diff.setSub( *this, rhs ); + diff.setAbs( diff ); + const LLQuad tol = _mm_set1_ps( tolerance ); + const LLQuad cmp = _mm_cmplt_ps( diff, tol ); + return (_mm_movemask_ps( cmp ) & LLVector4Logical::MASK_XYZW) == LLVector4Logical::MASK_XYZW; } inline bool LLVector4a::equals3(const LLVector4a& rhs, F32 tolerance ) const { - LLVector4a diff; diff.setSub( *this, rhs ); - diff.setAbs( diff ); - const LLQuad tol = _mm_set1_ps( tolerance ); - const LLQuad t = _mm_cmplt_ps( diff, tol ); - return (_mm_movemask_ps( t ) & LLVector4Logical::MASK_XYZ) == LLVector4Logical::MASK_XYZ; - + LLVector4a diff; diff.setSub( *this, rhs ); + diff.setAbs( diff ); + const LLQuad tol = _mm_set1_ps( tolerance ); + const LLQuad t = _mm_cmplt_ps( diff, tol ); + return (_mm_movemask_ps( t ) & LLVector4Logical::MASK_XYZ) == LLVector4Logical::MASK_XYZ; + } //////////////////////////////////// // OPERATORS -//////////////////////////////////// +//////////////////////////////////// // Do NOT add aditional operators without consulting someone with SSE experience inline const LLVector4a& LLVector4a::operator= ( const LLVector4a& rhs ) { - mQ = rhs.mQ; - return *this; + mQ = rhs.mQ; + return *this; } inline const LLVector4a& LLVector4a::operator= ( const LLQuad& rhs ) { - mQ = rhs; - return *this; + mQ = rhs; + return *this; } inline LLVector4a::operator LLQuad() const { - return mQ; + return mQ; } diff --git a/indra/llmath/llvector4logical.h b/indra/llmath/llvector4logical.h index c5698f7cea..d08b5513d9 100644 --- a/indra/llmath/llvector4logical.h +++ b/indra/llmath/llvector4logical.h @@ -1,31 +1,31 @@ -/** +/** * @file llvector4logical.h * @brief LLVector4Logical class header file - Companion class to LLVector4a for logical and bit-twiddling operations * * $LicenseInfo:firstyear=2010&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ -#ifndef LL_VECTOR4LOGICAL_H -#define LL_VECTOR4LOGICAL_H +#ifndef LL_VECTOR4LOGICAL_H +#define LL_VECTOR4LOGICAL_H #include "llmemory.h" @@ -41,86 +41,86 @@ static LL_ALIGN_16(const U32 S_V4LOGICAL_MASK_TABLE[4*4]) = { - 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF + 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF }; class LLVector4Logical { public: - - enum { - MASK_X = 1, - MASK_Y = 1 << 1, - MASK_Z = 1 << 2, - MASK_W = 1 << 3, - MASK_XYZ = MASK_X | MASK_Y | MASK_Z, - MASK_XYZW = MASK_XYZ | MASK_W - }; - - // Empty default ctor - LLVector4Logical() {} - - LLVector4Logical( const LLQuad& quad ) - { - mQ = quad; - } - - // Create and return a mask consisting of the lowest order bit of each element - inline U32 getGatheredBits() const - { - return _mm_movemask_ps(mQ); - }; - - // Invert this mask - inline LLVector4Logical& invert() - { - static const LL_ALIGN_16(U32 allOnes[4]) = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; - ll_assert_aligned(allOnes,16); - mQ = _mm_andnot_ps( mQ, *(LLQuad*)(allOnes) ); - return *this; - } - - inline LLBool32 areAllSet( U32 mask ) const - { - return ( getGatheredBits() & mask) == mask; - } - - inline LLBool32 areAllSet() const - { - return areAllSet( MASK_XYZW ); - } - - inline LLBool32 areAnySet( U32 mask ) const - { - return getGatheredBits() & mask; - } - - inline LLBool32 areAnySet() const - { - return areAnySet( MASK_XYZW ); - } - - inline operator LLQuad() const - { - return mQ; - } - - inline void clear() - { - mQ = _mm_setzero_ps(); - } - - template<int N> void setElement() - { - mQ = _mm_or_ps( mQ, *reinterpret_cast<const LLQuad*>(S_V4LOGICAL_MASK_TABLE + 4*N) ); - } - + + enum { + MASK_X = 1, + MASK_Y = 1 << 1, + MASK_Z = 1 << 2, + MASK_W = 1 << 3, + MASK_XYZ = MASK_X | MASK_Y | MASK_Z, + MASK_XYZW = MASK_XYZ | MASK_W + }; + + // Empty default ctor + LLVector4Logical() {} + + LLVector4Logical( const LLQuad& quad ) + { + mQ = quad; + } + + // Create and return a mask consisting of the lowest order bit of each element + inline U32 getGatheredBits() const + { + return _mm_movemask_ps(mQ); + }; + + // Invert this mask + inline LLVector4Logical& invert() + { + static const LL_ALIGN_16(U32 allOnes[4]) = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + ll_assert_aligned(allOnes,16); + mQ = _mm_andnot_ps( mQ, *(LLQuad*)(allOnes) ); + return *this; + } + + inline LLBool32 areAllSet( U32 mask ) const + { + return ( getGatheredBits() & mask) == mask; + } + + inline LLBool32 areAllSet() const + { + return areAllSet( MASK_XYZW ); + } + + inline LLBool32 areAnySet( U32 mask ) const + { + return getGatheredBits() & mask; + } + + inline LLBool32 areAnySet() const + { + return areAnySet( MASK_XYZW ); + } + + inline operator LLQuad() const + { + return mQ; + } + + inline void clear() + { + mQ = _mm_setzero_ps(); + } + + template<int N> void setElement() + { + mQ = _mm_or_ps( mQ, *reinterpret_cast<const LLQuad*>(S_V4LOGICAL_MASK_TABLE + 4*N) ); + } + private: - - LLQuad mQ; + + LLQuad mQ; }; #endif //LL_VECTOR4ALOGICAL_H diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 0b9712ff8c..96680a11d5 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1,24 +1,24 @@ -/** +/** * @file llvolume.cpp * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -65,7 +65,7 @@ constexpr F32 MIN_CUT_DELTA = 0.02f; constexpr F32 HOLLOW_MIN = 0.f; constexpr F32 HOLLOW_MAX = 0.95f; -constexpr F32 HOLLOW_MAX_SQUARE = 0.7f; +constexpr F32 HOLLOW_MAX_SQUARE = 0.7f; constexpr F32 TWIST_MIN = -1.f; constexpr F32 TWIST_MAX = 1.f; @@ -88,8 +88,8 @@ constexpr F32 REV_MAX = 4.f; constexpr F32 TAPER_MIN = -1.f; constexpr F32 TAPER_MAX = 1.f; -constexpr F32 SKEW_MIN = -0.95f; -constexpr F32 SKEW_MAX = 0.95f; +constexpr F32 SKEW_MIN = -0.95f; +constexpr F32 SKEW_MAX = 0.95f; constexpr F32 SCULPT_MIN_AREA = 0.002f; constexpr S32 SCULPT_MIN_AREA_DETAIL = 1; @@ -98,260 +98,260 @@ bool gDebugGL = false; // See settings.xml "RenderDebugGL" bool check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, const LLVector3& norm) { - LLVector3 test = (pt2-pt1)%(pt3-pt2); + LLVector3 test = (pt2-pt1)%(pt3-pt2); - //answer - if(test * norm < 0) - { - return false; - } - else - { - return true; - } -} + //answer + if(test * norm < 0) + { + return false; + } + else + { + return true; + } +} bool LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size) { - return LLLineSegmentBoxIntersect(start.mV, end.mV, center.mV, size.mV); + return LLLineSegmentBoxIntersect(start.mV, end.mV, center.mV, size.mV); } bool LLLineSegmentBoxIntersect(const F32* start, const F32* end, const F32* center, const F32* size) { - F32 fAWdU[3]{}; - F32 dir[3]{}; - F32 diff[3]{}; + F32 fAWdU[3]{}; + F32 dir[3]{}; + F32 diff[3]{}; + + for (U32 i = 0; i < 3; i++) + { + dir[i] = 0.5f * (end[i] - start[i]); + diff[i] = (0.5f * (end[i] + start[i])) - center[i]; + fAWdU[i] = fabsf(dir[i]); + if(fabsf(diff[i])>size[i] + fAWdU[i]) return false; + } - for (U32 i = 0; i < 3; i++) - { - dir[i] = 0.5f * (end[i] - start[i]); - diff[i] = (0.5f * (end[i] + start[i])) - center[i]; - fAWdU[i] = fabsf(dir[i]); - if(fabsf(diff[i])>size[i] + fAWdU[i]) return false; - } + float f; + f = dir[1] * diff[2] - dir[2] * diff[1]; if(fabsf(f)>size[1]*fAWdU[2] + size[2]*fAWdU[1]) return false; + f = dir[2] * diff[0] - dir[0] * diff[2]; if(fabsf(f)>size[0]*fAWdU[2] + size[2]*fAWdU[0]) return false; + f = dir[0] * diff[1] - dir[1] * diff[0]; if(fabsf(f)>size[0]*fAWdU[1] + size[1]*fAWdU[0]) return false; - float f; - f = dir[1] * diff[2] - dir[2] * diff[1]; if(fabsf(f)>size[1]*fAWdU[2] + size[2]*fAWdU[1]) return false; - f = dir[2] * diff[0] - dir[0] * diff[2]; if(fabsf(f)>size[0]*fAWdU[2] + size[2]*fAWdU[0]) return false; - f = dir[0] * diff[1] - dir[1] * diff[0]; if(fabsf(f)>size[0]*fAWdU[1] + size[1]*fAWdU[0]) return false; - - return true; + return true; } // Finds tangent vec based on three vertices with texture coordinates. // Fills in dummy values if the triangle has degenerate texture coordinates. void calc_tangent_from_triangle( - LLVector4a& normal, - LLVector4a& tangent_out, - const LLVector4a& v1, - const LLVector2& w1, - const LLVector4a& v2, - const LLVector2& w2, - const LLVector4a& v3, - const LLVector2& w3) -{ - const F32* v1ptr = v1.getF32ptr(); - const F32* v2ptr = v2.getF32ptr(); - const F32* v3ptr = v3.getF32ptr(); + LLVector4a& normal, + LLVector4a& tangent_out, + const LLVector4a& v1, + const LLVector2& w1, + const LLVector4a& v2, + const LLVector2& w2, + const LLVector4a& v3, + const LLVector2& w3) +{ + const F32* v1ptr = v1.getF32ptr(); + const F32* v2ptr = v2.getF32ptr(); + const F32* v3ptr = v3.getF32ptr(); + + float x1 = v2ptr[0] - v1ptr[0]; + float x2 = v3ptr[0] - v1ptr[0]; + float y1 = v2ptr[1] - v1ptr[1]; + float y2 = v3ptr[1] - v1ptr[1]; + float z1 = v2ptr[2] - v1ptr[2]; + float z2 = v3ptr[2] - v1ptr[2]; + + float s1 = w2.mV[0] - w1.mV[0]; + float s2 = w3.mV[0] - w1.mV[0]; + float t1 = w2.mV[1] - w1.mV[1]; + float t2 = w3.mV[1] - w1.mV[1]; + + F32 rd = s1*t2-s2*t1; + + float r = ((rd*rd) > FLT_EPSILON) ? (1.0f / rd) + : ((rd > 0.0f) ? 1024.f : -1024.f); //some made up large ratio for division by zero + + llassert(llfinite(r)); + llassert(!llisnan(r)); + + LLVector4a sdir( + (t2 * x1 - t1 * x2) * r, + (t2 * y1 - t1 * y2) * r, + (t2 * z1 - t1 * z2) * r); + + LLVector4a tdir( + (s1 * x2 - s2 * x1) * r, + (s1 * y2 - s2 * y1) * r, + (s1 * z2 - s2 * z1) * r); + + LLVector4a n = normal; + LLVector4a t = sdir; + + LLVector4a ncrosst; + ncrosst.setCross3(n,t); + + // Gram-Schmidt orthogonalize + n.mul(n.dot3(t).getF32()); + + LLVector4a tsubn; + tsubn.setSub(t,n); + + if (tsubn.dot3(tsubn).getF32() > F_APPROXIMATELY_ZERO) + { + tsubn.normalize3fast_checked(); - float x1 = v2ptr[0] - v1ptr[0]; - float x2 = v3ptr[0] - v1ptr[0]; - float y1 = v2ptr[1] - v1ptr[1]; - float y2 = v3ptr[1] - v1ptr[1]; - float z1 = v2ptr[2] - v1ptr[2]; - float z2 = v3ptr[2] - v1ptr[2]; + // Calculate handedness + F32 handedness = ncrosst.dot3(tdir).getF32() < 0.f ? -1.f : 1.f; - float s1 = w2.mV[0] - w1.mV[0]; - float s2 = w3.mV[0] - w1.mV[0]; - float t1 = w2.mV[1] - w1.mV[1]; - float t2 = w3.mV[1] - w1.mV[1]; + tsubn.getF32ptr()[3] = handedness; - F32 rd = s1*t2-s2*t1; + tangent_out = tsubn; + } + else + { + // degenerate, make up a value + // + tangent_out.set(0,0,1,1); + } - float r = ((rd*rd) > FLT_EPSILON) ? (1.0f / rd) - : ((rd > 0.0f) ? 1024.f : -1024.f); //some made up large ratio for division by zero +} - llassert(llfinite(r)); - llassert(!llisnan(r)); - LLVector4a sdir( - (t2 * x1 - t1 * x2) * r, - (t2 * y1 - t1 * y2) * r, - (t2 * z1 - t1 * z2) * r); +// intersect test between triangle vert0, vert1, vert2 and a ray from orig in direction dir. +// returns true if intersecting and returns barycentric coordinates in intersection_a, intersection_b, +// and returns the intersection point along dir in intersection_t. - LLVector4a tdir( - (s1 * x2 - s2 * x1) * r, - (s1 * y2 - s2 * y1) * r, - (s1 * z2 - s2 * z1) * r); +// Moller-Trumbore algorithm +bool LLTriangleRayIntersect(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir, + F32& intersection_a, F32& intersection_b, F32& intersection_t) +{ - LLVector4a n = normal; - LLVector4a t = sdir; + /* find vectors for two edges sharing vert0 */ + LLVector4a edge1; + edge1.setSub(vert1, vert0); - LLVector4a ncrosst; - ncrosst.setCross3(n,t); + LLVector4a edge2; + edge2.setSub(vert2, vert0); - // Gram-Schmidt orthogonalize - n.mul(n.dot3(t).getF32()); + /* begin calculating determinant - also used to calculate U parameter */ + LLVector4a pvec; + pvec.setCross3(dir, edge2); - LLVector4a tsubn; - tsubn.setSub(t,n); + /* if determinant is near zero, ray lies in plane of triangle */ + LLVector4a det; + det.setAllDot3(edge1, pvec); - if (tsubn.dot3(tsubn).getF32() > F_APPROXIMATELY_ZERO) - { - tsubn.normalize3fast_checked(); + if (det.greaterEqual(LLVector4a::getEpsilon()).getGatheredBits() & 0x7) + { + /* calculate distance from vert0 to ray origin */ + LLVector4a tvec; + tvec.setSub(orig, vert0); - // Calculate handedness - F32 handedness = ncrosst.dot3(tdir).getF32() < 0.f ? -1.f : 1.f; + /* calculate U parameter and test bounds */ + LLVector4a u; + u.setAllDot3(tvec,pvec); - tsubn.getF32ptr()[3] = handedness; + if ((u.greaterEqual(LLVector4a::getZero()).getGatheredBits() & 0x7) && + (u.lessEqual(det).getGatheredBits() & 0x7)) + { + /* prepare to test V parameter */ + LLVector4a qvec; + qvec.setCross3(tvec, edge1); - tangent_out = tsubn; - } - else - { - // degenerate, make up a value - // - tangent_out.set(0,0,1,1); - } + /* calculate V parameter and test bounds */ + LLVector4a v; + v.setAllDot3(dir, qvec); -} + //if (!(v < 0.f || u + v > det)) -// intersect test between triangle vert0, vert1, vert2 and a ray from orig in direction dir. -// returns true if intersecting and returns barycentric coordinates in intersection_a, intersection_b, -// and returns the intersection point along dir in intersection_t. + LLVector4a sum_uv; + sum_uv.setAdd(u, v); -// Moller-Trumbore algorithm -bool LLTriangleRayIntersect(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir, - F32& intersection_a, F32& intersection_b, F32& intersection_t) -{ - - /* find vectors for two edges sharing vert0 */ - LLVector4a edge1; - edge1.setSub(vert1, vert0); - - LLVector4a edge2; - edge2.setSub(vert2, vert0); - - /* begin calculating determinant - also used to calculate U parameter */ - LLVector4a pvec; - pvec.setCross3(dir, edge2); - - /* if determinant is near zero, ray lies in plane of triangle */ - LLVector4a det; - det.setAllDot3(edge1, pvec); - - if (det.greaterEqual(LLVector4a::getEpsilon()).getGatheredBits() & 0x7) - { - /* calculate distance from vert0 to ray origin */ - LLVector4a tvec; - tvec.setSub(orig, vert0); - - /* calculate U parameter and test bounds */ - LLVector4a u; - u.setAllDot3(tvec,pvec); - - if ((u.greaterEqual(LLVector4a::getZero()).getGatheredBits() & 0x7) && - (u.lessEqual(det).getGatheredBits() & 0x7)) - { - /* prepare to test V parameter */ - LLVector4a qvec; - qvec.setCross3(tvec, edge1); - - /* calculate V parameter and test bounds */ - LLVector4a v; - v.setAllDot3(dir, qvec); - - - //if (!(v < 0.f || u + v > det)) - - LLVector4a sum_uv; - sum_uv.setAdd(u, v); - - S32 v_gequal = v.greaterEqual(LLVector4a::getZero()).getGatheredBits() & 0x7; - S32 sum_lequal = sum_uv.lessEqual(det).getGatheredBits() & 0x7; - - if (v_gequal && sum_lequal) - { - /* calculate t, scale parameters, ray intersects triangle */ - LLVector4a t; - t.setAllDot3(edge2,qvec); - - t.div(det); - u.div(det); - v.div(det); - - intersection_a = u[0]; - intersection_b = v[0]; - intersection_t = t[0]; - return true; - } - } - } - - return false; -} + S32 v_gequal = v.greaterEqual(LLVector4a::getZero()).getGatheredBits() & 0x7; + S32 sum_lequal = sum_uv.lessEqual(det).getGatheredBits() & 0x7; + + if (v_gequal && sum_lequal) + { + /* calculate t, scale parameters, ray intersects triangle */ + LLVector4a t; + t.setAllDot3(edge2,qvec); + + t.div(det); + u.div(det); + v.div(det); + + intersection_a = u[0]; + intersection_b = v[0]; + intersection_t = t[0]; + return true; + } + } + } + + return false; +} bool LLTriangleRayIntersectTwoSided(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir, - F32& intersection_a, F32& intersection_b, F32& intersection_t) -{ - F32 u, v, t; - - /* find vectors for two edges sharing vert0 */ - LLVector4a edge1; - edge1.setSub(vert1, vert0); - - - LLVector4a edge2; - edge2.setSub(vert2, vert0); - - /* begin calculating determinant - also used to calculate U parameter */ - LLVector4a pvec; - pvec.setCross3(dir, edge2); - - /* if determinant is near zero, ray lies in plane of triangle */ - F32 det = edge1.dot3(pvec).getF32(); - - - if (det > -F_APPROXIMATELY_ZERO && det < F_APPROXIMATELY_ZERO) - { - return false; - } - - F32 inv_det = 1.f / det; - - /* calculate distance from vert0 to ray origin */ - LLVector4a tvec; - tvec.setSub(orig, vert0); - - /* calculate U parameter and test bounds */ - u = (tvec.dot3(pvec).getF32()) * inv_det; - if (u < 0.f || u > 1.f) - { - return false; - } - - /* prepare to test V parameter */ - tvec.sub(edge1); - - /* calculate V parameter and test bounds */ - v = (dir.dot3(tvec).getF32()) * inv_det; - - if (v < 0.f || u + v > 1.f) - { - return false; - } - - /* calculate t, ray intersects triangle */ - t = (edge2.dot3(tvec).getF32()) * inv_det; - - intersection_a = u; - intersection_b = v; - intersection_t = t; - - - return true; -} + F32& intersection_a, F32& intersection_b, F32& intersection_t) +{ + F32 u, v, t; + + /* find vectors for two edges sharing vert0 */ + LLVector4a edge1; + edge1.setSub(vert1, vert0); + + + LLVector4a edge2; + edge2.setSub(vert2, vert0); + + /* begin calculating determinant - also used to calculate U parameter */ + LLVector4a pvec; + pvec.setCross3(dir, edge2); + + /* if determinant is near zero, ray lies in plane of triangle */ + F32 det = edge1.dot3(pvec).getF32(); + + + if (det > -F_APPROXIMATELY_ZERO && det < F_APPROXIMATELY_ZERO) + { + return false; + } + + F32 inv_det = 1.f / det; + + /* calculate distance from vert0 to ray origin */ + LLVector4a tvec; + tvec.setSub(orig, vert0); + + /* calculate U parameter and test bounds */ + u = (tvec.dot3(pvec).getF32()) * inv_det; + if (u < 0.f || u > 1.f) + { + return false; + } + + /* prepare to test V parameter */ + tvec.sub(edge1); + + /* calculate V parameter and test bounds */ + v = (dir.dot3(tvec).getF32()) * inv_det; + + if (v < 0.f || u + v > 1.f) + { + return false; + } + + /* calculate t, ray intersects triangle */ + t = (edge2.dot3(tvec).getF32()) * inv_det; + + intersection_a = u; + intersection_b = v; + intersection_t = t; + + + return true; +} //------------------------------------------------------------------- // statics @@ -362,91 +362,91 @@ bool LLTriangleRayIntersectTwoSided(const LLVector4a& vert0, const LLVector4a& v LLProfile::Face* LLProfile::addCap(S16 faceID) { - Face *face = vector_append(mFaces, 1); - - face->mIndex = 0; - face->mCount = mTotal; - face->mScaleU= 1.0f; - face->mCap = true; - face->mFaceID = faceID; - return face; + Face *face = vector_append(mFaces, 1); + + face->mIndex = 0; + face->mCount = mTotal; + face->mScaleU= 1.0f; + face->mCap = true; + face->mFaceID = faceID; + return face; } LLProfile::Face* LLProfile::addFace(S32 i, S32 count, F32 scaleU, S16 faceID, bool flat) { - Face *face = vector_append(mFaces, 1); - - face->mIndex = i; - face->mCount = count; - face->mScaleU= scaleU; + Face *face = vector_append(mFaces, 1); + + face->mIndex = i; + face->mCount = count; + face->mScaleU= scaleU; - face->mFlat = flat; - face->mCap = false; - face->mFaceID = faceID; - return face; + face->mFlat = flat; + face->mCap = false; + face->mFaceID = faceID; + return face; } //static S32 LLProfile::getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset, F32 bevel, F32 ang_scale, S32 split) { // this is basically LLProfile::genNGon stripped down to only the operations that influence the number of points - S32 np = 0; - - // Generate an n-sided "circular" path. - // 0 is (1,0), and we go counter-clockwise along a circular path from there. - F32 t, t_step, t_first, t_fraction; - - F32 begin = params.getBegin(); - F32 end = params.getEnd(); - - t_step = 1.0f / sides; - - t_first = floor(begin * sides) / (F32)sides; - - // pt1 is the first point on the fractional face. - // Starting t and ang values for the first face - t = t_first; - - // Increment to the next point. - // pt2 is the end point on the fractional face - t += t_step; - - t_fraction = (begin - t_first)*sides; - - // Only use if it's not almost exactly on an edge. - if (t_fraction < 0.9999f) - { - np++; - } - - // There's lots of potential here for floating point error to generate unneeded extra points - DJS 04/05/02 - while (t < end) - { - // Iterate through all the integer steps of t. - np++; - - t += t_step; - } - - t_fraction = (end - (t - t_step))*sides; - - // Find the fraction that we need to add to the end point. - t_fraction = (end - (t - t_step))*sides; - if (t_fraction > 0.0001f) - { - np++; - } - - // If we're sliced, the profile is open. - if ((end - begin)*ang_scale < 0.99f) - { - if (params.getHollow() <= 0) - { - // put center point if not hollow. - np++; - } - } - - return np; + S32 np = 0; + + // Generate an n-sided "circular" path. + // 0 is (1,0), and we go counter-clockwise along a circular path from there. + F32 t, t_step, t_first, t_fraction; + + F32 begin = params.getBegin(); + F32 end = params.getEnd(); + + t_step = 1.0f / sides; + + t_first = floor(begin * sides) / (F32)sides; + + // pt1 is the first point on the fractional face. + // Starting t and ang values for the first face + t = t_first; + + // Increment to the next point. + // pt2 is the end point on the fractional face + t += t_step; + + t_fraction = (begin - t_first)*sides; + + // Only use if it's not almost exactly on an edge. + if (t_fraction < 0.9999f) + { + np++; + } + + // There's lots of potential here for floating point error to generate unneeded extra points - DJS 04/05/02 + while (t < end) + { + // Iterate through all the integer steps of t. + np++; + + t += t_step; + } + + t_fraction = (end - (t - t_step))*sides; + + // Find the fraction that we need to add to the end point. + t_fraction = (end - (t - t_step))*sides; + if (t_fraction > 0.0001f) + { + np++; + } + + // If we're sliced, the profile is open. + if ((end - begin)*ang_scale < 0.99f) + { + if (params.getHollow() <= 0) + { + // put center point if not hollow. + np++; + } + } + + return np; } // What is the bevel parameter used for? - DJS 04/05/02 @@ -454,129 +454,129 @@ S32 LLProfile::getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 of // filleted and chamfered corners void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F32 bevel, F32 ang_scale, S32 split) { - // Generate an n-sided "circular" path. - // 0 is (1,0), and we go counter-clockwise along a circular path from there. - constexpr F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; - F32 scale = 0.5f; - F32 t, t_step, t_first, t_fraction, ang, ang_step; - LLVector4a pt1,pt2; - - F32 begin = params.getBegin(); - F32 end = params.getEnd(); - - t_step = 1.0f / sides; - ang_step = 2.0f*F_PI*t_step*ang_scale; - - // Scale to have size "match" scale. Compensates to get object to generally fill bounding box. - - S32 total_sides = ll_round(sides / ang_scale); // Total number of sides all around - - if (total_sides < 8) - { - scale = tableScale[total_sides]; - } - - t_first = floor(begin * sides) / (F32)sides; - - // pt1 is the first point on the fractional face. - // Starting t and ang values for the first face - t = t_first; - ang = 2.0f*F_PI*(t*ang_scale + offset); - pt1.set(cos(ang)*scale,sin(ang)*scale, t); - - // Increment to the next point. - // pt2 is the end point on the fractional face - t += t_step; - ang += ang_step; - pt2.set(cos(ang)*scale,sin(ang)*scale,t); - - t_fraction = (begin - t_first)*sides; - - // Only use if it's not almost exactly on an edge. - if (t_fraction < 0.9999f) - { - LLVector4a new_pt; - new_pt.setLerp(pt1, pt2, t_fraction); - mProfile.push_back(new_pt); - } - - // There's lots of potential here for floating point error to generate unneeded extra points - DJS 04/05/02 - while (t < end) - { - // Iterate through all the integer steps of t. - pt1.set(cos(ang)*scale,sin(ang)*scale,t); - - if (mProfile.size() > 0) { - LLVector4a p = mProfile[mProfile.size()-1]; - for (S32 i = 0; i < split && mProfile.size() > 0; i++) { - //mProfile.push_back(p+(pt1-p) * 1.0f/(float)(split+1) * (float)(i+1)); - LLVector4a new_pt; - new_pt.setSub(pt1, p); - new_pt.mul(1.0f/(float)(split+1) * (float)(i+1)); - new_pt.add(p); - mProfile.push_back(new_pt); - } - } - mProfile.push_back(pt1); - - t += t_step; - ang += ang_step; - } - - t_fraction = (end - (t - t_step))*sides; - - // pt1 is the first point on the fractional face - // pt2 is the end point on the fractional face - pt2.set(cos(ang)*scale,sin(ang)*scale,t); - - // Find the fraction that we need to add to the end point. - t_fraction = (end - (t - t_step))*sides; - if (t_fraction > 0.0001f) - { - LLVector4a new_pt; - new_pt.setLerp(pt1, pt2, t_fraction); - - if (mProfile.size() > 0) { - LLVector4a p = mProfile[mProfile.size()-1]; - for (S32 i = 0; i < split && mProfile.size() > 0; i++) { - //mProfile.push_back(p+(new_pt-p) * 1.0f/(float)(split+1) * (float)(i+1)); - - LLVector4a pt1; - pt1.setSub(new_pt, p); - pt1.mul(1.0f/(float)(split+1) * (float)(i+1)); - pt1.add(p); - mProfile.push_back(pt1); - } - } - mProfile.push_back(new_pt); - } - - // If we're sliced, the profile is open. - if ((end - begin)*ang_scale < 0.99f) - { - if ((end - begin)*ang_scale > 0.5f) - { - mConcave = true; - } - else - { - mConcave = false; - } - mOpen = true; - if (params.getHollow() <= 0) - { - // put center point if not hollow. - mProfile.push_back(LLVector4a(0,0,0)); - } - } - else - { - // The profile isn't open. - mOpen = false; - mConcave = false; - } - - mTotal = mProfile.size(); + // Generate an n-sided "circular" path. + // 0 is (1,0), and we go counter-clockwise along a circular path from there. + constexpr F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; + F32 scale = 0.5f; + F32 t, t_step, t_first, t_fraction, ang, ang_step; + LLVector4a pt1,pt2; + + F32 begin = params.getBegin(); + F32 end = params.getEnd(); + + t_step = 1.0f / sides; + ang_step = 2.0f*F_PI*t_step*ang_scale; + + // Scale to have size "match" scale. Compensates to get object to generally fill bounding box. + + S32 total_sides = ll_round(sides / ang_scale); // Total number of sides all around + + if (total_sides < 8) + { + scale = tableScale[total_sides]; + } + + t_first = floor(begin * sides) / (F32)sides; + + // pt1 is the first point on the fractional face. + // Starting t and ang values for the first face + t = t_first; + ang = 2.0f*F_PI*(t*ang_scale + offset); + pt1.set(cos(ang)*scale,sin(ang)*scale, t); + + // Increment to the next point. + // pt2 is the end point on the fractional face + t += t_step; + ang += ang_step; + pt2.set(cos(ang)*scale,sin(ang)*scale,t); + + t_fraction = (begin - t_first)*sides; + + // Only use if it's not almost exactly on an edge. + if (t_fraction < 0.9999f) + { + LLVector4a new_pt; + new_pt.setLerp(pt1, pt2, t_fraction); + mProfile.push_back(new_pt); + } + + // There's lots of potential here for floating point error to generate unneeded extra points - DJS 04/05/02 + while (t < end) + { + // Iterate through all the integer steps of t. + pt1.set(cos(ang)*scale,sin(ang)*scale,t); + + if (mProfile.size() > 0) { + LLVector4a p = mProfile[mProfile.size()-1]; + for (S32 i = 0; i < split && mProfile.size() > 0; i++) { + //mProfile.push_back(p+(pt1-p) * 1.0f/(float)(split+1) * (float)(i+1)); + LLVector4a new_pt; + new_pt.setSub(pt1, p); + new_pt.mul(1.0f/(float)(split+1) * (float)(i+1)); + new_pt.add(p); + mProfile.push_back(new_pt); + } + } + mProfile.push_back(pt1); + + t += t_step; + ang += ang_step; + } + + t_fraction = (end - (t - t_step))*sides; + + // pt1 is the first point on the fractional face + // pt2 is the end point on the fractional face + pt2.set(cos(ang)*scale,sin(ang)*scale,t); + + // Find the fraction that we need to add to the end point. + t_fraction = (end - (t - t_step))*sides; + if (t_fraction > 0.0001f) + { + LLVector4a new_pt; + new_pt.setLerp(pt1, pt2, t_fraction); + + if (mProfile.size() > 0) { + LLVector4a p = mProfile[mProfile.size()-1]; + for (S32 i = 0; i < split && mProfile.size() > 0; i++) { + //mProfile.push_back(p+(new_pt-p) * 1.0f/(float)(split+1) * (float)(i+1)); + + LLVector4a pt1; + pt1.setSub(new_pt, p); + pt1.mul(1.0f/(float)(split+1) * (float)(i+1)); + pt1.add(p); + mProfile.push_back(pt1); + } + } + mProfile.push_back(new_pt); + } + + // If we're sliced, the profile is open. + if ((end - begin)*ang_scale < 0.99f) + { + if ((end - begin)*ang_scale > 0.5f) + { + mConcave = true; + } + else + { + mConcave = false; + } + mOpen = true; + if (params.getHollow() <= 0) + { + // put center point if not hollow. + mProfile.push_back(LLVector4a(0,0,0)); + } + } + else + { + // The profile isn't open. + mOpen = false; + mConcave = false; + } + + mTotal = mProfile.size(); } // Hollow is percent of the original bounding box, not of this particular @@ -584,603 +584,603 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3 // a swept square. LLProfile::Face* LLProfile::addHole(const LLProfileParams& params, bool flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split) { - // Note that addHole will NOT work for non-"circular" profiles, if we ever decide to use them. + // Note that addHole will NOT work for non-"circular" profiles, if we ever decide to use them. - // Total add has number of vertices on outside. - mTotalOut = mTotal; + // Total add has number of vertices on outside. + mTotalOut = mTotal; - // Why is the "bevel" parameter -1? DJS 04/05/02 - genNGon(params, llfloor(sides),offset,-1, ang_scale, split); + // Why is the "bevel" parameter -1? DJS 04/05/02 + genNGon(params, llfloor(sides),offset,-1, ang_scale, split); - Face *face = addFace(mTotalOut, mTotal-mTotalOut,0,LL_FACE_INNER_SIDE, flat); + Face *face = addFace(mTotalOut, mTotal-mTotalOut,0,LL_FACE_INNER_SIDE, flat); - static thread_local LLAlignedArray<LLVector4a,64> pt; - pt.resize(mTotal) ; + static thread_local LLAlignedArray<LLVector4a,64> pt; + pt.resize(mTotal) ; - for (S32 i=mTotalOut;i<mTotal;i++) - { - pt[i] = mProfile[i]; - pt[i].mul(box_hollow); - } + for (S32 i=mTotalOut;i<mTotal;i++) + { + pt[i] = mProfile[i]; + pt[i].mul(box_hollow); + } - S32 j=mTotal-1; - for (S32 i=mTotalOut;i<mTotal;i++) - { - mProfile[i] = pt[j--]; - } + S32 j=mTotal-1; + for (S32 i=mTotalOut;i<mTotal;i++) + { + mProfile[i] = pt[j--]; + } - for (S32 i=0;i<(S32)mFaces.size();i++) - { - if (mFaces[i].mCap) - { - mFaces[i].mCount *= 2; - } - } + for (S32 i=0;i<(S32)mFaces.size();i++) + { + if (mFaces[i].mCap) + { + mFaces[i].mCount *= 2; + } + } - return face; + return face; } //static S32 LLProfile::getNumPoints(const LLProfileParams& params, bool path_open,F32 detail, S32 split, - bool is_sculpted, S32 sculpt_size) + bool is_sculpted, S32 sculpt_size) { // this is basically LLProfile::generate stripped down to only operations that influence the number of points - if (detail < MIN_LOD) - { - detail = MIN_LOD; - } - - // Generate the face data - F32 hollow = params.getHollow(); - - S32 np = 0; - - switch (params.getCurveType() & LL_PCODE_PROFILE_MASK) - { - case LL_PCODE_PROFILE_SQUARE: - { - np = getNumNGonPoints(params, 4,-0.375, 0, 1, split); - - if (hollow) - { - np *= 2; - } - } - break; - case LL_PCODE_PROFILE_ISOTRI: - case LL_PCODE_PROFILE_RIGHTTRI: - case LL_PCODE_PROFILE_EQUALTRI: - { - np = getNumNGonPoints(params, 3,0, 0, 1, split); - - if (hollow) - { - np *= 2; - } - } - break; - case LL_PCODE_PROFILE_CIRCLE: - { - // If this has a square hollow, we should adjust the - // number of faces a bit so that the geometry lines up. - U8 hole_type=0; - F32 circle_detail = MIN_DETAIL_FACES * detail; - if (hollow) - { - hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK; - if (hole_type == LL_PCODE_HOLE_SQUARE) - { - // Snap to the next multiple of four sides, - // so that corners line up. - circle_detail = llceil(circle_detail / 4.0f) * 4.0f; - } - } - - S32 sides = (S32)circle_detail; - - if (is_sculpted) - sides = sculpt_size; - - np = getNumNGonPoints(params, sides); - - if (hollow) - { - np *= 2; - } - } - break; - case LL_PCODE_PROFILE_CIRCLE_HALF: - { - // If this has a square hollow, we should adjust the - // number of faces a bit so that the geometry lines up. - U8 hole_type=0; - // Number of faces is cut in half because it's only a half-circle. - F32 circle_detail = MIN_DETAIL_FACES * detail * 0.5f; - if (hollow) - { - hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK; - if (hole_type == LL_PCODE_HOLE_SQUARE) - { - // Snap to the next multiple of four sides (div 2), - // so that corners line up. - circle_detail = llceil(circle_detail / 2.0f) * 2.0f; - } - } - np = getNumNGonPoints(params, llfloor(circle_detail), 0.5f, 0.f, 0.5f); - - if (hollow) - { - np *= 2; - } - - // Special case for openness of sphere - if ((params.getEnd() - params.getBegin()) < 1.f) - { - } - else if (!hollow) - { - np++; - } - } - break; - default: - break; - }; - - - return np; + if (detail < MIN_LOD) + { + detail = MIN_LOD; + } + + // Generate the face data + F32 hollow = params.getHollow(); + + S32 np = 0; + + switch (params.getCurveType() & LL_PCODE_PROFILE_MASK) + { + case LL_PCODE_PROFILE_SQUARE: + { + np = getNumNGonPoints(params, 4,-0.375, 0, 1, split); + + if (hollow) + { + np *= 2; + } + } + break; + case LL_PCODE_PROFILE_ISOTRI: + case LL_PCODE_PROFILE_RIGHTTRI: + case LL_PCODE_PROFILE_EQUALTRI: + { + np = getNumNGonPoints(params, 3,0, 0, 1, split); + + if (hollow) + { + np *= 2; + } + } + break; + case LL_PCODE_PROFILE_CIRCLE: + { + // If this has a square hollow, we should adjust the + // number of faces a bit so that the geometry lines up. + U8 hole_type=0; + F32 circle_detail = MIN_DETAIL_FACES * detail; + if (hollow) + { + hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK; + if (hole_type == LL_PCODE_HOLE_SQUARE) + { + // Snap to the next multiple of four sides, + // so that corners line up. + circle_detail = llceil(circle_detail / 4.0f) * 4.0f; + } + } + + S32 sides = (S32)circle_detail; + + if (is_sculpted) + sides = sculpt_size; + + np = getNumNGonPoints(params, sides); + + if (hollow) + { + np *= 2; + } + } + break; + case LL_PCODE_PROFILE_CIRCLE_HALF: + { + // If this has a square hollow, we should adjust the + // number of faces a bit so that the geometry lines up. + U8 hole_type=0; + // Number of faces is cut in half because it's only a half-circle. + F32 circle_detail = MIN_DETAIL_FACES * detail * 0.5f; + if (hollow) + { + hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK; + if (hole_type == LL_PCODE_HOLE_SQUARE) + { + // Snap to the next multiple of four sides (div 2), + // so that corners line up. + circle_detail = llceil(circle_detail / 2.0f) * 2.0f; + } + } + np = getNumNGonPoints(params, llfloor(circle_detail), 0.5f, 0.f, 0.5f); + + if (hollow) + { + np *= 2; + } + + // Special case for openness of sphere + if ((params.getEnd() - params.getBegin()) < 1.f) + { + } + else if (!hollow) + { + np++; + } + } + break; + default: + break; + }; + + + return np; } bool LLProfile::generate(const LLProfileParams& params, bool path_open,F32 detail, S32 split, - bool is_sculpted, S32 sculpt_size) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME - - if ((!mDirty) && (!is_sculpted)) - { - return false; - } - mDirty = false; - - if (detail < MIN_LOD) - { - LL_INFOS() << "Generating profile with LOD < MIN_LOD. CLAMPING" << LL_ENDL; - detail = MIN_LOD; - } - - mProfile.resize(0); - mFaces.resize(0); - - // Generate the face data - S32 i; - F32 begin = params.getBegin(); - F32 end = params.getEnd(); - F32 hollow = params.getHollow(); - - // Quick validation to eliminate some server crashes. - if (begin > end - 0.01f) - { - LL_WARNS() << "LLProfile::generate() assertion failed (begin >= end)" << LL_ENDL; - return false; - } - - S32 face_num = 0; - - switch (params.getCurveType() & LL_PCODE_PROFILE_MASK) - { - case LL_PCODE_PROFILE_SQUARE: - { - genNGon(params, 4,-0.375, 0, 1, split); - if (path_open) - { - addCap (LL_FACE_PATH_BEGIN); - } - - for (i = llfloor(begin * 4.f); i < llfloor(end * 4.f + .999f); i++) - { - addFace((face_num++) * (split +1), split+2, 1, LL_FACE_OUTER_SIDE_0 << i, true); - } - - LLVector4a scale(1,1,4,1); - - for (i = 0; i <(S32) mProfile.size(); i++) - { - // Scale by 4 to generate proper tex coords. - mProfile[i].mul(scale); - llassert(mProfile[i].isFinite3()); - } - - if (hollow) - { - switch (params.getCurveType() & LL_PCODE_HOLE_MASK) - { - case LL_PCODE_HOLE_TRIANGLE: - // This offset is not correct, but we can't change it now... DK 11/17/04 - addHole(params, true, 3, -0.375f, hollow, 1.f, split); - break; - case LL_PCODE_HOLE_CIRCLE: - // TODO: Compute actual detail levels for cubes - addHole(params, false, MIN_DETAIL_FACES * detail, -0.375f, hollow, 1.f); - break; - case LL_PCODE_HOLE_SAME: - case LL_PCODE_HOLE_SQUARE: - default: - addHole(params, true, 4, -0.375f, hollow, 1.f, split); - break; - } - } - - if (path_open) { - mFaces[0].mCount = mTotal; - } - } - break; - case LL_PCODE_PROFILE_ISOTRI: - case LL_PCODE_PROFILE_RIGHTTRI: - case LL_PCODE_PROFILE_EQUALTRI: - { - genNGon(params, 3,0, 0, 1, split); - LLVector4a scale(1,1,3,1); - for (i = 0; i <(S32) mProfile.size(); i++) - { - // Scale by 3 to generate proper tex coords. - mProfile[i].mul(scale); - llassert(mProfile[i].isFinite3()); - } - - if (path_open) - { - addCap(LL_FACE_PATH_BEGIN); - } - - for (i = llfloor(begin * 3.f); i < llfloor(end * 3.f + .999f); i++) - { - addFace((face_num++) * (split +1), split+2, 1, LL_FACE_OUTER_SIDE_0 << i, true); - } - if (hollow) - { - // Swept triangles need smaller hollowness values, - // because the triangle doesn't fill the bounding box. - F32 triangle_hollow = hollow / 2.f; - - switch (params.getCurveType() & LL_PCODE_HOLE_MASK) - { - case LL_PCODE_HOLE_CIRCLE: - // TODO: Actually generate level of detail for triangles - addHole(params, false, MIN_DETAIL_FACES * detail, 0, triangle_hollow, 1.f); - break; - case LL_PCODE_HOLE_SQUARE: - addHole(params, true, 4, 0, triangle_hollow, 1.f, split); - break; - case LL_PCODE_HOLE_SAME: - case LL_PCODE_HOLE_TRIANGLE: - default: - addHole(params, true, 3, 0, triangle_hollow, 1.f, split); - break; - } - } - } - break; - case LL_PCODE_PROFILE_CIRCLE: - { - // If this has a square hollow, we should adjust the - // number of faces a bit so that the geometry lines up. - U8 hole_type=0; - F32 circle_detail = MIN_DETAIL_FACES * detail; - if (hollow) - { - hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK; - if (hole_type == LL_PCODE_HOLE_SQUARE) - { - // Snap to the next multiple of four sides, - // so that corners line up. - circle_detail = llceil(circle_detail / 4.0f) * 4.0f; - } - } - - S32 sides = (S32)circle_detail; - - if (is_sculpted) - sides = sculpt_size; - - genNGon(params, sides); - - if (path_open) - { - addCap (LL_FACE_PATH_BEGIN); - } - - if (mOpen && !hollow) - { - addFace(0,mTotal-1,0,LL_FACE_OUTER_SIDE_0, false); - } - else - { - addFace(0,mTotal,0,LL_FACE_OUTER_SIDE_0, false); - } - - if (hollow) - { - switch (hole_type) - { - case LL_PCODE_HOLE_SQUARE: - addHole(params, true, 4, 0, hollow, 1.f, split); - break; - case LL_PCODE_HOLE_TRIANGLE: - addHole(params, true, 3, 0, hollow, 1.f, split); - break; - case LL_PCODE_HOLE_CIRCLE: - case LL_PCODE_HOLE_SAME: - default: - addHole(params, true, circle_detail, 0, hollow, 1.f); - break; - } - } - } - break; - case LL_PCODE_PROFILE_CIRCLE_HALF: - { - // If this has a square hollow, we should adjust the - // number of faces a bit so that the geometry lines up. - U8 hole_type=0; - // Number of faces is cut in half because it's only a half-circle. - F32 circle_detail = MIN_DETAIL_FACES * detail * 0.5f; - if (hollow) - { - hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK; - if (hole_type == LL_PCODE_HOLE_SQUARE) - { - // Snap to the next multiple of four sides (div 2), - // so that corners line up. - circle_detail = llceil(circle_detail / 2.0f) * 2.0f; - } - } - genNGon(params, llfloor(circle_detail), 0.5f, 0.f, 0.5f); - if (path_open) - { - addCap(LL_FACE_PATH_BEGIN); - } - if (mOpen && !params.getHollow()) - { - addFace(0,mTotal-1,0,LL_FACE_OUTER_SIDE_0, false); - } - else - { - addFace(0,mTotal,0,LL_FACE_OUTER_SIDE_0, false); - } - - if (hollow) - { - switch (hole_type) - { - case LL_PCODE_HOLE_SQUARE: - addHole(params, true, 2, 0.5f, hollow, 0.5f, split); - break; - case LL_PCODE_HOLE_TRIANGLE: - addHole(params, true, 3, 0.5f, hollow, 0.5f, split); - break; - case LL_PCODE_HOLE_CIRCLE: - case LL_PCODE_HOLE_SAME: - default: - addHole(params, false, circle_detail, 0.5f, hollow, 0.5f); - break; - } - } - - // Special case for openness of sphere - if ((params.getEnd() - params.getBegin()) < 1.f) - { - mOpen = true; - } - else if (!hollow) - { - mOpen = false; - mProfile.push_back(mProfile[0]); - mTotal++; - } - } - break; - default: - LL_ERRS() << "Unknown profile: getCurveType()=" << params.getCurveType() << LL_ENDL; - break; - }; - - if (path_open) - { - addCap(LL_FACE_PATH_END); // bottom - } - - if ( mOpen) // interior edge caps - { - addFace(mTotal-1, 2,0.5,LL_FACE_PROFILE_BEGIN, true); - - if (hollow) - { - addFace(mTotalOut-1, 2,0.5,LL_FACE_PROFILE_END, true); - } - else - { - addFace(mTotal-2, 2,0.5,LL_FACE_PROFILE_END, true); - } - } - - return true; + bool is_sculpted, S32 sculpt_size) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME + + if ((!mDirty) && (!is_sculpted)) + { + return false; + } + mDirty = false; + + if (detail < MIN_LOD) + { + LL_INFOS() << "Generating profile with LOD < MIN_LOD. CLAMPING" << LL_ENDL; + detail = MIN_LOD; + } + + mProfile.resize(0); + mFaces.resize(0); + + // Generate the face data + S32 i; + F32 begin = params.getBegin(); + F32 end = params.getEnd(); + F32 hollow = params.getHollow(); + + // Quick validation to eliminate some server crashes. + if (begin > end - 0.01f) + { + LL_WARNS() << "LLProfile::generate() assertion failed (begin >= end)" << LL_ENDL; + return false; + } + + S32 face_num = 0; + + switch (params.getCurveType() & LL_PCODE_PROFILE_MASK) + { + case LL_PCODE_PROFILE_SQUARE: + { + genNGon(params, 4,-0.375, 0, 1, split); + if (path_open) + { + addCap (LL_FACE_PATH_BEGIN); + } + + for (i = llfloor(begin * 4.f); i < llfloor(end * 4.f + .999f); i++) + { + addFace((face_num++) * (split +1), split+2, 1, LL_FACE_OUTER_SIDE_0 << i, true); + } + + LLVector4a scale(1,1,4,1); + + for (i = 0; i <(S32) mProfile.size(); i++) + { + // Scale by 4 to generate proper tex coords. + mProfile[i].mul(scale); + llassert(mProfile[i].isFinite3()); + } + + if (hollow) + { + switch (params.getCurveType() & LL_PCODE_HOLE_MASK) + { + case LL_PCODE_HOLE_TRIANGLE: + // This offset is not correct, but we can't change it now... DK 11/17/04 + addHole(params, true, 3, -0.375f, hollow, 1.f, split); + break; + case LL_PCODE_HOLE_CIRCLE: + // TODO: Compute actual detail levels for cubes + addHole(params, false, MIN_DETAIL_FACES * detail, -0.375f, hollow, 1.f); + break; + case LL_PCODE_HOLE_SAME: + case LL_PCODE_HOLE_SQUARE: + default: + addHole(params, true, 4, -0.375f, hollow, 1.f, split); + break; + } + } + + if (path_open) { + mFaces[0].mCount = mTotal; + } + } + break; + case LL_PCODE_PROFILE_ISOTRI: + case LL_PCODE_PROFILE_RIGHTTRI: + case LL_PCODE_PROFILE_EQUALTRI: + { + genNGon(params, 3,0, 0, 1, split); + LLVector4a scale(1,1,3,1); + for (i = 0; i <(S32) mProfile.size(); i++) + { + // Scale by 3 to generate proper tex coords. + mProfile[i].mul(scale); + llassert(mProfile[i].isFinite3()); + } + + if (path_open) + { + addCap(LL_FACE_PATH_BEGIN); + } + + for (i = llfloor(begin * 3.f); i < llfloor(end * 3.f + .999f); i++) + { + addFace((face_num++) * (split +1), split+2, 1, LL_FACE_OUTER_SIDE_0 << i, true); + } + if (hollow) + { + // Swept triangles need smaller hollowness values, + // because the triangle doesn't fill the bounding box. + F32 triangle_hollow = hollow / 2.f; + + switch (params.getCurveType() & LL_PCODE_HOLE_MASK) + { + case LL_PCODE_HOLE_CIRCLE: + // TODO: Actually generate level of detail for triangles + addHole(params, false, MIN_DETAIL_FACES * detail, 0, triangle_hollow, 1.f); + break; + case LL_PCODE_HOLE_SQUARE: + addHole(params, true, 4, 0, triangle_hollow, 1.f, split); + break; + case LL_PCODE_HOLE_SAME: + case LL_PCODE_HOLE_TRIANGLE: + default: + addHole(params, true, 3, 0, triangle_hollow, 1.f, split); + break; + } + } + } + break; + case LL_PCODE_PROFILE_CIRCLE: + { + // If this has a square hollow, we should adjust the + // number of faces a bit so that the geometry lines up. + U8 hole_type=0; + F32 circle_detail = MIN_DETAIL_FACES * detail; + if (hollow) + { + hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK; + if (hole_type == LL_PCODE_HOLE_SQUARE) + { + // Snap to the next multiple of four sides, + // so that corners line up. + circle_detail = llceil(circle_detail / 4.0f) * 4.0f; + } + } + + S32 sides = (S32)circle_detail; + + if (is_sculpted) + sides = sculpt_size; + + genNGon(params, sides); + + if (path_open) + { + addCap (LL_FACE_PATH_BEGIN); + } + + if (mOpen && !hollow) + { + addFace(0,mTotal-1,0,LL_FACE_OUTER_SIDE_0, false); + } + else + { + addFace(0,mTotal,0,LL_FACE_OUTER_SIDE_0, false); + } + + if (hollow) + { + switch (hole_type) + { + case LL_PCODE_HOLE_SQUARE: + addHole(params, true, 4, 0, hollow, 1.f, split); + break; + case LL_PCODE_HOLE_TRIANGLE: + addHole(params, true, 3, 0, hollow, 1.f, split); + break; + case LL_PCODE_HOLE_CIRCLE: + case LL_PCODE_HOLE_SAME: + default: + addHole(params, true, circle_detail, 0, hollow, 1.f); + break; + } + } + } + break; + case LL_PCODE_PROFILE_CIRCLE_HALF: + { + // If this has a square hollow, we should adjust the + // number of faces a bit so that the geometry lines up. + U8 hole_type=0; + // Number of faces is cut in half because it's only a half-circle. + F32 circle_detail = MIN_DETAIL_FACES * detail * 0.5f; + if (hollow) + { + hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK; + if (hole_type == LL_PCODE_HOLE_SQUARE) + { + // Snap to the next multiple of four sides (div 2), + // so that corners line up. + circle_detail = llceil(circle_detail / 2.0f) * 2.0f; + } + } + genNGon(params, llfloor(circle_detail), 0.5f, 0.f, 0.5f); + if (path_open) + { + addCap(LL_FACE_PATH_BEGIN); + } + if (mOpen && !params.getHollow()) + { + addFace(0,mTotal-1,0,LL_FACE_OUTER_SIDE_0, false); + } + else + { + addFace(0,mTotal,0,LL_FACE_OUTER_SIDE_0, false); + } + + if (hollow) + { + switch (hole_type) + { + case LL_PCODE_HOLE_SQUARE: + addHole(params, true, 2, 0.5f, hollow, 0.5f, split); + break; + case LL_PCODE_HOLE_TRIANGLE: + addHole(params, true, 3, 0.5f, hollow, 0.5f, split); + break; + case LL_PCODE_HOLE_CIRCLE: + case LL_PCODE_HOLE_SAME: + default: + addHole(params, false, circle_detail, 0.5f, hollow, 0.5f); + break; + } + } + + // Special case for openness of sphere + if ((params.getEnd() - params.getBegin()) < 1.f) + { + mOpen = true; + } + else if (!hollow) + { + mOpen = false; + mProfile.push_back(mProfile[0]); + mTotal++; + } + } + break; + default: + LL_ERRS() << "Unknown profile: getCurveType()=" << params.getCurveType() << LL_ENDL; + break; + }; + + if (path_open) + { + addCap(LL_FACE_PATH_END); // bottom + } + + if ( mOpen) // interior edge caps + { + addFace(mTotal-1, 2,0.5,LL_FACE_PROFILE_BEGIN, true); + + if (hollow) + { + addFace(mTotalOut-1, 2,0.5,LL_FACE_PROFILE_END, true); + } + else + { + addFace(mTotal-2, 2,0.5,LL_FACE_PROFILE_END, true); + } + } + + return true; } bool LLProfileParams::importFile(LLFILE *fp) { - const S32 BUFSIZE = 16384; - char buffer[BUFSIZE]; /* Flawfinder: ignore */ - // *NOTE: changing the size or type of these buffers will require - // changing the sscanf below. - char keyword[256]; /* Flawfinder: ignore */ - char valuestr[256]; /* Flawfinder: ignore */ - keyword[0] = 0; - valuestr[0] = 0; - F32 tempF32; - U32 tempU32; - - while (!feof(fp)) - { - if (fgets(buffer, BUFSIZE, fp) == NULL) - { - buffer[0] = '\0'; - } - - sscanf( /* Flawfinder: ignore */ - buffer, - " %255s %255s", - keyword, valuestr); - if (!strcmp("{", keyword)) - { - continue; - } - if (!strcmp("}",keyword)) - { - break; - } - else if (!strcmp("curve", keyword)) - { - sscanf(valuestr,"%d",&tempU32); - setCurveType((U8) tempU32); - } - else if (!strcmp("begin",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setBegin(tempF32); - } - else if (!strcmp("end",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setEnd(tempF32); - } - else if (!strcmp("hollow",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setHollow(tempF32); - } - else - { - LL_WARNS() << "unknown keyword " << keyword << " in profile import" << LL_ENDL; - } - } - - return true; + const S32 BUFSIZE = 16384; + char buffer[BUFSIZE]; /* Flawfinder: ignore */ + // *NOTE: changing the size or type of these buffers will require + // changing the sscanf below. + char keyword[256]; /* Flawfinder: ignore */ + char valuestr[256]; /* Flawfinder: ignore */ + keyword[0] = 0; + valuestr[0] = 0; + F32 tempF32; + U32 tempU32; + + while (!feof(fp)) + { + if (fgets(buffer, BUFSIZE, fp) == NULL) + { + buffer[0] = '\0'; + } + + sscanf( /* Flawfinder: ignore */ + buffer, + " %255s %255s", + keyword, valuestr); + if (!strcmp("{", keyword)) + { + continue; + } + if (!strcmp("}",keyword)) + { + break; + } + else if (!strcmp("curve", keyword)) + { + sscanf(valuestr,"%d",&tempU32); + setCurveType((U8) tempU32); + } + else if (!strcmp("begin",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setBegin(tempF32); + } + else if (!strcmp("end",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setEnd(tempF32); + } + else if (!strcmp("hollow",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setHollow(tempF32); + } + else + { + LL_WARNS() << "unknown keyword " << keyword << " in profile import" << LL_ENDL; + } + } + + return true; } bool LLProfileParams::exportFile(LLFILE *fp) const { - fprintf(fp,"\t\tprofile 0\n"); - fprintf(fp,"\t\t{\n"); - fprintf(fp,"\t\t\tcurve\t%d\n", getCurveType()); - fprintf(fp,"\t\t\tbegin\t%g\n", getBegin()); - fprintf(fp,"\t\t\tend\t%g\n", getEnd()); - fprintf(fp,"\t\t\thollow\t%g\n", getHollow()); - fprintf(fp, "\t\t}\n"); - return true; + fprintf(fp,"\t\tprofile 0\n"); + fprintf(fp,"\t\t{\n"); + fprintf(fp,"\t\t\tcurve\t%d\n", getCurveType()); + fprintf(fp,"\t\t\tbegin\t%g\n", getBegin()); + fprintf(fp,"\t\t\tend\t%g\n", getEnd()); + fprintf(fp,"\t\t\thollow\t%g\n", getHollow()); + fprintf(fp, "\t\t}\n"); + return true; } bool LLProfileParams::importLegacyStream(std::istream& input_stream) { - const S32 BUFSIZE = 16384; - char buffer[BUFSIZE]; /* Flawfinder: ignore */ - // *NOTE: changing the size or type of these buffers will require - // changing the sscanf below. - char keyword[256]; /* Flawfinder: ignore */ - char valuestr[256]; /* Flawfinder: ignore */ - keyword[0] = 0; - valuestr[0] = 0; - F32 tempF32; - U32 tempU32; - - while (input_stream.good()) - { - input_stream.getline(buffer, BUFSIZE); - sscanf( /* Flawfinder: ignore */ - buffer, - " %255s %255s", - keyword, - valuestr); - if (!strcmp("{", keyword)) - { - continue; - } - if (!strcmp("}",keyword)) - { - break; - } - else if (!strcmp("curve", keyword)) - { - sscanf(valuestr,"%d",&tempU32); - setCurveType((U8) tempU32); - } - else if (!strcmp("begin",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setBegin(tempF32); - } - else if (!strcmp("end",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setEnd(tempF32); - } - else if (!strcmp("hollow",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setHollow(tempF32); - } - else - { - LL_WARNS() << "unknown keyword " << keyword << " in profile import" << LL_ENDL; - } - } - - return true; + const S32 BUFSIZE = 16384; + char buffer[BUFSIZE]; /* Flawfinder: ignore */ + // *NOTE: changing the size or type of these buffers will require + // changing the sscanf below. + char keyword[256]; /* Flawfinder: ignore */ + char valuestr[256]; /* Flawfinder: ignore */ + keyword[0] = 0; + valuestr[0] = 0; + F32 tempF32; + U32 tempU32; + + while (input_stream.good()) + { + input_stream.getline(buffer, BUFSIZE); + sscanf( /* Flawfinder: ignore */ + buffer, + " %255s %255s", + keyword, + valuestr); + if (!strcmp("{", keyword)) + { + continue; + } + if (!strcmp("}",keyword)) + { + break; + } + else if (!strcmp("curve", keyword)) + { + sscanf(valuestr,"%d",&tempU32); + setCurveType((U8) tempU32); + } + else if (!strcmp("begin",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setBegin(tempF32); + } + else if (!strcmp("end",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setEnd(tempF32); + } + else if (!strcmp("hollow",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setHollow(tempF32); + } + else + { + LL_WARNS() << "unknown keyword " << keyword << " in profile import" << LL_ENDL; + } + } + + return true; } bool LLProfileParams::exportLegacyStream(std::ostream& output_stream) const { - output_stream <<"\t\tprofile 0\n"; - output_stream <<"\t\t{\n"; - output_stream <<"\t\t\tcurve\t" << (S32) getCurveType() << "\n"; - output_stream <<"\t\t\tbegin\t" << getBegin() << "\n"; - output_stream <<"\t\t\tend\t" << getEnd() << "\n"; - output_stream <<"\t\t\thollow\t" << getHollow() << "\n"; - output_stream << "\t\t}\n"; - return true; + output_stream <<"\t\tprofile 0\n"; + output_stream <<"\t\t{\n"; + output_stream <<"\t\t\tcurve\t" << (S32) getCurveType() << "\n"; + output_stream <<"\t\t\tbegin\t" << getBegin() << "\n"; + output_stream <<"\t\t\tend\t" << getEnd() << "\n"; + output_stream <<"\t\t\thollow\t" << getHollow() << "\n"; + output_stream << "\t\t}\n"; + return true; } LLSD LLProfileParams::asLLSD() const { - LLSD sd; + LLSD sd; - sd["curve"] = getCurveType(); - sd["begin"] = getBegin(); - sd["end"] = getEnd(); - sd["hollow"] = getHollow(); - return sd; + sd["curve"] = getCurveType(); + sd["begin"] = getBegin(); + sd["end"] = getEnd(); + sd["hollow"] = getHollow(); + return sd; } bool LLProfileParams::fromLLSD(LLSD& sd) { - setCurveType(sd["curve"].asInteger()); - setBegin((F32)sd["begin"].asReal()); - setEnd((F32)sd["end"].asReal()); - setHollow((F32)sd["hollow"].asReal()); - return true; + setCurveType(sd["curve"].asInteger()); + setBegin((F32)sd["begin"].asReal()); + setEnd((F32)sd["end"].asReal()); + setHollow((F32)sd["hollow"].asReal()); + return true; } void LLProfileParams::copyParams(const LLProfileParams ¶ms) { - setCurveType(params.getCurveType()); - setBegin(params.getBegin()); - setEnd(params.getEnd()); - setHollow(params.getHollow()); + setCurveType(params.getCurveType()); + setBegin(params.getBegin()); + setEnd(params.getEnd()); + setHollow(params.getHollow()); } @@ -1190,760 +1190,760 @@ LLPath::~LLPath() S32 LLPath::getNumNGonPoints(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale) { //this is basically LLPath::genNGon stripped down to only operations that influence the number of points added - S32 ret = 0; + S32 ret = 0; - F32 step= 1.0f / sides; - F32 t = params.getBegin(); - ret = 1; - - t+=step; + F32 step= 1.0f / sides; + F32 t = params.getBegin(); + ret = 1; - // Snap to a quantized parameter, so that cut does not - // affect most sample points. - t = ((S32)(t * sides)) / (F32)sides; + t+=step; - // Run through the non-cut dependent points. - while (t < params.getEnd()) - { - ret++; - t+=step; - } + // Snap to a quantized parameter, so that cut does not + // affect most sample points. + t = ((S32)(t * sides)) / (F32)sides; - ret++; + // Run through the non-cut dependent points. + while (t < params.getEnd()) + { + ret++; + t+=step; + } - return ret; + ret++; + + return ret; } void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME - - // Generates a circular path, starting at (1, 0, 0), counterclockwise along the xz plane. - constexpr F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; - - F32 revolutions = params.getRevolutions(); - F32 skew = params.getSkew(); - F32 skew_mag = fabs(skew); - F32 hole_x = params.getScaleX() * (1.0f - skew_mag); - F32 hole_y = params.getScaleY(); - - // Calculate taper begin/end for x,y (Negative means taper the beginning) - F32 taper_x_begin = 1.0f; - F32 taper_x_end = 1.0f - params.getTaperX(); - F32 taper_y_begin = 1.0f; - F32 taper_y_end = 1.0f - params.getTaperY(); - - if ( taper_x_end > 1.0f ) - { - // Flip tapering. - taper_x_begin = 2.0f - taper_x_end; - taper_x_end = 1.0f; - } - if ( taper_y_end > 1.0f ) - { - // Flip tapering. - taper_y_begin = 2.0f - taper_y_end; - taper_y_end = 1.0f; - } - - // For spheres, the radius is usually zero. - F32 radius_start = 0.5f; - if (sides < 8) - { - radius_start = tableScale[sides]; - } - - // Scale the radius to take the hole size into account. - radius_start *= 1.0f - hole_y; - - // Now check the radius offset to calculate the start,end radius. (Negative means - // decrease the start radius instead). - F32 radius_end = radius_start; - F32 radius_offset = params.getRadiusOffset(); - if (radius_offset < 0.f) - { - radius_start *= 1.f + radius_offset; - } - else - { - radius_end *= 1.f - radius_offset; - } - - // Is the path NOT a closed loop? - mOpen = ( (params.getEnd()*end_scale - params.getBegin() < 1.0f) || - (skew_mag > 0.001f) || - (fabs(taper_x_end - taper_x_begin) > 0.001f) || - (fabs(taper_y_end - taper_y_begin) > 0.001f) || - (fabs(radius_end - radius_start) > 0.001f) ); - - F32 ang, c, s; - LLQuaternion twist, qang; - PathPt *pt; - LLVector3 path_axis (1.f, 0.f, 0.f); - //LLVector3 twist_axis(0.f, 0.f, 1.f); - F32 twist_begin = params.getTwistBegin() * twist_scale; - F32 twist_end = params.getTwist() * twist_scale; - - // We run through this once before the main loop, to make sure - // the path begins at the correct cut. - F32 step= 1.0f / sides; - F32 t = params.getBegin(); - pt = mPath.append(1); - ang = 2.0f*F_PI*revolutions * t; - s = sin(ang)*lerp(radius_start, radius_end, t); - c = cos(ang)*lerp(radius_start, radius_end, t); - - - pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s) - + lerp(-skew ,skew, t) * 0.5f, - c + lerp(0,params.getShear().mV[1],s), - s); - pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t), - hole_y * lerp(taper_y_begin, taper_y_end, t), - 0,1); - pt->mTexT = t; - - // Twist rotates the path along the x,y plane (I think) - DJS 04/05/02 - twist.setQuat (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1); - // Rotate the point around the circle's center. - qang.setQuat (ang,path_axis); - - LLMatrix3 rot(twist * qang); - - pt->mRot.loadu(rot); - - t+=step; - - // Snap to a quantized parameter, so that cut does not - // affect most sample points. - t = ((S32)(t * sides)) / (F32)sides; - - // Run through the non-cut dependent points. - while (t < params.getEnd()) - { - pt = mPath.append(1); - - ang = 2.0f*F_PI*revolutions * t; - c = cos(ang)*lerp(radius_start, radius_end, t); - s = sin(ang)*lerp(radius_start, radius_end, t); - - pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s) - + lerp(-skew ,skew, t) * 0.5f, - c + lerp(0,params.getShear().mV[1],s), - s); - - pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t), - hole_y * lerp(taper_y_begin, taper_y_end, t), - 0,1); - pt->mTexT = t; - - // Twist rotates the path along the x,y plane (I think) - DJS 04/05/02 - twist.setQuat (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1); - // Rotate the point around the circle's center. - qang.setQuat (ang,path_axis); - LLMatrix3 tmp(twist*qang); - pt->mRot.loadu(tmp); - - t+=step; - } - - // Make one final pass for the end cut. - t = params.getEnd(); - pt = mPath.append(1); - ang = 2.0f*F_PI*revolutions * t; - c = cos(ang)*lerp(radius_start, radius_end, t); - s = sin(ang)*lerp(radius_start, radius_end, t); - - pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s) - + lerp(-skew ,skew, t) * 0.5f, - c + lerp(0,params.getShear().mV[1],s), - s); - pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t), - hole_y * lerp(taper_y_begin, taper_y_end, t), - 0,1); - pt->mTexT = t; - - // Twist rotates the path along the x,y plane (I think) - DJS 04/05/02 - twist.setQuat (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1); - // Rotate the point around the circle's center. - qang.setQuat (ang,path_axis); - LLMatrix3 tmp(twist*qang); - pt->mRot.loadu(tmp); - - mTotal = mPath.size(); + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME + + // Generates a circular path, starting at (1, 0, 0), counterclockwise along the xz plane. + constexpr F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; + + F32 revolutions = params.getRevolutions(); + F32 skew = params.getSkew(); + F32 skew_mag = fabs(skew); + F32 hole_x = params.getScaleX() * (1.0f - skew_mag); + F32 hole_y = params.getScaleY(); + + // Calculate taper begin/end for x,y (Negative means taper the beginning) + F32 taper_x_begin = 1.0f; + F32 taper_x_end = 1.0f - params.getTaperX(); + F32 taper_y_begin = 1.0f; + F32 taper_y_end = 1.0f - params.getTaperY(); + + if ( taper_x_end > 1.0f ) + { + // Flip tapering. + taper_x_begin = 2.0f - taper_x_end; + taper_x_end = 1.0f; + } + if ( taper_y_end > 1.0f ) + { + // Flip tapering. + taper_y_begin = 2.0f - taper_y_end; + taper_y_end = 1.0f; + } + + // For spheres, the radius is usually zero. + F32 radius_start = 0.5f; + if (sides < 8) + { + radius_start = tableScale[sides]; + } + + // Scale the radius to take the hole size into account. + radius_start *= 1.0f - hole_y; + + // Now check the radius offset to calculate the start,end radius. (Negative means + // decrease the start radius instead). + F32 radius_end = radius_start; + F32 radius_offset = params.getRadiusOffset(); + if (radius_offset < 0.f) + { + radius_start *= 1.f + radius_offset; + } + else + { + radius_end *= 1.f - radius_offset; + } + + // Is the path NOT a closed loop? + mOpen = ( (params.getEnd()*end_scale - params.getBegin() < 1.0f) || + (skew_mag > 0.001f) || + (fabs(taper_x_end - taper_x_begin) > 0.001f) || + (fabs(taper_y_end - taper_y_begin) > 0.001f) || + (fabs(radius_end - radius_start) > 0.001f) ); + + F32 ang, c, s; + LLQuaternion twist, qang; + PathPt *pt; + LLVector3 path_axis (1.f, 0.f, 0.f); + //LLVector3 twist_axis(0.f, 0.f, 1.f); + F32 twist_begin = params.getTwistBegin() * twist_scale; + F32 twist_end = params.getTwist() * twist_scale; + + // We run through this once before the main loop, to make sure + // the path begins at the correct cut. + F32 step= 1.0f / sides; + F32 t = params.getBegin(); + pt = mPath.append(1); + ang = 2.0f*F_PI*revolutions * t; + s = sin(ang)*lerp(radius_start, radius_end, t); + c = cos(ang)*lerp(radius_start, radius_end, t); + + + pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s) + + lerp(-skew ,skew, t) * 0.5f, + c + lerp(0,params.getShear().mV[1],s), + s); + pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t), + hole_y * lerp(taper_y_begin, taper_y_end, t), + 0,1); + pt->mTexT = t; + + // Twist rotates the path along the x,y plane (I think) - DJS 04/05/02 + twist.setQuat (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1); + // Rotate the point around the circle's center. + qang.setQuat (ang,path_axis); + + LLMatrix3 rot(twist * qang); + + pt->mRot.loadu(rot); + + t+=step; + + // Snap to a quantized parameter, so that cut does not + // affect most sample points. + t = ((S32)(t * sides)) / (F32)sides; + + // Run through the non-cut dependent points. + while (t < params.getEnd()) + { + pt = mPath.append(1); + + ang = 2.0f*F_PI*revolutions * t; + c = cos(ang)*lerp(radius_start, radius_end, t); + s = sin(ang)*lerp(radius_start, radius_end, t); + + pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s) + + lerp(-skew ,skew, t) * 0.5f, + c + lerp(0,params.getShear().mV[1],s), + s); + + pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t), + hole_y * lerp(taper_y_begin, taper_y_end, t), + 0,1); + pt->mTexT = t; + + // Twist rotates the path along the x,y plane (I think) - DJS 04/05/02 + twist.setQuat (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1); + // Rotate the point around the circle's center. + qang.setQuat (ang,path_axis); + LLMatrix3 tmp(twist*qang); + pt->mRot.loadu(tmp); + + t+=step; + } + + // Make one final pass for the end cut. + t = params.getEnd(); + pt = mPath.append(1); + ang = 2.0f*F_PI*revolutions * t; + c = cos(ang)*lerp(radius_start, radius_end, t); + s = sin(ang)*lerp(radius_start, radius_end, t); + + pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s) + + lerp(-skew ,skew, t) * 0.5f, + c + lerp(0,params.getShear().mV[1],s), + s); + pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t), + hole_y * lerp(taper_y_begin, taper_y_end, t), + 0,1); + pt->mTexT = t; + + // Twist rotates the path along the x,y plane (I think) - DJS 04/05/02 + twist.setQuat (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1); + // Rotate the point around the circle's center. + qang.setQuat (ang,path_axis); + LLMatrix3 tmp(twist*qang); + pt->mRot.loadu(tmp); + + mTotal = mPath.size(); } const LLVector2 LLPathParams::getBeginScale() const { - LLVector2 begin_scale(1.f, 1.f); - if (getScaleX() > 1) - { - begin_scale.mV[0] = 2-getScaleX(); - } - if (getScaleY() > 1) - { - begin_scale.mV[1] = 2-getScaleY(); - } - return begin_scale; + LLVector2 begin_scale(1.f, 1.f); + if (getScaleX() > 1) + { + begin_scale.mV[0] = 2-getScaleX(); + } + if (getScaleY() > 1) + { + begin_scale.mV[1] = 2-getScaleY(); + } + return begin_scale; } const LLVector2 LLPathParams::getEndScale() const { - LLVector2 end_scale(1.f, 1.f); - if (getScaleX() < 1) - { - end_scale.mV[0] = getScaleX(); - } - if (getScaleY() < 1) - { - end_scale.mV[1] = getScaleY(); - } - return end_scale; + LLVector2 end_scale(1.f, 1.f); + if (getScaleX() < 1) + { + end_scale.mV[0] = getScaleX(); + } + if (getScaleY() < 1) + { + end_scale.mV[1] = getScaleY(); + } + return end_scale; } S32 LLPath::getNumPoints(const LLPathParams& params, F32 detail) { // this is basically LLPath::generate stripped down to only the operations that influence the number of points - if (detail < MIN_LOD) - { - detail = MIN_LOD; - } + if (detail < MIN_LOD) + { + detail = MIN_LOD; + } - S32 np = 2; // hardcode for line + S32 np = 2; // hardcode for line - // Is this 0xf0 mask really necessary? DK 03/02/05 + // Is this 0xf0 mask really necessary? DK 03/02/05 - switch (params.getCurveType() & 0xf0) - { - default: - case LL_PCODE_PATH_LINE: - { - // Take the begin/end twist into account for detail. - np = llfloor(fabs(params.getTwistBegin() - params.getTwist()) * 3.5f * (detail-0.5f)) + 2; - } - break; + switch (params.getCurveType() & 0xf0) + { + default: + case LL_PCODE_PATH_LINE: + { + // Take the begin/end twist into account for detail. + np = llfloor(fabs(params.getTwistBegin() - params.getTwist()) * 3.5f * (detail-0.5f)) + 2; + } + break; - case LL_PCODE_PATH_CIRCLE: - { - // Increase the detail as the revolutions and twist increase. - F32 twist_mag = fabs(params.getTwistBegin() - params.getTwist()); + case LL_PCODE_PATH_CIRCLE: + { + // Increase the detail as the revolutions and twist increase. + F32 twist_mag = fabs(params.getTwistBegin() - params.getTwist()); - S32 sides = (S32)llfloor(llfloor((MIN_DETAIL_FACES * detail + twist_mag * 3.5f * (detail-0.5f))) * params.getRevolutions()); + S32 sides = (S32)llfloor(llfloor((MIN_DETAIL_FACES * detail + twist_mag * 3.5f * (detail-0.5f))) * params.getRevolutions()); - np = sides; - } - break; + np = sides; + } + break; - case LL_PCODE_PATH_CIRCLE2: - { - //genNGon(params, llfloor(MIN_DETAIL_FACES * detail), 4.f, 0.f); - np = getNumNGonPoints(params, llfloor(MIN_DETAIL_FACES * detail)); - } - break; + case LL_PCODE_PATH_CIRCLE2: + { + //genNGon(params, llfloor(MIN_DETAIL_FACES * detail), 4.f, 0.f); + np = getNumNGonPoints(params, llfloor(MIN_DETAIL_FACES * detail)); + } + break; - case LL_PCODE_PATH_TEST: + case LL_PCODE_PATH_TEST: - np = 5; - break; - }; + np = 5; + break; + }; - return np; + return np; } bool LLPath::generate(const LLPathParams& params, F32 detail, S32 split, - bool is_sculpted, S32 sculpt_size) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME - - if ((!mDirty) && (!is_sculpted)) - { - return false; - } - - if (detail < MIN_LOD) - { - LL_INFOS() << "Generating path with LOD < MIN! Clamping to 1" << LL_ENDL; - detail = MIN_LOD; - } - - mDirty = false; - S32 np = 2; // hardcode for line - - mPath.resize(0); - mOpen = true; - - // Is this 0xf0 mask really necessary? DK 03/02/05 - switch (params.getCurveType() & 0xf0) - { - default: - case LL_PCODE_PATH_LINE: - { - // Take the begin/end twist into account for detail. - np = llfloor(fabs(params.getTwistBegin() - params.getTwist()) * 3.5f * (detail-0.5f)) + 2; - if (np < split+2) - { - np = split+2; - } - - mStep = 1.0f / (np-1); - - mPath.resize(np); - - LLVector2 start_scale = params.getBeginScale(); - LLVector2 end_scale = params.getEndScale(); - - for (S32 i=0;i<np;i++) - { - F32 t = lerp(params.getBegin(),params.getEnd(),(F32)i * mStep); - mPath[i].mPos.set(lerp(0,params.getShear().mV[0],t), - lerp(0,params.getShear().mV[1],t), - t - 0.5f); - LLQuaternion quat; - quat.setQuat(lerp(F_PI * params.getTwistBegin(),F_PI * params.getTwist(),t),0,0,1); - LLMatrix3 tmp(quat); - mPath[i].mRot.loadu(tmp); - mPath[i].mScale.set(lerp(start_scale.mV[0],end_scale.mV[0],t), - lerp(start_scale.mV[1],end_scale.mV[1],t), - 0,1); - mPath[i].mTexT = t; - } - } - break; - - case LL_PCODE_PATH_CIRCLE: - { - // Increase the detail as the revolutions and twist increase. - F32 twist_mag = fabs(params.getTwistBegin() - params.getTwist()); - - S32 sides = (S32)llfloor(llfloor((MIN_DETAIL_FACES * detail + twist_mag * 3.5f * (detail-0.5f))) * params.getRevolutions()); - - if (is_sculpted) - sides = llmax(sculpt_size, 1); - - if (0 < sides) - genNGon(params, sides); - } - break; - - case LL_PCODE_PATH_CIRCLE2: - { - if (params.getEnd() - params.getBegin() >= 0.99f && - params.getScaleX() >= .99f) - { - mOpen = false; - } - - //genNGon(params, llfloor(MIN_DETAIL_FACES * detail), 4.f, 0.f); - genNGon(params, llfloor(MIN_DETAIL_FACES * detail)); - - F32 toggle = 0.5f; - for (S32 i=0;i<(S32)mPath.size();i++) - { - mPath[i].mPos.getF32ptr()[0] = toggle; - if (toggle == 0.5f) - toggle = -0.5f; - else - toggle = 0.5f; - } - } - - break; - - case LL_PCODE_PATH_TEST: - - np = 5; - mStep = 1.0f / (np-1); - - mPath.resize(np); - - for (S32 i=0;i<np;i++) - { - F32 t = (F32)i * mStep; - mPath[i].mPos.set(0, - lerp(0, -sin(F_PI*params.getTwist()*t)*0.5f,t), - lerp(-0.5f, cos(F_PI*params.getTwist()*t)*0.5f,t)); - mPath[i].mScale.set(lerp(1,params.getScale().mV[0],t), - lerp(1,params.getScale().mV[1],t), 0,1); - mPath[i].mTexT = t; - LLQuaternion quat; - quat.setQuat(F_PI * params.getTwist() * t,1,0,0); - LLMatrix3 tmp(quat); - mPath[i].mRot.loadu(tmp); - } - - break; - }; - - if (params.getTwist() != params.getTwistBegin()) mOpen = true; - - //if ((int(fabsf(params.getTwist() - params.getTwistBegin())*100))%100 != 0) { - // mOpen = true; - //} - - return true; + bool is_sculpted, S32 sculpt_size) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME + + if ((!mDirty) && (!is_sculpted)) + { + return false; + } + + if (detail < MIN_LOD) + { + LL_INFOS() << "Generating path with LOD < MIN! Clamping to 1" << LL_ENDL; + detail = MIN_LOD; + } + + mDirty = false; + S32 np = 2; // hardcode for line + + mPath.resize(0); + mOpen = true; + + // Is this 0xf0 mask really necessary? DK 03/02/05 + switch (params.getCurveType() & 0xf0) + { + default: + case LL_PCODE_PATH_LINE: + { + // Take the begin/end twist into account for detail. + np = llfloor(fabs(params.getTwistBegin() - params.getTwist()) * 3.5f * (detail-0.5f)) + 2; + if (np < split+2) + { + np = split+2; + } + + mStep = 1.0f / (np-1); + + mPath.resize(np); + + LLVector2 start_scale = params.getBeginScale(); + LLVector2 end_scale = params.getEndScale(); + + for (S32 i=0;i<np;i++) + { + F32 t = lerp(params.getBegin(),params.getEnd(),(F32)i * mStep); + mPath[i].mPos.set(lerp(0,params.getShear().mV[0],t), + lerp(0,params.getShear().mV[1],t), + t - 0.5f); + LLQuaternion quat; + quat.setQuat(lerp(F_PI * params.getTwistBegin(),F_PI * params.getTwist(),t),0,0,1); + LLMatrix3 tmp(quat); + mPath[i].mRot.loadu(tmp); + mPath[i].mScale.set(lerp(start_scale.mV[0],end_scale.mV[0],t), + lerp(start_scale.mV[1],end_scale.mV[1],t), + 0,1); + mPath[i].mTexT = t; + } + } + break; + + case LL_PCODE_PATH_CIRCLE: + { + // Increase the detail as the revolutions and twist increase. + F32 twist_mag = fabs(params.getTwistBegin() - params.getTwist()); + + S32 sides = (S32)llfloor(llfloor((MIN_DETAIL_FACES * detail + twist_mag * 3.5f * (detail-0.5f))) * params.getRevolutions()); + + if (is_sculpted) + sides = llmax(sculpt_size, 1); + + if (0 < sides) + genNGon(params, sides); + } + break; + + case LL_PCODE_PATH_CIRCLE2: + { + if (params.getEnd() - params.getBegin() >= 0.99f && + params.getScaleX() >= .99f) + { + mOpen = false; + } + + //genNGon(params, llfloor(MIN_DETAIL_FACES * detail), 4.f, 0.f); + genNGon(params, llfloor(MIN_DETAIL_FACES * detail)); + + F32 toggle = 0.5f; + for (S32 i=0;i<(S32)mPath.size();i++) + { + mPath[i].mPos.getF32ptr()[0] = toggle; + if (toggle == 0.5f) + toggle = -0.5f; + else + toggle = 0.5f; + } + } + + break; + + case LL_PCODE_PATH_TEST: + + np = 5; + mStep = 1.0f / (np-1); + + mPath.resize(np); + + for (S32 i=0;i<np;i++) + { + F32 t = (F32)i * mStep; + mPath[i].mPos.set(0, + lerp(0, -sin(F_PI*params.getTwist()*t)*0.5f,t), + lerp(-0.5f, cos(F_PI*params.getTwist()*t)*0.5f,t)); + mPath[i].mScale.set(lerp(1,params.getScale().mV[0],t), + lerp(1,params.getScale().mV[1],t), 0,1); + mPath[i].mTexT = t; + LLQuaternion quat; + quat.setQuat(F_PI * params.getTwist() * t,1,0,0); + LLMatrix3 tmp(quat); + mPath[i].mRot.loadu(tmp); + } + + break; + }; + + if (params.getTwist() != params.getTwistBegin()) mOpen = true; + + //if ((int(fabsf(params.getTwist() - params.getTwistBegin())*100))%100 != 0) { + // mOpen = true; + //} + + return true; } bool LLDynamicPath::generate(const LLPathParams& params, F32 detail, S32 split, - bool is_sculpted, S32 sculpt_size) + bool is_sculpted, S32 sculpt_size) { - mOpen = true; // Draw end caps - if (getPathLength() == 0) - { - // Path hasn't been generated yet. - // Some algorithms later assume at least TWO path points. - resizePath(2); - LLQuaternion quat; - quat.setQuat(0,0,0); - LLMatrix3 tmp(quat); - - for (U32 i = 0; i < 2; i++) - { - mPath[i].mPos.set(0, 0, 0); - mPath[i].mRot.loadu(tmp); - mPath[i].mScale.set(1, 1, 0, 1); - mPath[i].mTexT = 0; - } - } + mOpen = true; // Draw end caps + if (getPathLength() == 0) + { + // Path hasn't been generated yet. + // Some algorithms later assume at least TWO path points. + resizePath(2); + LLQuaternion quat; + quat.setQuat(0,0,0); + LLMatrix3 tmp(quat); + + for (U32 i = 0; i < 2; i++) + { + mPath[i].mPos.set(0, 0, 0); + mPath[i].mRot.loadu(tmp); + mPath[i].mScale.set(1, 1, 0, 1); + mPath[i].mTexT = 0; + } + } - return true; + return true; } bool LLPathParams::importFile(LLFILE *fp) { - const S32 BUFSIZE = 16384; - char buffer[BUFSIZE]; /* Flawfinder: ignore */ - // *NOTE: changing the size or type of these buffers will require - // changing the sscanf below. - char keyword[256]; /* Flawfinder: ignore */ - char valuestr[256]; /* Flawfinder: ignore */ - keyword[0] = 0; - valuestr[0] = 0; - - F32 tempF32; - F32 x, y; - U32 tempU32; - - while (!feof(fp)) - { - if (fgets(buffer, BUFSIZE, fp) == NULL) - { - buffer[0] = '\0'; - } - - sscanf( /* Flawfinder: ignore */ - buffer, - " %255s %255s", - keyword, valuestr); - if (!strcmp("{", keyword)) - { - continue; - } - if (!strcmp("}",keyword)) - { - break; - } - else if (!strcmp("curve", keyword)) - { - sscanf(valuestr,"%d",&tempU32); - setCurveType((U8) tempU32); - } - else if (!strcmp("begin",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setBegin(tempF32); - } - else if (!strcmp("end",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setEnd(tempF32); - } - else if (!strcmp("scale",keyword)) - { - // Legacy for one dimensional scale per path - sscanf(valuestr,"%g",&tempF32); - setScale(tempF32, tempF32); - } - else if (!strcmp("scale_x", keyword)) - { - sscanf(valuestr, "%g", &x); - setScaleX(x); - } - else if (!strcmp("scale_y", keyword)) - { - sscanf(valuestr, "%g", &y); - setScaleY(y); - } - else if (!strcmp("shear_x", keyword)) - { - sscanf(valuestr, "%g", &x); - setShearX(x); - } - else if (!strcmp("shear_y", keyword)) - { - sscanf(valuestr, "%g", &y); - setShearY(y); - } - else if (!strcmp("twist",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setTwist(tempF32); - } - else if (!strcmp("twist_begin", keyword)) - { - sscanf(valuestr, "%g", &y); - setTwistBegin(y); - } - else if (!strcmp("radius_offset", keyword)) - { - sscanf(valuestr, "%g", &y); - setRadiusOffset(y); - } - else if (!strcmp("taper_x", keyword)) - { - sscanf(valuestr, "%g", &y); - setTaperX(y); - } - else if (!strcmp("taper_y", keyword)) - { - sscanf(valuestr, "%g", &y); - setTaperY(y); - } - else if (!strcmp("revolutions", keyword)) - { - sscanf(valuestr, "%g", &y); - setRevolutions(y); - } - else if (!strcmp("skew", keyword)) - { - sscanf(valuestr, "%g", &y); - setSkew(y); - } - else - { - LL_WARNS() << "unknown keyword " << " in path import" << LL_ENDL; - } - } - return true; + const S32 BUFSIZE = 16384; + char buffer[BUFSIZE]; /* Flawfinder: ignore */ + // *NOTE: changing the size or type of these buffers will require + // changing the sscanf below. + char keyword[256]; /* Flawfinder: ignore */ + char valuestr[256]; /* Flawfinder: ignore */ + keyword[0] = 0; + valuestr[0] = 0; + + F32 tempF32; + F32 x, y; + U32 tempU32; + + while (!feof(fp)) + { + if (fgets(buffer, BUFSIZE, fp) == NULL) + { + buffer[0] = '\0'; + } + + sscanf( /* Flawfinder: ignore */ + buffer, + " %255s %255s", + keyword, valuestr); + if (!strcmp("{", keyword)) + { + continue; + } + if (!strcmp("}",keyword)) + { + break; + } + else if (!strcmp("curve", keyword)) + { + sscanf(valuestr,"%d",&tempU32); + setCurveType((U8) tempU32); + } + else if (!strcmp("begin",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setBegin(tempF32); + } + else if (!strcmp("end",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setEnd(tempF32); + } + else if (!strcmp("scale",keyword)) + { + // Legacy for one dimensional scale per path + sscanf(valuestr,"%g",&tempF32); + setScale(tempF32, tempF32); + } + else if (!strcmp("scale_x", keyword)) + { + sscanf(valuestr, "%g", &x); + setScaleX(x); + } + else if (!strcmp("scale_y", keyword)) + { + sscanf(valuestr, "%g", &y); + setScaleY(y); + } + else if (!strcmp("shear_x", keyword)) + { + sscanf(valuestr, "%g", &x); + setShearX(x); + } + else if (!strcmp("shear_y", keyword)) + { + sscanf(valuestr, "%g", &y); + setShearY(y); + } + else if (!strcmp("twist",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setTwist(tempF32); + } + else if (!strcmp("twist_begin", keyword)) + { + sscanf(valuestr, "%g", &y); + setTwistBegin(y); + } + else if (!strcmp("radius_offset", keyword)) + { + sscanf(valuestr, "%g", &y); + setRadiusOffset(y); + } + else if (!strcmp("taper_x", keyword)) + { + sscanf(valuestr, "%g", &y); + setTaperX(y); + } + else if (!strcmp("taper_y", keyword)) + { + sscanf(valuestr, "%g", &y); + setTaperY(y); + } + else if (!strcmp("revolutions", keyword)) + { + sscanf(valuestr, "%g", &y); + setRevolutions(y); + } + else if (!strcmp("skew", keyword)) + { + sscanf(valuestr, "%g", &y); + setSkew(y); + } + else + { + LL_WARNS() << "unknown keyword " << " in path import" << LL_ENDL; + } + } + return true; } bool LLPathParams::exportFile(LLFILE *fp) const { - fprintf(fp, "\t\tpath 0\n"); - fprintf(fp, "\t\t{\n"); - fprintf(fp, "\t\t\tcurve\t%d\n", getCurveType()); - fprintf(fp, "\t\t\tbegin\t%g\n", getBegin()); - fprintf(fp, "\t\t\tend\t%g\n", getEnd()); - fprintf(fp, "\t\t\tscale_x\t%g\n", getScaleX() ); - fprintf(fp, "\t\t\tscale_y\t%g\n", getScaleY() ); - fprintf(fp, "\t\t\tshear_x\t%g\n", getShearX() ); - fprintf(fp, "\t\t\tshear_y\t%g\n", getShearY() ); - fprintf(fp,"\t\t\ttwist\t%g\n", getTwist()); - - fprintf(fp,"\t\t\ttwist_begin\t%g\n", getTwistBegin()); - fprintf(fp,"\t\t\tradius_offset\t%g\n", getRadiusOffset()); - fprintf(fp,"\t\t\ttaper_x\t%g\n", getTaperX()); - fprintf(fp,"\t\t\ttaper_y\t%g\n", getTaperY()); - fprintf(fp,"\t\t\trevolutions\t%g\n", getRevolutions()); - fprintf(fp,"\t\t\tskew\t%g\n", getSkew()); - - fprintf(fp, "\t\t}\n"); - return true; + fprintf(fp, "\t\tpath 0\n"); + fprintf(fp, "\t\t{\n"); + fprintf(fp, "\t\t\tcurve\t%d\n", getCurveType()); + fprintf(fp, "\t\t\tbegin\t%g\n", getBegin()); + fprintf(fp, "\t\t\tend\t%g\n", getEnd()); + fprintf(fp, "\t\t\tscale_x\t%g\n", getScaleX() ); + fprintf(fp, "\t\t\tscale_y\t%g\n", getScaleY() ); + fprintf(fp, "\t\t\tshear_x\t%g\n", getShearX() ); + fprintf(fp, "\t\t\tshear_y\t%g\n", getShearY() ); + fprintf(fp,"\t\t\ttwist\t%g\n", getTwist()); + + fprintf(fp,"\t\t\ttwist_begin\t%g\n", getTwistBegin()); + fprintf(fp,"\t\t\tradius_offset\t%g\n", getRadiusOffset()); + fprintf(fp,"\t\t\ttaper_x\t%g\n", getTaperX()); + fprintf(fp,"\t\t\ttaper_y\t%g\n", getTaperY()); + fprintf(fp,"\t\t\trevolutions\t%g\n", getRevolutions()); + fprintf(fp,"\t\t\tskew\t%g\n", getSkew()); + + fprintf(fp, "\t\t}\n"); + return true; } bool LLPathParams::importLegacyStream(std::istream& input_stream) { - const S32 BUFSIZE = 16384; - char buffer[BUFSIZE]; /* Flawfinder: ignore */ - // *NOTE: changing the size or type of these buffers will require - // changing the sscanf below. - char keyword[256]; /* Flawfinder: ignore */ - char valuestr[256]; /* Flawfinder: ignore */ - keyword[0] = 0; - valuestr[0] = 0; - - F32 tempF32; - F32 x, y; - U32 tempU32; - - while (input_stream.good()) - { - input_stream.getline(buffer, BUFSIZE); - sscanf( /* Flawfinder: ignore */ - buffer, - " %255s %255s", - keyword, valuestr); - if (!strcmp("{", keyword)) - { - continue; - } - if (!strcmp("}",keyword)) - { - break; - } - else if (!strcmp("curve", keyword)) - { - sscanf(valuestr,"%d",&tempU32); - setCurveType((U8) tempU32); - } - else if (!strcmp("begin",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setBegin(tempF32); - } - else if (!strcmp("end",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setEnd(tempF32); - } - else if (!strcmp("scale",keyword)) - { - // Legacy for one dimensional scale per path - sscanf(valuestr,"%g",&tempF32); - setScale(tempF32, tempF32); - } - else if (!strcmp("scale_x", keyword)) - { - sscanf(valuestr, "%g", &x); - setScaleX(x); - } - else if (!strcmp("scale_y", keyword)) - { - sscanf(valuestr, "%g", &y); - setScaleY(y); - } - else if (!strcmp("shear_x", keyword)) - { - sscanf(valuestr, "%g", &x); - setShearX(x); - } - else if (!strcmp("shear_y", keyword)) - { - sscanf(valuestr, "%g", &y); - setShearY(y); - } - else if (!strcmp("twist",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setTwist(tempF32); - } - else if (!strcmp("twist_begin", keyword)) - { - sscanf(valuestr, "%g", &y); - setTwistBegin(y); - } - else if (!strcmp("radius_offset", keyword)) - { - sscanf(valuestr, "%g", &y); - setRadiusOffset(y); - } - else if (!strcmp("taper_x", keyword)) - { - sscanf(valuestr, "%g", &y); - setTaperX(y); - } - else if (!strcmp("taper_y", keyword)) - { - sscanf(valuestr, "%g", &y); - setTaperY(y); - } - else if (!strcmp("revolutions", keyword)) - { - sscanf(valuestr, "%g", &y); - setRevolutions(y); - } - else if (!strcmp("skew", keyword)) - { - sscanf(valuestr, "%g", &y); - setSkew(y); - } - else - { - LL_WARNS() << "unknown keyword " << " in path import" << LL_ENDL; - } - } - return true; + const S32 BUFSIZE = 16384; + char buffer[BUFSIZE]; /* Flawfinder: ignore */ + // *NOTE: changing the size or type of these buffers will require + // changing the sscanf below. + char keyword[256]; /* Flawfinder: ignore */ + char valuestr[256]; /* Flawfinder: ignore */ + keyword[0] = 0; + valuestr[0] = 0; + + F32 tempF32; + F32 x, y; + U32 tempU32; + + while (input_stream.good()) + { + input_stream.getline(buffer, BUFSIZE); + sscanf( /* Flawfinder: ignore */ + buffer, + " %255s %255s", + keyword, valuestr); + if (!strcmp("{", keyword)) + { + continue; + } + if (!strcmp("}",keyword)) + { + break; + } + else if (!strcmp("curve", keyword)) + { + sscanf(valuestr,"%d",&tempU32); + setCurveType((U8) tempU32); + } + else if (!strcmp("begin",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setBegin(tempF32); + } + else if (!strcmp("end",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setEnd(tempF32); + } + else if (!strcmp("scale",keyword)) + { + // Legacy for one dimensional scale per path + sscanf(valuestr,"%g",&tempF32); + setScale(tempF32, tempF32); + } + else if (!strcmp("scale_x", keyword)) + { + sscanf(valuestr, "%g", &x); + setScaleX(x); + } + else if (!strcmp("scale_y", keyword)) + { + sscanf(valuestr, "%g", &y); + setScaleY(y); + } + else if (!strcmp("shear_x", keyword)) + { + sscanf(valuestr, "%g", &x); + setShearX(x); + } + else if (!strcmp("shear_y", keyword)) + { + sscanf(valuestr, "%g", &y); + setShearY(y); + } + else if (!strcmp("twist",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setTwist(tempF32); + } + else if (!strcmp("twist_begin", keyword)) + { + sscanf(valuestr, "%g", &y); + setTwistBegin(y); + } + else if (!strcmp("radius_offset", keyword)) + { + sscanf(valuestr, "%g", &y); + setRadiusOffset(y); + } + else if (!strcmp("taper_x", keyword)) + { + sscanf(valuestr, "%g", &y); + setTaperX(y); + } + else if (!strcmp("taper_y", keyword)) + { + sscanf(valuestr, "%g", &y); + setTaperY(y); + } + else if (!strcmp("revolutions", keyword)) + { + sscanf(valuestr, "%g", &y); + setRevolutions(y); + } + else if (!strcmp("skew", keyword)) + { + sscanf(valuestr, "%g", &y); + setSkew(y); + } + else + { + LL_WARNS() << "unknown keyword " << " in path import" << LL_ENDL; + } + } + return true; } bool LLPathParams::exportLegacyStream(std::ostream& output_stream) const { - output_stream << "\t\tpath 0\n"; - output_stream << "\t\t{\n"; - output_stream << "\t\t\tcurve\t" << (S32) getCurveType() << "\n"; - output_stream << "\t\t\tbegin\t" << getBegin() << "\n"; - output_stream << "\t\t\tend\t" << getEnd() << "\n"; - output_stream << "\t\t\tscale_x\t" << getScaleX() << "\n"; - output_stream << "\t\t\tscale_y\t" << getScaleY() << "\n"; - output_stream << "\t\t\tshear_x\t" << getShearX() << "\n"; - output_stream << "\t\t\tshear_y\t" << getShearY() << "\n"; - output_stream <<"\t\t\ttwist\t" << getTwist() << "\n"; - - output_stream <<"\t\t\ttwist_begin\t" << getTwistBegin() << "\n"; - output_stream <<"\t\t\tradius_offset\t" << getRadiusOffset() << "\n"; - output_stream <<"\t\t\ttaper_x\t" << getTaperX() << "\n"; - output_stream <<"\t\t\ttaper_y\t" << getTaperY() << "\n"; - output_stream <<"\t\t\trevolutions\t" << getRevolutions() << "\n"; - output_stream <<"\t\t\tskew\t" << getSkew() << "\n"; - - output_stream << "\t\t}\n"; - return true; + output_stream << "\t\tpath 0\n"; + output_stream << "\t\t{\n"; + output_stream << "\t\t\tcurve\t" << (S32) getCurveType() << "\n"; + output_stream << "\t\t\tbegin\t" << getBegin() << "\n"; + output_stream << "\t\t\tend\t" << getEnd() << "\n"; + output_stream << "\t\t\tscale_x\t" << getScaleX() << "\n"; + output_stream << "\t\t\tscale_y\t" << getScaleY() << "\n"; + output_stream << "\t\t\tshear_x\t" << getShearX() << "\n"; + output_stream << "\t\t\tshear_y\t" << getShearY() << "\n"; + output_stream <<"\t\t\ttwist\t" << getTwist() << "\n"; + + output_stream <<"\t\t\ttwist_begin\t" << getTwistBegin() << "\n"; + output_stream <<"\t\t\tradius_offset\t" << getRadiusOffset() << "\n"; + output_stream <<"\t\t\ttaper_x\t" << getTaperX() << "\n"; + output_stream <<"\t\t\ttaper_y\t" << getTaperY() << "\n"; + output_stream <<"\t\t\trevolutions\t" << getRevolutions() << "\n"; + output_stream <<"\t\t\tskew\t" << getSkew() << "\n"; + + output_stream << "\t\t}\n"; + return true; } LLSD LLPathParams::asLLSD() const { - LLSD sd = LLSD(); - sd["curve"] = getCurveType(); - sd["begin"] = getBegin(); - sd["end"] = getEnd(); - sd["scale_x"] = getScaleX(); - sd["scale_y"] = getScaleY(); - sd["shear_x"] = getShearX(); - sd["shear_y"] = getShearY(); - sd["twist"] = getTwist(); - sd["twist_begin"] = getTwistBegin(); - sd["radius_offset"] = getRadiusOffset(); - sd["taper_x"] = getTaperX(); - sd["taper_y"] = getTaperY(); - sd["revolutions"] = getRevolutions(); - sd["skew"] = getSkew(); - - return sd; + LLSD sd = LLSD(); + sd["curve"] = getCurveType(); + sd["begin"] = getBegin(); + sd["end"] = getEnd(); + sd["scale_x"] = getScaleX(); + sd["scale_y"] = getScaleY(); + sd["shear_x"] = getShearX(); + sd["shear_y"] = getShearY(); + sd["twist"] = getTwist(); + sd["twist_begin"] = getTwistBegin(); + sd["radius_offset"] = getRadiusOffset(); + sd["taper_x"] = getTaperX(); + sd["taper_y"] = getTaperY(); + sd["revolutions"] = getRevolutions(); + sd["skew"] = getSkew(); + + return sd; } bool LLPathParams::fromLLSD(LLSD& sd) { - setCurveType(sd["curve"].asInteger()); - setBegin((F32)sd["begin"].asReal()); - setEnd((F32)sd["end"].asReal()); - setScaleX((F32)sd["scale_x"].asReal()); - setScaleY((F32)sd["scale_y"].asReal()); - setShearX((F32)sd["shear_x"].asReal()); - setShearY((F32)sd["shear_y"].asReal()); - setTwist((F32)sd["twist"].asReal()); - setTwistBegin((F32)sd["twist_begin"].asReal()); - setRadiusOffset((F32)sd["radius_offset"].asReal()); - setTaperX((F32)sd["taper_x"].asReal()); - setTaperY((F32)sd["taper_y"].asReal()); - setRevolutions((F32)sd["revolutions"].asReal()); - setSkew((F32)sd["skew"].asReal()); - return true; + setCurveType(sd["curve"].asInteger()); + setBegin((F32)sd["begin"].asReal()); + setEnd((F32)sd["end"].asReal()); + setScaleX((F32)sd["scale_x"].asReal()); + setScaleY((F32)sd["scale_y"].asReal()); + setShearX((F32)sd["shear_x"].asReal()); + setShearY((F32)sd["shear_y"].asReal()); + setTwist((F32)sd["twist"].asReal()); + setTwistBegin((F32)sd["twist_begin"].asReal()); + setRadiusOffset((F32)sd["radius_offset"].asReal()); + setTaperX((F32)sd["taper_x"].asReal()); + setTaperY((F32)sd["taper_y"].asReal()); + setRevolutions((F32)sd["revolutions"].asReal()); + setSkew((F32)sd["skew"].asReal()); + return true; } void LLPathParams::copyParams(const LLPathParams ¶ms) { - setCurveType(params.getCurveType()); - setBegin(params.getBegin()); - setEnd(params.getEnd()); - setScale(params.getScaleX(), params.getScaleY() ); - setShear(params.getShearX(), params.getShearY() ); - setTwist(params.getTwist()); - setTwistBegin(params.getTwistBegin()); - setRadiusOffset(params.getRadiusOffset()); - setTaper( params.getTaperX(), params.getTaperY() ); - setRevolutions(params.getRevolutions()); - setSkew(params.getSkew()); + setCurveType(params.getCurveType()); + setBegin(params.getBegin()); + setEnd(params.getEnd()); + setScale(params.getScaleX(), params.getScaleY() ); + setShear(params.getShearX(), params.getShearY() ); + setTwist(params.getTwist()); + setTwistBegin(params.getTwistBegin()); + setRadiusOffset(params.getRadiusOffset()); + setTaper( params.getTaperX(), params.getTaperY() ); + setRevolutions(params.getRevolutions()); + setSkew(params.getSkew()); } LLProfile::~LLProfile() @@ -1954,53 +1954,53 @@ LLProfile::~LLProfile() S32 LLVolume::sNumMeshPoints = 0; LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const bool generate_single_face, const bool is_unique) - : mParams(params) -{ - mUnique = is_unique; - mFaceMask = 0x0; - mDetail = detail; - mSculptLevel = -2; - mSurfaceArea = 1.f; //only calculated for sculpts, defaults to 1 for all other prims - mIsMeshAssetLoaded = false; + : mParams(params) +{ + mUnique = is_unique; + mFaceMask = 0x0; + mDetail = detail; + mSculptLevel = -2; + mSurfaceArea = 1.f; //only calculated for sculpts, defaults to 1 for all other prims + mIsMeshAssetLoaded = false; mIsMeshAssetUnavaliable = false; - mLODScaleBias.setVec(1,1,1); - mHullPoints = nullptr; - mHullIndices = nullptr; - mNumHullPoints = 0; - mNumHullIndices = 0; - - // set defaults - if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE) - { - mPathp = new LLDynamicPath(); - } - else - { - mPathp = new LLPath(); - } - mProfilep = new LLProfile(); - - mGenerateSingleFace = generate_single_face; - - generate(); - - if ((mParams.getSculptID().isNull() && mParams.getSculptType() == LL_SCULPT_TYPE_NONE) || mParams.getSculptType() == LL_SCULPT_TYPE_MESH) - { - createVolumeFaces(); - } + mLODScaleBias.setVec(1,1,1); + mHullPoints = nullptr; + mHullIndices = nullptr; + mNumHullPoints = 0; + mNumHullIndices = 0; + + // set defaults + if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE) + { + mPathp = new LLDynamicPath(); + } + else + { + mPathp = new LLPath(); + } + mProfilep = new LLProfile(); + + mGenerateSingleFace = generate_single_face; + + generate(); + + if ((mParams.getSculptID().isNull() && mParams.getSculptType() == LL_SCULPT_TYPE_NONE) || mParams.getSculptType() == LL_SCULPT_TYPE_MESH) + { + createVolumeFaces(); + } } void LLVolume::resizePath(S32 length) { - mPathp->resizePath(length); - mVolumeFaces.clear(); - setDirty(); + mPathp->resizePath(length); + mVolumeFaces.clear(); + setDirty(); } void LLVolume::regen() { - generate(); - createVolumeFaces(); + generate(); + createVolumeFaces(); } void LLVolume::genTangents(S32 face) @@ -2012,103 +2012,103 @@ void LLVolume::genTangents(S32 face) LLVolume::~LLVolume() { - sNumMeshPoints -= mMesh.size(); - delete mPathp; + sNumMeshPoints -= mMesh.size(); + delete mPathp; - delete mProfilep; + delete mProfilep; - mPathp = NULL; - mProfilep = NULL; - mVolumeFaces.clear(); + mPathp = NULL; + mProfilep = NULL; + mVolumeFaces.clear(); - ll_aligned_free_16(mHullPoints); - mHullPoints = NULL; - ll_aligned_free_16(mHullIndices); - mHullIndices = NULL; + ll_aligned_free_16(mHullPoints); + mHullPoints = NULL; + ll_aligned_free_16(mHullIndices); + mHullIndices = NULL; } bool LLVolume::generate() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME - - LL_CHECK_MEMORY - llassert_always(mProfilep); - - //Added 10.03.05 Dave Parks - // Split is a parameter to LLProfile::generate that tesselates edges on the profile - // to prevent lighting and texture interpolation errors on triangles that are - // stretched due to twisting or scaling on the path. - S32 split = (S32) ((mDetail)*0.66f); - - if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_LINE && - (mParams.getPathParams().getScale().mV[0] != 1.0f || - mParams.getPathParams().getScale().mV[1] != 1.0f) && - (mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_SQUARE || - mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_ISOTRI || - mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_EQUALTRI || - mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_RIGHTTRI)) - { - split = 0; - } - - mLODScaleBias.setVec(0.5f, 0.5f, 0.5f); - - F32 profile_detail = mDetail; - F32 path_detail = mDetail; - - if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH) - { - U8 path_type = mParams.getPathParams().getCurveType(); - U8 profile_type = mParams.getProfileParams().getCurveType(); - if (path_type == LL_PCODE_PATH_LINE && profile_type == LL_PCODE_PROFILE_CIRCLE) - { - //cylinders don't care about Z-Axis - mLODScaleBias.setVec(0.6f, 0.6f, 0.0f); - } - else if (path_type == LL_PCODE_PATH_CIRCLE) - { - mLODScaleBias.setVec(0.6f, 0.6f, 0.6f); - } - } - - bool regenPath = mPathp->generate(mParams.getPathParams(), path_detail, split); - bool regenProf = mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(),profile_detail, split); - - if (regenPath || regenProf ) - { - S32 sizeS = mPathp->mPath.size(); - S32 sizeT = mProfilep->mProfile.size(); - - sNumMeshPoints -= mMesh.size(); - mMesh.resize(sizeT * sizeS); - sNumMeshPoints += mMesh.size(); - - //generate vertex positions - - // Run along the path. - LLVector4a* dst = mMesh.mArray; - - for (S32 s = 0; s < sizeS; ++s) - { - F32* scale = mPathp->mPath[s].mScale.getF32ptr(); - - F32 sc [] = - { scale[0], 0, 0, 0, - 0, scale[1], 0, 0, - 0, 0, scale[2], 0, - 0, 0, 0, 1 }; - - LLMatrix4 rot((F32*) mPathp->mPath[s].mRot.mMatrix); - LLMatrix4 scale_mat(sc); - - scale_mat *= rot; - - LLMatrix4a rot_mat; - rot_mat.loadu(scale_mat); - - LLVector4a* profile = mProfilep->mProfile.mArray; - LLVector4a* end_profile = profile+sizeT; - LLVector4a offset = mPathp->mPath[s].mPos; + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME + + LL_CHECK_MEMORY + llassert_always(mProfilep); + + //Added 10.03.05 Dave Parks + // Split is a parameter to LLProfile::generate that tesselates edges on the profile + // to prevent lighting and texture interpolation errors on triangles that are + // stretched due to twisting or scaling on the path. + S32 split = (S32) ((mDetail)*0.66f); + + if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_LINE && + (mParams.getPathParams().getScale().mV[0] != 1.0f || + mParams.getPathParams().getScale().mV[1] != 1.0f) && + (mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_SQUARE || + mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_ISOTRI || + mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_EQUALTRI || + mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_RIGHTTRI)) + { + split = 0; + } + + mLODScaleBias.setVec(0.5f, 0.5f, 0.5f); + + F32 profile_detail = mDetail; + F32 path_detail = mDetail; + + if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH) + { + U8 path_type = mParams.getPathParams().getCurveType(); + U8 profile_type = mParams.getProfileParams().getCurveType(); + if (path_type == LL_PCODE_PATH_LINE && profile_type == LL_PCODE_PROFILE_CIRCLE) + { + //cylinders don't care about Z-Axis + mLODScaleBias.setVec(0.6f, 0.6f, 0.0f); + } + else if (path_type == LL_PCODE_PATH_CIRCLE) + { + mLODScaleBias.setVec(0.6f, 0.6f, 0.6f); + } + } + + bool regenPath = mPathp->generate(mParams.getPathParams(), path_detail, split); + bool regenProf = mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(),profile_detail, split); + + if (regenPath || regenProf ) + { + S32 sizeS = mPathp->mPath.size(); + S32 sizeT = mProfilep->mProfile.size(); + + sNumMeshPoints -= mMesh.size(); + mMesh.resize(sizeT * sizeS); + sNumMeshPoints += mMesh.size(); + + //generate vertex positions + + // Run along the path. + LLVector4a* dst = mMesh.mArray; + + for (S32 s = 0; s < sizeS; ++s) + { + F32* scale = mPathp->mPath[s].mScale.getF32ptr(); + + F32 sc [] = + { scale[0], 0, 0, 0, + 0, scale[1], 0, 0, + 0, 0, scale[2], 0, + 0, 0, 0, 1 }; + + LLMatrix4 rot((F32*) mPathp->mPath[s].mRot.mMatrix); + LLMatrix4 scale_mat(sc); + + scale_mat *= rot; + + LLMatrix4a rot_mat; + rot_mat.loadu(scale_mat); + + LLVector4a* profile = mProfilep->mProfile.mArray; + LLVector4a* end_profile = profile+sizeT; + LLVector4a offset = mPathp->mPath[s].mPos; // hack to work around MAINT-5660 for debug until we can suss out // what is wrong with the path generated that inserts NaNs... @@ -2117,241 +2117,241 @@ bool LLVolume::generate() offset.clear(); } - LLVector4a tmp; + LLVector4a tmp; - // Run along the profile. - while (profile < end_profile) - { - rot_mat.rotate(*profile++, tmp); - dst->setAdd(tmp,offset); - ++dst; - } - } + // Run along the profile. + while (profile < end_profile) + { + rot_mat.rotate(*profile++, tmp); + dst->setAdd(tmp,offset); + ++dst; + } + } - for (std::vector<LLProfile::Face>::iterator iter = mProfilep->mFaces.begin(); - iter != mProfilep->mFaces.end(); ++iter) - { - LLFaceID id = iter->mFaceID; - mFaceMask |= id; - } - LL_CHECK_MEMORY - return true; - } + for (std::vector<LLProfile::Face>::iterator iter = mProfilep->mFaces.begin(); + iter != mProfilep->mFaces.end(); ++iter) + { + LLFaceID id = iter->mFaceID; + mFaceMask |= id; + } + LL_CHECK_MEMORY + return true; + } - LL_CHECK_MEMORY - return false; + LL_CHECK_MEMORY + return false; } void LLVolumeFace::VertexData::init() { - if (!mData) - { - mData = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*2); - } + if (!mData) + { + mData = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*2); + } } LLVolumeFace::VertexData::VertexData() { - mData = NULL; - init(); + mData = NULL; + init(); } - + LLVolumeFace::VertexData::VertexData(const VertexData& rhs) { - mData = NULL; - *this = rhs; + mData = NULL; + *this = rhs; } const LLVolumeFace::VertexData& LLVolumeFace::VertexData::operator=(const LLVolumeFace::VertexData& rhs) { - if (this != &rhs) - { - init(); - LLVector4a::memcpyNonAliased16((F32*) mData, (F32*) rhs.mData, 2*sizeof(LLVector4a)); - mTexCoord = rhs.mTexCoord; - } - return *this; + if (this != &rhs) + { + init(); + LLVector4a::memcpyNonAliased16((F32*) mData, (F32*) rhs.mData, 2*sizeof(LLVector4a)); + mTexCoord = rhs.mTexCoord; + } + return *this; } LLVolumeFace::VertexData::~VertexData() { - ll_aligned_free_16(mData); - mData = NULL; + ll_aligned_free_16(mData); + mData = NULL; } LLVector4a& LLVolumeFace::VertexData::getPosition() { - return mData[POSITION]; + return mData[POSITION]; } LLVector4a& LLVolumeFace::VertexData::getNormal() { - return mData[NORMAL]; + return mData[NORMAL]; } const LLVector4a& LLVolumeFace::VertexData::getPosition() const { - return mData[POSITION]; + return mData[POSITION]; } const LLVector4a& LLVolumeFace::VertexData::getNormal() const { - return mData[NORMAL]; + return mData[NORMAL]; } void LLVolumeFace::VertexData::setPosition(const LLVector4a& pos) { - mData[POSITION] = pos; + mData[POSITION] = pos; } void LLVolumeFace::VertexData::setNormal(const LLVector4a& norm) { - mData[NORMAL] = norm; + mData[NORMAL] = norm; } bool LLVolumeFace::VertexData::operator<(const LLVolumeFace::VertexData& rhs)const { - const F32* lp = this->getPosition().getF32ptr(); - const F32* rp = rhs.getPosition().getF32ptr(); + const F32* lp = this->getPosition().getF32ptr(); + const F32* rp = rhs.getPosition().getF32ptr(); - if (lp[0] != rp[0]) - { - return lp[0] < rp[0]; - } + if (lp[0] != rp[0]) + { + return lp[0] < rp[0]; + } - if (rp[1] != lp[1]) - { - return lp[1] < rp[1]; - } + if (rp[1] != lp[1]) + { + return lp[1] < rp[1]; + } - if (rp[2] != lp[2]) - { - return lp[2] < rp[2]; - } + if (rp[2] != lp[2]) + { + return lp[2] < rp[2]; + } - lp = getNormal().getF32ptr(); - rp = rhs.getNormal().getF32ptr(); + lp = getNormal().getF32ptr(); + rp = rhs.getNormal().getF32ptr(); - if (lp[0] != rp[0]) - { - return lp[0] < rp[0]; - } + if (lp[0] != rp[0]) + { + return lp[0] < rp[0]; + } - if (rp[1] != lp[1]) - { - return lp[1] < rp[1]; - } + if (rp[1] != lp[1]) + { + return lp[1] < rp[1]; + } - if (rp[2] != lp[2]) - { - return lp[2] < rp[2]; - } + if (rp[2] != lp[2]) + { + return lp[2] < rp[2]; + } - if (mTexCoord.mV[0] != rhs.mTexCoord.mV[0]) - { - return mTexCoord.mV[0] < rhs.mTexCoord.mV[0]; - } + if (mTexCoord.mV[0] != rhs.mTexCoord.mV[0]) + { + return mTexCoord.mV[0] < rhs.mTexCoord.mV[0]; + } - return mTexCoord.mV[1] < rhs.mTexCoord.mV[1]; + return mTexCoord.mV[1] < rhs.mTexCoord.mV[1]; } bool LLVolumeFace::VertexData::operator==(const LLVolumeFace::VertexData& rhs)const { - return mData[POSITION].equals3(rhs.getPosition()) && - mData[NORMAL].equals3(rhs.getNormal()) && - mTexCoord == rhs.mTexCoord; + return mData[POSITION].equals3(rhs.getPosition()) && + mData[NORMAL].equals3(rhs.getNormal()) && + mTexCoord == rhs.mTexCoord; } bool LLVolumeFace::VertexData::compareNormal(const LLVolumeFace::VertexData& rhs, F32 angle_cutoff) const { - bool retval = false; + bool retval = false; - const F32 epsilon = 0.00001f; + const F32 epsilon = 0.00001f; - if (rhs.mData[POSITION].equals3(mData[POSITION], epsilon) && - fabs(rhs.mTexCoord[0]-mTexCoord[0]) < epsilon && - fabs(rhs.mTexCoord[1]-mTexCoord[1]) < epsilon) - { - if (angle_cutoff > 1.f) - { - retval = (mData[NORMAL].equals3(rhs.mData[NORMAL], epsilon)); - } - else - { - F32 cur_angle = rhs.mData[NORMAL].dot3(mData[NORMAL]).getF32(); - retval = cur_angle > angle_cutoff; - } - } + if (rhs.mData[POSITION].equals3(mData[POSITION], epsilon) && + fabs(rhs.mTexCoord[0]-mTexCoord[0]) < epsilon && + fabs(rhs.mTexCoord[1]-mTexCoord[1]) < epsilon) + { + if (angle_cutoff > 1.f) + { + retval = (mData[NORMAL].equals3(rhs.mData[NORMAL], epsilon)); + } + else + { + F32 cur_angle = rhs.mData[NORMAL].dot3(mData[NORMAL]).getF32(); + retval = cur_angle > angle_cutoff; + } + } - return retval; + return retval; } bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME - //input stream is now pointing at a zlib compressed block of LLSD - //decompress block - LLSD mdl; - U32 uzip_result = LLUZipHelper::unzip_llsd(mdl, is, size); - if (uzip_result != LLUZipHelper::ZR_OK) - { - LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD with code " << uzip_result << " , will probably fetch from sim again." << LL_ENDL; - return false; - } - return unpackVolumeFacesInternal(mdl); + //input stream is now pointing at a zlib compressed block of LLSD + //decompress block + LLSD mdl; + U32 uzip_result = LLUZipHelper::unzip_llsd(mdl, is, size); + if (uzip_result != LLUZipHelper::ZR_OK) + { + LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD with code " << uzip_result << " , will probably fetch from sim again." << LL_ENDL; + return false; + } + return unpackVolumeFacesInternal(mdl); } bool LLVolume::unpackVolumeFaces(U8* in_data, S32 size) { - //input data is now pointing at a zlib compressed block of LLSD - //decompress block - LLSD mdl; - U32 uzip_result = LLUZipHelper::unzip_llsd(mdl, in_data, size); - if (uzip_result != LLUZipHelper::ZR_OK) - { - LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD with code " << uzip_result << " , will probably fetch from sim again." << LL_ENDL; - return false; - } - return unpackVolumeFacesInternal(mdl); + //input data is now pointing at a zlib compressed block of LLSD + //decompress block + LLSD mdl; + U32 uzip_result = LLUZipHelper::unzip_llsd(mdl, in_data, size); + if (uzip_result != LLUZipHelper::ZR_OK) + { + LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD with code " << uzip_result << " , will probably fetch from sim again." << LL_ENDL; + return false; + } + return unpackVolumeFacesInternal(mdl); } bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl) { - { - U32 face_count = mdl.size(); - - if (face_count == 0) - { //no faces unpacked, treat as failed decode - LL_WARNS() << "found no faces!" << LL_ENDL; - return false; - } - - mVolumeFaces.resize(face_count); - - for (size_t i = 0; i < face_count; ++i) - { - LLVolumeFace& face = mVolumeFaces[i]; - - if (mdl[i].has("NoGeometry")) - { //face has no geometry, continue - face.resizeIndices(3); - face.resizeVertices(1); - face.mPositions->clear(); - face.mNormals->clear(); - face.mTexCoords->setZero(); - memset(face.mIndices, 0, sizeof(U16)*3); - continue; - } - - LLSD::Binary pos = mdl[i]["Position"]; - LLSD::Binary norm = mdl[i]["Normal"]; + { + U32 face_count = mdl.size(); + + if (face_count == 0) + { //no faces unpacked, treat as failed decode + LL_WARNS() << "found no faces!" << LL_ENDL; + return false; + } + + mVolumeFaces.resize(face_count); + + for (size_t i = 0; i < face_count; ++i) + { + LLVolumeFace& face = mVolumeFaces[i]; + + if (mdl[i].has("NoGeometry")) + { //face has no geometry, continue + face.resizeIndices(3); + face.resizeVertices(1); + face.mPositions->clear(); + face.mNormals->clear(); + face.mTexCoords->setZero(); + memset(face.mIndices, 0, sizeof(U16)*3); + continue; + } + + LLSD::Binary pos = mdl[i]["Position"]; + LLSD::Binary norm = mdl[i]["Normal"]; LLSD::Binary tangent = mdl[i]["Tangent"]; - LLSD::Binary tc = mdl[i]["TexCoord0"]; - LLSD::Binary idx = mdl[i]["TriangleList"]; + LLSD::Binary tc = mdl[i]["TexCoord0"]; + LLSD::Binary idx = mdl[i]["TriangleList"]; - //copy out indices + //copy out indices S32 num_indices = idx.size() / 2; const S32 indices_to_discard = num_indices % 3; if (indices_to_discard > 0) @@ -2367,22 +2367,22 @@ bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl) LL_WARNS() << "Failed to allocate " << num_indices << " indices for face index: " << i << " Total: " << face_count << LL_ENDL; continue; } - - if (idx.empty() || face.mNumIndices < 3) - { //why is there an empty index list? - LL_WARNS() << "Empty face present! Face index: " << i << " Total: " << face_count << LL_ENDL; - continue; - } - - U16* indices = (U16*) &(idx[0]); + + if (idx.empty() || face.mNumIndices < 3) + { //why is there an empty index list? + LL_WARNS() << "Empty face present! Face index: " << i << " Total: " << face_count << LL_ENDL; + continue; + } + + U16* indices = (U16*) &(idx[0]); for (U32 j = 0; j < num_indices; ++j) - { - face.mIndices[j] = indices[j]; - } + { + face.mIndices[j] = indices[j]; + } - //copy out vertices - U32 num_verts = pos.size()/(3*2); - face.resizeVertices(num_verts); + //copy out vertices + U32 num_verts = pos.size()/(3*2); + face.resizeVertices(num_verts); if (num_verts > 0 && !face.mPositions) { @@ -2391,19 +2391,19 @@ bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl) continue; } - LLVector3 minp; - LLVector3 maxp; - LLVector2 min_tc; - LLVector2 max_tc; - - minp.setValue(mdl[i]["PositionDomain"]["Min"]); - maxp.setValue(mdl[i]["PositionDomain"]["Max"]); - LLVector4a min_pos, max_pos; - min_pos.load3(minp.mV); - max_pos.load3(maxp.mV); + LLVector3 minp; + LLVector3 maxp; + LLVector2 min_tc; + LLVector2 max_tc; - min_tc.setValue(mdl[i]["TexCoord0Domain"]["Min"]); - max_tc.setValue(mdl[i]["TexCoord0Domain"]["Max"]); + minp.setValue(mdl[i]["PositionDomain"]["Min"]); + maxp.setValue(mdl[i]["PositionDomain"]["Max"]); + LLVector4a min_pos, max_pos; + min_pos.load3(minp.mV); + max_pos.load3(maxp.mV); + + min_tc.setValue(mdl[i]["TexCoord0Domain"]["Min"]); + max_tc.setValue(mdl[i]["TexCoord0Domain"]["Max"]); //unpack normalized scale/translation if (mdl[i].has("NormalizedScale")) @@ -2414,56 +2414,56 @@ bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl) { face.mNormalizedScale.set(1, 1, 1); } - - LLVector4a pos_range; - pos_range.setSub(max_pos, min_pos); - LLVector2 tc_range2 = max_tc - min_tc; - - LLVector4a tc_range; - tc_range.set(tc_range2[0], tc_range2[1], tc_range2[0], tc_range2[1]); - LLVector4a min_tc4(min_tc[0], min_tc[1], min_tc[0], min_tc[1]); - - LLVector4a* pos_out = face.mPositions; - LLVector4a* norm_out = face.mNormals; - LLVector4a* tc_out = (LLVector4a*) face.mTexCoords; - - { - U16* v = (U16*) &(pos[0]); - for (U32 j = 0; j < num_verts; ++j) - { - pos_out->set((F32) v[0], (F32) v[1], (F32) v[2]); - pos_out->div(65535.f); - pos_out->mul(pos_range); - pos_out->add(min_pos); - pos_out++; - v += 3; - } - - } - - { - if (!norm.empty()) - { - U16* n = (U16*) &(norm[0]); - for (U32 j = 0; j < num_verts; ++j) - { - norm_out->set((F32) n[0], (F32) n[1], (F32) n[2]); - norm_out->div(65535.f); - norm_out->mul(2.f); - norm_out->sub(1.f); - norm_out++; - n += 3; - } - } - else - { - for (U32 j = 0; j < num_verts; ++j) - { - norm_out->clear(); - norm_out++; // or just norm_out[j].clear(); - } - } - } + + LLVector4a pos_range; + pos_range.setSub(max_pos, min_pos); + LLVector2 tc_range2 = max_tc - min_tc; + + LLVector4a tc_range; + tc_range.set(tc_range2[0], tc_range2[1], tc_range2[0], tc_range2[1]); + LLVector4a min_tc4(min_tc[0], min_tc[1], min_tc[0], min_tc[1]); + + LLVector4a* pos_out = face.mPositions; + LLVector4a* norm_out = face.mNormals; + LLVector4a* tc_out = (LLVector4a*) face.mTexCoords; + + { + U16* v = (U16*) &(pos[0]); + for (U32 j = 0; j < num_verts; ++j) + { + pos_out->set((F32) v[0], (F32) v[1], (F32) v[2]); + pos_out->div(65535.f); + pos_out->mul(pos_range); + pos_out->add(min_pos); + pos_out++; + v += 3; + } + + } + + { + if (!norm.empty()) + { + U16* n = (U16*) &(norm[0]); + for (U32 j = 0; j < num_verts; ++j) + { + norm_out->set((F32) n[0], (F32) n[1], (F32) n[2]); + norm_out->div(65535.f); + norm_out->mul(2.f); + norm_out->sub(1.f); + norm_out++; + n += 3; + } + } + else + { + for (U32 j = 0; j < num_verts; ++j) + { + norm_out->clear(); + norm_out++; // or just norm_out[j].clear(); + } + } + } #if 0 // keep this code for now in case we decide to add support for on-the-wire tangents { @@ -2472,9 +2472,9 @@ bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl) face.allocateTangents(face.mNumVertices); U16* t = (U16*)&(tangent[0]); - // NOTE: tangents coming from the asset may not be mikkt space, but they should always be used by the GLTF shaders to + // NOTE: tangents coming from the asset may not be mikkt space, but they should always be used by the GLTF shaders to // maintain compliance with the GLTF spec - LLVector4a* t_out = face.mTangents; + LLVector4a* t_out = face.mTangents; for (U32 j = 0; j < num_verts; ++j) { @@ -2493,43 +2493,43 @@ bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl) } #endif - { - if (!tc.empty()) - { - U16* t = (U16*) &(tc[0]); - for (U32 j = 0; j < num_verts; j+=2) - { - if (j < num_verts-1) - { - tc_out->set((F32) t[0], (F32) t[1], (F32) t[2], (F32) t[3]); - } - else - { - tc_out->set((F32) t[0], (F32) t[1], 0.f, 0.f); - } - - t += 4; - - tc_out->div(65535.f); - tc_out->mul(tc_range); - tc_out->add(min_tc4); - - tc_out++; - } - } - else - { - for (U32 j = 0; j < num_verts; j += 2) - { - tc_out->clear(); - tc_out++; - } - } - } - - if (mdl[i].has("Weights")) - { - face.allocateWeights(num_verts); + { + if (!tc.empty()) + { + U16* t = (U16*) &(tc[0]); + for (U32 j = 0; j < num_verts; j+=2) + { + if (j < num_verts-1) + { + tc_out->set((F32) t[0], (F32) t[1], (F32) t[2], (F32) t[3]); + } + else + { + tc_out->set((F32) t[0], (F32) t[1], 0.f, 0.f); + } + + t += 4; + + tc_out->div(65535.f); + tc_out->mul(tc_range); + tc_out->add(min_tc4); + + tc_out++; + } + } + else + { + for (U32 j = 0; j < num_verts; j += 2) + { + tc_out->clear(); + tc_out++; + } + } + } + + if (mdl[i].has("Weights")) + { + face.allocateWeights(num_verts); if (!face.mWeights && num_verts) { LL_WARNS() << "Failed to allocate " << num_verts << " weights for face index: " << i << " Total: " << face_count << LL_ENDL; @@ -2538,40 +2538,40 @@ bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl) continue; } - LLSD::Binary weights = mdl[i]["Weights"]; + LLSD::Binary weights = mdl[i]["Weights"]; - U32 idx = 0; + U32 idx = 0; - U32 cur_vertex = 0; - while (idx < weights.size() && cur_vertex < num_verts) - { - const U8 END_INFLUENCES = 0xFF; - U8 joint = weights[idx++]; + U32 cur_vertex = 0; + while (idx < weights.size() && cur_vertex < num_verts) + { + const U8 END_INFLUENCES = 0xFF; + U8 joint = weights[idx++]; - U32 cur_influence = 0; - LLVector4 wght(0,0,0,0); + U32 cur_influence = 0; + LLVector4 wght(0,0,0,0); U32 joints[4] = {0,0,0,0}; - LLVector4 joints_with_weights(0,0,0,0); - - while (joint != END_INFLUENCES && idx < weights.size()) - { - U16 influence = weights[idx++]; - influence |= ((U16) weights[idx++] << 8); - - F32 w = llclamp((F32) influence / 65535.f, 0.001f, 0.999f); - wght.mV[cur_influence] = w; - joints[cur_influence] = joint; - cur_influence++; - - if (cur_influence >= 4) - { - joint = END_INFLUENCES; - } - else - { - joint = weights[idx++]; - } - } + LLVector4 joints_with_weights(0,0,0,0); + + while (joint != END_INFLUENCES && idx < weights.size()) + { + U16 influence = weights[idx++]; + influence |= ((U16) weights[idx++] << 8); + + F32 w = llclamp((F32) influence / 65535.f, 0.001f, 0.999f); + wght.mV[cur_influence] = w; + joints[cur_influence] = joint; + cur_influence++; + + if (cur_influence >= 4) + { + joint = END_INFLUENCES; + } + else + { + joint = weights[idx++]; + } + } F32 wsum = wght.mV[VX] + wght.mV[VY] + wght.mV[VZ] + wght.mV[VW]; if (wsum <= 0.f) { @@ -2585,139 +2585,139 @@ bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl) // A failure here would indicate a floating point precision error in the math. llassert((k >= cur_influence) || (f_combined - S32(f_combined) > 0.0f)); } - face.mWeights[cur_vertex].loadua(joints_with_weights.mV); - - cur_vertex++; - } - - if (cur_vertex != num_verts || idx != weights.size()) - { - LL_WARNS() << "Vertex weight count does not match vertex count!" << LL_ENDL; - } - - } - - // modifier flags? - bool do_mirror = (mParams.getSculptType() & LL_SCULPT_FLAG_MIRROR); - bool do_invert = (mParams.getSculptType() &LL_SCULPT_FLAG_INVERT); - - - // translate to actions: - bool do_reflect_x = false; - bool do_reverse_triangles = false; - bool do_invert_normals = false; - - if (do_mirror) - { - do_reflect_x = true; - do_reverse_triangles = !do_reverse_triangles; - } - - if (do_invert) - { - do_invert_normals = true; - do_reverse_triangles = !do_reverse_triangles; - } - - // now do the work - - if (do_reflect_x) - { - LLVector4a* p = (LLVector4a*) face.mPositions; - LLVector4a* n = (LLVector4a*) face.mNormals; - - for (S32 i = 0; i < face.mNumVertices; i++) - { - p[i].mul(-1.0f); - n[i].mul(-1.0f); - } - } - - if (do_invert_normals) - { - LLVector4a* n = (LLVector4a*) face.mNormals; - - for (S32 i = 0; i < face.mNumVertices; i++) - { - n[i].mul(-1.0f); - } - } - - if (do_reverse_triangles) - { - for (U32 j = 0; j < face.mNumIndices; j += 3) - { - // swap the 2nd and 3rd index - S32 swap = face.mIndices[j+1]; - face.mIndices[j+1] = face.mIndices[j+2]; - face.mIndices[j+2] = swap; - } - } - - //calculate bounding box - // VFExtents change - LLVector4a& min = face.mExtents[0]; - LLVector4a& max = face.mExtents[1]; - - if (face.mNumVertices < 3) - { //empty face, use a dummy 1cm (at 1m scale) bounding box - min.splat(-0.005f); - max.splat(0.005f); - } - else - { - min = max = face.mPositions[0]; - - for (S32 i = 1; i < face.mNumVertices; ++i) - { - min.setMin(min, face.mPositions[i]); - max.setMax(max, face.mPositions[i]); - } - - if (face.mTexCoords) - { - LLVector2& min_tc = face.mTexCoordExtents[0]; - LLVector2& max_tc = face.mTexCoordExtents[1]; - - min_tc = face.mTexCoords[0]; - max_tc = face.mTexCoords[0]; - - for (U32 j = 1; j < face.mNumVertices; ++j) - { - update_min_max(min_tc, max_tc, face.mTexCoords[j]); - } - } - else - { - face.mTexCoordExtents[0].set(0,0); - face.mTexCoordExtents[1].set(1,1); - } - } - } - } - - if (!cacheOptimize(true)) - { - // Out of memory? - LL_WARNS() << "Failed to optimize!" << LL_ENDL; - mVolumeFaces.clear(); - return false; - } - - mSculptLevel = 0; // success! - - return true; + face.mWeights[cur_vertex].loadua(joints_with_weights.mV); + + cur_vertex++; + } + + if (cur_vertex != num_verts || idx != weights.size()) + { + LL_WARNS() << "Vertex weight count does not match vertex count!" << LL_ENDL; + } + + } + + // modifier flags? + bool do_mirror = (mParams.getSculptType() & LL_SCULPT_FLAG_MIRROR); + bool do_invert = (mParams.getSculptType() &LL_SCULPT_FLAG_INVERT); + + + // translate to actions: + bool do_reflect_x = false; + bool do_reverse_triangles = false; + bool do_invert_normals = false; + + if (do_mirror) + { + do_reflect_x = true; + do_reverse_triangles = !do_reverse_triangles; + } + + if (do_invert) + { + do_invert_normals = true; + do_reverse_triangles = !do_reverse_triangles; + } + + // now do the work + + if (do_reflect_x) + { + LLVector4a* p = (LLVector4a*) face.mPositions; + LLVector4a* n = (LLVector4a*) face.mNormals; + + for (S32 i = 0; i < face.mNumVertices; i++) + { + p[i].mul(-1.0f); + n[i].mul(-1.0f); + } + } + + if (do_invert_normals) + { + LLVector4a* n = (LLVector4a*) face.mNormals; + + for (S32 i = 0; i < face.mNumVertices; i++) + { + n[i].mul(-1.0f); + } + } + + if (do_reverse_triangles) + { + for (U32 j = 0; j < face.mNumIndices; j += 3) + { + // swap the 2nd and 3rd index + S32 swap = face.mIndices[j+1]; + face.mIndices[j+1] = face.mIndices[j+2]; + face.mIndices[j+2] = swap; + } + } + + //calculate bounding box + // VFExtents change + LLVector4a& min = face.mExtents[0]; + LLVector4a& max = face.mExtents[1]; + + if (face.mNumVertices < 3) + { //empty face, use a dummy 1cm (at 1m scale) bounding box + min.splat(-0.005f); + max.splat(0.005f); + } + else + { + min = max = face.mPositions[0]; + + for (S32 i = 1; i < face.mNumVertices; ++i) + { + min.setMin(min, face.mPositions[i]); + max.setMax(max, face.mPositions[i]); + } + + if (face.mTexCoords) + { + LLVector2& min_tc = face.mTexCoordExtents[0]; + LLVector2& max_tc = face.mTexCoordExtents[1]; + + min_tc = face.mTexCoords[0]; + max_tc = face.mTexCoords[0]; + + for (U32 j = 1; j < face.mNumVertices; ++j) + { + update_min_max(min_tc, max_tc, face.mTexCoords[j]); + } + } + else + { + face.mTexCoordExtents[0].set(0,0); + face.mTexCoordExtents[1].set(1,1); + } + } + } + } + + if (!cacheOptimize(true)) + { + // Out of memory? + LL_WARNS() << "Failed to optimize!" << LL_ENDL; + mVolumeFaces.clear(); + return false; + } + + mSculptLevel = 0; // success! + + return true; } bool LLVolume::isMeshAssetLoaded() { - return mIsMeshAssetLoaded; + return mIsMeshAssetLoaded; } void LLVolume::setMeshAssetLoaded(bool loaded) { - mIsMeshAssetLoaded = loaded; + mIsMeshAssetLoaded = loaded; if (loaded) { mIsMeshAssetUnavaliable = false; @@ -2738,375 +2738,375 @@ bool LLVolume::isMeshAssetUnavaliable() return mIsMeshAssetUnavaliable; } -void LLVolume::copyFacesTo(std::vector<LLVolumeFace> &faces) const +void LLVolume::copyFacesTo(std::vector<LLVolumeFace> &faces) const { - faces = mVolumeFaces; + faces = mVolumeFaces; } void LLVolume::copyFacesFrom(const std::vector<LLVolumeFace> &faces) { - mVolumeFaces = faces; - mSculptLevel = 0; + mVolumeFaces = faces; + mSculptLevel = 0; } void LLVolume::copyVolumeFaces(const LLVolume* volume) { - mVolumeFaces = volume->mVolumeFaces; - mSculptLevel = 0; + mVolumeFaces = volume->mVolumeFaces; + mSculptLevel = 0; } bool LLVolume::cacheOptimize(bool gen_tangents) { - for (S32 i = 0; i < mVolumeFaces.size(); ++i) - { - if (!mVolumeFaces[i].cacheOptimize(gen_tangents)) - { - return false; - } - } - return true; + for (S32 i = 0; i < mVolumeFaces.size(); ++i) + { + if (!mVolumeFaces[i].cacheOptimize(gen_tangents)) + { + return false; + } + } + return true; } -S32 LLVolume::getNumFaces() const +S32 LLVolume::getNumFaces() const { - return mIsMeshAssetLoaded ? getNumVolumeFaces() : (S32)mProfilep->mFaces.size(); + return mIsMeshAssetLoaded ? getNumVolumeFaces() : (S32)mProfilep->mFaces.size(); } void LLVolume::createVolumeFaces() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME - - if (mGenerateSingleFace) - { - // do nothing - } - else - { - S32 num_faces = getNumFaces(); - bool partial_build = true; - if (num_faces != mVolumeFaces.size()) - { - partial_build = false; - mVolumeFaces.resize(num_faces); - } - // Initialize volume faces with parameter data - for (S32 i = 0; i < (S32)mVolumeFaces.size(); i++) - { - LLVolumeFace& vf = mVolumeFaces[i]; - LLProfile::Face& face = mProfilep->mFaces[i]; - vf.mBeginS = face.mIndex; - vf.mNumS = face.mCount; - if (vf.mNumS < 0) - { - LL_ERRS() << "Volume face corruption detected." << LL_ENDL; - } - - vf.mBeginT = 0; - vf.mNumT= getPath().mPath.size(); - vf.mID = i; - - // Set the type mask bits correctly - if (mParams.getProfileParams().getHollow() > 0) - { - vf.mTypeMask |= LLVolumeFace::HOLLOW_MASK; - } - if (mProfilep->isOpen()) - { - vf.mTypeMask |= LLVolumeFace::OPEN_MASK; - } - if (face.mCap) - { - vf.mTypeMask |= LLVolumeFace::CAP_MASK; - if (face.mFaceID == LL_FACE_PATH_BEGIN) - { - vf.mTypeMask |= LLVolumeFace::TOP_MASK; - } - else - { - llassert(face.mFaceID == LL_FACE_PATH_END); - vf.mTypeMask |= LLVolumeFace::BOTTOM_MASK; - } - } - else if (face.mFaceID & (LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END)) - { - vf.mTypeMask |= LLVolumeFace::FLAT_MASK | LLVolumeFace::END_MASK; - } - else - { - vf.mTypeMask |= LLVolumeFace::SIDE_MASK; - if (face.mFlat) - { - vf.mTypeMask |= LLVolumeFace::FLAT_MASK; - } - if (face.mFaceID & LL_FACE_INNER_SIDE) - { - vf.mTypeMask |= LLVolumeFace::INNER_MASK; - if (face.mFlat && vf.mNumS > 2) - { //flat inner faces have to copy vert normals - vf.mNumS = vf.mNumS*2; - if (vf.mNumS < 0) - { - LL_ERRS() << "Volume face corruption detected." << LL_ENDL; - } - } - } - else - { - vf.mTypeMask |= LLVolumeFace::OUTER_MASK; - } - } - } - - for (face_list_t::iterator iter = mVolumeFaces.begin(); - iter != mVolumeFaces.end(); ++iter) - { - (*iter).create(this, partial_build); - } - } + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME + + if (mGenerateSingleFace) + { + // do nothing + } + else + { + S32 num_faces = getNumFaces(); + bool partial_build = true; + if (num_faces != mVolumeFaces.size()) + { + partial_build = false; + mVolumeFaces.resize(num_faces); + } + // Initialize volume faces with parameter data + for (S32 i = 0; i < (S32)mVolumeFaces.size(); i++) + { + LLVolumeFace& vf = mVolumeFaces[i]; + LLProfile::Face& face = mProfilep->mFaces[i]; + vf.mBeginS = face.mIndex; + vf.mNumS = face.mCount; + if (vf.mNumS < 0) + { + LL_ERRS() << "Volume face corruption detected." << LL_ENDL; + } + + vf.mBeginT = 0; + vf.mNumT= getPath().mPath.size(); + vf.mID = i; + + // Set the type mask bits correctly + if (mParams.getProfileParams().getHollow() > 0) + { + vf.mTypeMask |= LLVolumeFace::HOLLOW_MASK; + } + if (mProfilep->isOpen()) + { + vf.mTypeMask |= LLVolumeFace::OPEN_MASK; + } + if (face.mCap) + { + vf.mTypeMask |= LLVolumeFace::CAP_MASK; + if (face.mFaceID == LL_FACE_PATH_BEGIN) + { + vf.mTypeMask |= LLVolumeFace::TOP_MASK; + } + else + { + llassert(face.mFaceID == LL_FACE_PATH_END); + vf.mTypeMask |= LLVolumeFace::BOTTOM_MASK; + } + } + else if (face.mFaceID & (LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END)) + { + vf.mTypeMask |= LLVolumeFace::FLAT_MASK | LLVolumeFace::END_MASK; + } + else + { + vf.mTypeMask |= LLVolumeFace::SIDE_MASK; + if (face.mFlat) + { + vf.mTypeMask |= LLVolumeFace::FLAT_MASK; + } + if (face.mFaceID & LL_FACE_INNER_SIDE) + { + vf.mTypeMask |= LLVolumeFace::INNER_MASK; + if (face.mFlat && vf.mNumS > 2) + { //flat inner faces have to copy vert normals + vf.mNumS = vf.mNumS*2; + if (vf.mNumS < 0) + { + LL_ERRS() << "Volume face corruption detected." << LL_ENDL; + } + } + } + else + { + vf.mTypeMask |= LLVolumeFace::OUTER_MASK; + } + } + } + + for (face_list_t::iterator iter = mVolumeFaces.begin(); + iter != mVolumeFaces.end(); ++iter) + { + (*iter).create(this, partial_build); + } + } } inline LLVector4a sculpt_rgb_to_vector(U8 r, U8 g, U8 b) { - // maps RGB values to vector values [0..255] -> [-0.5..0.5] - LLVector4a value; - LLVector4a sub(0.5f, 0.5f, 0.5f); + // maps RGB values to vector values [0..255] -> [-0.5..0.5] + LLVector4a value; + LLVector4a sub(0.5f, 0.5f, 0.5f); - value.set(r,g,b); - value.mul(1.f/255.f); - value.sub(sub); + value.set(r,g,b); + value.mul(1.f/255.f); + value.sub(sub); - return value; + return value; } inline U32 sculpt_xy_to_index(U32 x, U32 y, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components) { - U32 index = (x + y * sculpt_width) * sculpt_components; - return index; + U32 index = (x + y * sculpt_width) * sculpt_components; + return index; } inline U32 sculpt_st_to_index(S32 s, S32 t, S32 size_s, S32 size_t, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components) { - U32 x = (U32) ((F32)s/(size_s) * (F32) sculpt_width); - U32 y = (U32) ((F32)t/(size_t) * (F32) sculpt_height); + U32 x = (U32) ((F32)s/(size_s) * (F32) sculpt_width); + U32 y = (U32) ((F32)t/(size_t) * (F32) sculpt_height); - return sculpt_xy_to_index(x, y, sculpt_width, sculpt_height, sculpt_components); + return sculpt_xy_to_index(x, y, sculpt_width, sculpt_height, sculpt_components); } inline LLVector4a sculpt_index_to_vector(U32 index, const U8* sculpt_data) { - LLVector4a v = sculpt_rgb_to_vector(sculpt_data[index], sculpt_data[index+1], sculpt_data[index+2]); + LLVector4a v = sculpt_rgb_to_vector(sculpt_data[index], sculpt_data[index+1], sculpt_data[index+2]); - return v; + return v; } inline LLVector4a sculpt_st_to_vector(S32 s, S32 t, S32 size_s, S32 size_t, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data) { - U32 index = sculpt_st_to_index(s, t, size_s, size_t, sculpt_width, sculpt_height, sculpt_components); + U32 index = sculpt_st_to_index(s, t, size_s, size_t, sculpt_width, sculpt_height, sculpt_components); - return sculpt_index_to_vector(index, sculpt_data); + return sculpt_index_to_vector(index, sculpt_data); } inline LLVector4a sculpt_xy_to_vector(U32 x, U32 y, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data) { - U32 index = sculpt_xy_to_index(x, y, sculpt_width, sculpt_height, sculpt_components); + U32 index = sculpt_xy_to_index(x, y, sculpt_width, sculpt_height, sculpt_components); - return sculpt_index_to_vector(index, sculpt_data); + return sculpt_index_to_vector(index, sculpt_data); } F32 LLVolume::sculptGetSurfaceArea() { - // test to see if image has enough variation to create non-degenerate geometry - - F32 area = 0; - - S32 sizeS = mPathp->mPath.size(); - S32 sizeT = mProfilep->mProfile.size(); - - for (S32 s = 0; s < sizeS-1; s++) - { - for (S32 t = 0; t < sizeT-1; t++) - { - // get four corners of quad - LLVector4a& p1 = mMesh[(s )*sizeT + (t )]; - LLVector4a& p2 = mMesh[(s+1)*sizeT + (t )]; - LLVector4a& p3 = mMesh[(s )*sizeT + (t+1)]; - LLVector4a& p4 = mMesh[(s+1)*sizeT + (t+1)]; + // test to see if image has enough variation to create non-degenerate geometry - // compute the area of the quad by taking the length of the cross product of the two triangles - LLVector4a v0,v1,v2,v3; - v0.setSub(p1,p2); - v1.setSub(p1,p3); - v2.setSub(p4,p2); - v3.setSub(p4,p3); + F32 area = 0; - LLVector4a cross1, cross2; - cross1.setCross3(v0,v1); - cross2.setCross3(v2,v3); + S32 sizeS = mPathp->mPath.size(); + S32 sizeT = mProfilep->mProfile.size(); - //LLVector3 cross1 = (p1 - p2) % (p1 - p3); - //LLVector3 cross2 = (p4 - p2) % (p4 - p3); - - area += (cross1.getLength3() + cross2.getLength3()).getF32() / 2.f; - } - } + for (S32 s = 0; s < sizeS-1; s++) + { + for (S32 t = 0; t < sizeT-1; t++) + { + // get four corners of quad + LLVector4a& p1 = mMesh[(s )*sizeT + (t )]; + LLVector4a& p2 = mMesh[(s+1)*sizeT + (t )]; + LLVector4a& p3 = mMesh[(s )*sizeT + (t+1)]; + LLVector4a& p4 = mMesh[(s+1)*sizeT + (t+1)]; + + // compute the area of the quad by taking the length of the cross product of the two triangles + LLVector4a v0,v1,v2,v3; + v0.setSub(p1,p2); + v1.setSub(p1,p3); + v2.setSub(p4,p2); + v3.setSub(p4,p3); + + LLVector4a cross1, cross2; + cross1.setCross3(v0,v1); + cross2.setCross3(v2,v3); + + //LLVector3 cross1 = (p1 - p2) % (p1 - p3); + //LLVector3 cross2 = (p4 - p2) % (p4 - p3); + + area += (cross1.getLength3() + cross2.getLength3()).getF32() / 2.f; + } + } - return area; + return area; } // create empty placeholder shape void LLVolume::sculptGenerateEmptyPlaceholder() { - S32 sizeS = mPathp->mPath.size(); - S32 sizeT = mProfilep->mProfile.size(); + S32 sizeS = mPathp->mPath.size(); + S32 sizeT = mProfilep->mProfile.size(); + + S32 line = 0; - S32 line = 0; + for (S32 s = 0; s < sizeS; s++) + { + for (S32 t = 0; t < sizeT; t++) + { + S32 i = t + line; + LLVector4a& pt = mMesh[i]; - for (S32 s = 0; s < sizeS; s++) - { - for (S32 t = 0; t < sizeT; t++) - { - S32 i = t + line; - LLVector4a& pt = mMesh[i]; - - F32* p = pt.getF32ptr(); + F32* p = pt.getF32ptr(); - p[0] = 0; - p[1] = 0; - p[2] = 0; + p[0] = 0; + p[1] = 0; + p[2] = 0; - llassert(pt.isFinite3()); - } - line += sizeT; - } + llassert(pt.isFinite3()); + } + line += sizeT; + } } // create sphere placeholder shape void LLVolume::sculptGenerateSpherePlaceholder() { - S32 sizeS = mPathp->mPath.size(); - S32 sizeT = mProfilep->mProfile.size(); + S32 sizeS = mPathp->mPath.size(); + S32 sizeT = mProfilep->mProfile.size(); - S32 line = 0; + S32 line = 0; - for (S32 s = 0; s < sizeS; s++) - { - for (S32 t = 0; t < sizeT; t++) - { - S32 i = t + line; - LLVector4a& pt = mMesh[i]; + for (S32 s = 0; s < sizeS; s++) + { + for (S32 t = 0; t < sizeT; t++) + { + S32 i = t + line; + LLVector4a& pt = mMesh[i]; - F32 u = (F32)s / (sizeS - 1); - F32 v = (F32)t / (sizeT - 1); + F32 u = (F32)s / (sizeS - 1); + F32 v = (F32)t / (sizeT - 1); - const F32 RADIUS = (F32) 0.3; + const F32 RADIUS = (F32) 0.3; - F32* p = pt.getF32ptr(); + F32* p = pt.getF32ptr(); - p[0] = (F32)(sin(F_PI * v) * cos(2.0 * F_PI * u) * RADIUS); - p[1] = (F32)(sin(F_PI * v) * sin(2.0 * F_PI * u) * RADIUS); - p[2] = (F32)(cos(F_PI * v) * RADIUS); + p[0] = (F32)(sin(F_PI * v) * cos(2.0 * F_PI * u) * RADIUS); + p[1] = (F32)(sin(F_PI * v) * sin(2.0 * F_PI * u) * RADIUS); + p[2] = (F32)(cos(F_PI * v) * RADIUS); - llassert(pt.isFinite3()); - } - line += sizeT; - } + llassert(pt.isFinite3()); + } + line += sizeT; + } } // create the vertices from the map void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type) { - U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK; - bool sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT; - bool sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR; - bool reverse_horizontal = (sculpt_invert ? !sculpt_mirror : sculpt_mirror); // XOR - - S32 sizeS = mPathp->mPath.size(); - S32 sizeT = mProfilep->mProfile.size(); - - S32 line = 0; - for (S32 s = 0; s < sizeS; s++) - { - // Run along the profile. - for (S32 t = 0; t < sizeT; t++) - { - S32 i = t + line; - LLVector4a& pt = mMesh[i]; - - S32 reversed_t = t; - - if (reverse_horizontal) - { - reversed_t = sizeT - t - 1; - } - - U32 x = (U32) ((F32)reversed_t/(sizeT-1) * (F32) sculpt_width); - U32 y = (U32) ((F32)s/(sizeS-1) * (F32) sculpt_height); - - - if (y == 0) // top row stitching - { - // pinch? - if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE) - { - x = sculpt_width / 2; - } - } - - if (y == sculpt_height) // bottom row stitching - { - // wrap? - if (sculpt_stitching == LL_SCULPT_TYPE_TORUS) - { - y = 0; - } - else - { - y = sculpt_height - 1; - } - - // pinch? - if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE) - { - x = sculpt_width / 2; - } - } - - if (x == sculpt_width) // side stitching - { - // wrap? - if ((sculpt_stitching == LL_SCULPT_TYPE_SPHERE) || - (sculpt_stitching == LL_SCULPT_TYPE_TORUS) || - (sculpt_stitching == LL_SCULPT_TYPE_CYLINDER)) - { - x = 0; - } - - else - { - x = sculpt_width - 1; - } - } - - pt = sculpt_xy_to_vector(x, y, sculpt_width, sculpt_height, sculpt_components, sculpt_data); - - if (sculpt_mirror) - { - LLVector4a scale(-1.f,1,1,1); - pt.mul(scale); - } - - llassert(pt.isFinite3()); - } - - line += sizeT; - } + U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK; + bool sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT; + bool sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR; + bool reverse_horizontal = (sculpt_invert ? !sculpt_mirror : sculpt_mirror); // XOR + + S32 sizeS = mPathp->mPath.size(); + S32 sizeT = mProfilep->mProfile.size(); + + S32 line = 0; + for (S32 s = 0; s < sizeS; s++) + { + // Run along the profile. + for (S32 t = 0; t < sizeT; t++) + { + S32 i = t + line; + LLVector4a& pt = mMesh[i]; + + S32 reversed_t = t; + + if (reverse_horizontal) + { + reversed_t = sizeT - t - 1; + } + + U32 x = (U32) ((F32)reversed_t/(sizeT-1) * (F32) sculpt_width); + U32 y = (U32) ((F32)s/(sizeS-1) * (F32) sculpt_height); + + + if (y == 0) // top row stitching + { + // pinch? + if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE) + { + x = sculpt_width / 2; + } + } + + if (y == sculpt_height) // bottom row stitching + { + // wrap? + if (sculpt_stitching == LL_SCULPT_TYPE_TORUS) + { + y = 0; + } + else + { + y = sculpt_height - 1; + } + + // pinch? + if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE) + { + x = sculpt_width / 2; + } + } + + if (x == sculpt_width) // side stitching + { + // wrap? + if ((sculpt_stitching == LL_SCULPT_TYPE_SPHERE) || + (sculpt_stitching == LL_SCULPT_TYPE_TORUS) || + (sculpt_stitching == LL_SCULPT_TYPE_CYLINDER)) + { + x = 0; + } + + else + { + x = sculpt_width - 1; + } + } + + pt = sculpt_xy_to_vector(x, y, sculpt_width, sculpt_height, sculpt_components, sculpt_data); + + if (sculpt_mirror) + { + LLVector4a scale(-1.f,1,1,1); + pt.mul(scale); + } + + llassert(pt.isFinite3()); + } + + line += sizeT; + } } @@ -3117,24 +3117,24 @@ constexpr S32 SCULPT_REZ_4 = 32; S32 sculpt_sides(F32 detail) { - // detail is usually one of: 1, 1.5, 2.5, 4.0. - - if (detail <= 1.0) - { - return SCULPT_REZ_1; - } - if (detail <= 2.0) - { - return SCULPT_REZ_2; - } - if (detail <= 3.0) - { - return SCULPT_REZ_3; - } - else - { - return SCULPT_REZ_4; - } + // detail is usually one of: 1, 1.5, 2.5, 4.0. + + if (detail <= 1.0) + { + return SCULPT_REZ_1; + } + if (detail <= 2.0) + { + return SCULPT_REZ_2; + } + if (detail <= 3.0) + { + return SCULPT_REZ_3; + } + else + { + return SCULPT_REZ_4; + } } @@ -3142,118 +3142,118 @@ S32 sculpt_sides(F32 detail) // determine the number of vertices in both s and t direction for this sculpt void sculpt_calc_mesh_resolution(U16 width, U16 height, U8 type, F32 detail, S32& s, S32& t) { - // this code has the following properties: - // 1) the aspect ratio of the mesh is as close as possible to the ratio of the map - // while still using all available verts - // 2) the mesh cannot have more verts than is allowed by LOD - // 3) the mesh cannot have more verts than is allowed by the map - - S32 max_vertices_lod = (S32)pow((double)sculpt_sides(detail), 2.0); - S32 max_vertices_map = width * height / 4; - - S32 vertices; - if (max_vertices_map > 0) - vertices = llmin(max_vertices_lod, max_vertices_map); - else - vertices = max_vertices_lod; - - - F32 ratio; - if ((width == 0) || (height == 0)) - ratio = 1.f; - else - ratio = (F32) width / (F32) height; - - - s = (S32)(F32) sqrt(((F32)vertices / ratio)); - - s = llmax(s, 4); // no degenerate sizes, please - t = vertices / s; - - t = llmax(t, 4); // no degenerate sizes, please - s = vertices / t; + // this code has the following properties: + // 1) the aspect ratio of the mesh is as close as possible to the ratio of the map + // while still using all available verts + // 2) the mesh cannot have more verts than is allowed by LOD + // 3) the mesh cannot have more verts than is allowed by the map + + S32 max_vertices_lod = (S32)pow((double)sculpt_sides(detail), 2.0); + S32 max_vertices_map = width * height / 4; + + S32 vertices; + if (max_vertices_map > 0) + vertices = llmin(max_vertices_lod, max_vertices_map); + else + vertices = max_vertices_lod; + + + F32 ratio; + if ((width == 0) || (height == 0)) + ratio = 1.f; + else + ratio = (F32) width / (F32) height; + + + s = (S32)(F32) sqrt(((F32)vertices / ratio)); + + s = llmax(s, 4); // no degenerate sizes, please + t = vertices / s; + + t = llmax(t, 4); // no degenerate sizes, please + s = vertices / t; } // sculpt replaces generate() for sculpted surfaces void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level, bool visible_placeholder) { - U8 sculpt_type = mParams.getSculptType(); + U8 sculpt_type = mParams.getSculptType(); - bool data_is_empty = false; + bool data_is_empty = false; - if (sculpt_width == 0 || sculpt_height == 0 || sculpt_components < 3 || sculpt_data == NULL) - { - sculpt_level = -1; - data_is_empty = true; - } + if (sculpt_width == 0 || sculpt_height == 0 || sculpt_components < 3 || sculpt_data == NULL) + { + sculpt_level = -1; + data_is_empty = true; + } - S32 requested_sizeS = 0; - S32 requested_sizeT = 0; + S32 requested_sizeS = 0; + S32 requested_sizeT = 0; - sculpt_calc_mesh_resolution(sculpt_width, sculpt_height, sculpt_type, mDetail, requested_sizeS, requested_sizeT); + sculpt_calc_mesh_resolution(sculpt_width, sculpt_height, sculpt_type, mDetail, requested_sizeS, requested_sizeT); - mPathp->generate(mParams.getPathParams(), mDetail, 0, true, requested_sizeS); - mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(), mDetail, 0, true, requested_sizeT); + mPathp->generate(mParams.getPathParams(), mDetail, 0, true, requested_sizeS); + mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(), mDetail, 0, true, requested_sizeT); + + S32 sizeS = mPathp->mPath.size(); // we requested a specific size, now see what we really got + S32 sizeT = mProfilep->mProfile.size(); // we requested a specific size, now see what we really got + + // weird crash bug - DEV-11158 - trying to collect more data: + if ((sizeS == 0) || (sizeT == 0)) + { + LL_WARNS() << "sculpt bad mesh size " << sizeS << " " << sizeT << LL_ENDL; + } - S32 sizeS = mPathp->mPath.size(); // we requested a specific size, now see what we really got - S32 sizeT = mProfilep->mProfile.size(); // we requested a specific size, now see what we really got + sNumMeshPoints -= mMesh.size(); + mMesh.resize(sizeS * sizeT); + sNumMeshPoints += mMesh.size(); - // weird crash bug - DEV-11158 - trying to collect more data: - if ((sizeS == 0) || (sizeT == 0)) - { - LL_WARNS() << "sculpt bad mesh size " << sizeS << " " << sizeT << LL_ENDL; - } - - sNumMeshPoints -= mMesh.size(); - mMesh.resize(sizeS * sizeT); - sNumMeshPoints += mMesh.size(); + //generate vertex positions + if (!data_is_empty) + { + sculptGenerateMapVertices(sculpt_width, sculpt_height, sculpt_components, sculpt_data, sculpt_type); - //generate vertex positions - if (!data_is_empty) - { - sculptGenerateMapVertices(sculpt_width, sculpt_height, sculpt_components, sculpt_data, sculpt_type); + // don't test lowest LOD to support legacy content DEV-33670 + if (mDetail > SCULPT_MIN_AREA_DETAIL) + { + F32 area = sculptGetSurfaceArea(); - // don't test lowest LOD to support legacy content DEV-33670 - if (mDetail > SCULPT_MIN_AREA_DETAIL) - { - F32 area = sculptGetSurfaceArea(); + mSurfaceArea = area; - mSurfaceArea = area; + const F32 SCULPT_MAX_AREA = 384.f; - const F32 SCULPT_MAX_AREA = 384.f; + if (area < SCULPT_MIN_AREA || area > SCULPT_MAX_AREA) + { + data_is_empty = true; + visible_placeholder = true; + } + } + } - if (area < SCULPT_MIN_AREA || area > SCULPT_MAX_AREA) - { - data_is_empty = true; - visible_placeholder = true; - } - } - } + if (data_is_empty) + { + if (visible_placeholder) + { + // Object should be visible since there will be nothing else to display + sculptGenerateSpherePlaceholder(); + } + else + { + sculptGenerateEmptyPlaceholder(); + } + } - if (data_is_empty) - { - if (visible_placeholder) - { - // Object should be visible since there will be nothing else to display - sculptGenerateSpherePlaceholder(); - } - else - { - sculptGenerateEmptyPlaceholder(); - } - } + for (S32 i = 0; i < (S32)mProfilep->mFaces.size(); i++) + { + mFaceMask |= mProfilep->mFaces[i].mFaceID; + } - for (S32 i = 0; i < (S32)mProfilep->mFaces.size(); i++) - { - mFaceMask |= mProfilep->mFaces[i].mFaceID; - } + mSculptLevel = sculpt_level; - mSculptLevel = sculpt_level; + // Delete any existing faces so that they get regenerated + mVolumeFaces.clear(); - // Delete any existing faces so that they get regenerated - mVolumeFaces.clear(); - - createVolumeFaces(); + createVolumeFaces(); } @@ -3261,12 +3261,12 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, bool LLVolume::isCap(S32 face) { - return mProfilep->mFaces[face].mCap; + return mProfilep->mFaces[face].mCap; } bool LLVolume::isFlat(S32 face) { - return mProfilep->mFaces[face].mFlat; + return mProfilep->mFaces[face].mFlat; } @@ -3277,457 +3277,457 @@ bool LLVolumeParams::isSculpt() const bool LLVolumeParams::isMeshSculpt() const { - return (mSculptType & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH; + return (mSculptType & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH; } bool LLVolumeParams::operator==(const LLVolumeParams ¶ms) const { - return ( (getPathParams() == params.getPathParams()) && - (getProfileParams() == params.getProfileParams()) && - (mSculptID == params.mSculptID) && - (mSculptType == params.mSculptType) ); + return ( (getPathParams() == params.getPathParams()) && + (getProfileParams() == params.getProfileParams()) && + (mSculptID == params.mSculptID) && + (mSculptType == params.mSculptType) ); } bool LLVolumeParams::operator!=(const LLVolumeParams ¶ms) const { - return ( (getPathParams() != params.getPathParams()) || - (getProfileParams() != params.getProfileParams()) || - (mSculptID != params.mSculptID) || - (mSculptType != params.mSculptType) ); + return ( (getPathParams() != params.getPathParams()) || + (getProfileParams() != params.getProfileParams()) || + (mSculptID != params.mSculptID) || + (mSculptType != params.mSculptType) ); } bool LLVolumeParams::operator<(const LLVolumeParams ¶ms) const { - if( getPathParams() != params.getPathParams() ) - { - return getPathParams() < params.getPathParams(); - } - - if (getProfileParams() != params.getProfileParams()) - { - return getProfileParams() < params.getProfileParams(); - } - - if (mSculptID != params.mSculptID) - { - return mSculptID < params.mSculptID; - } + if( getPathParams() != params.getPathParams() ) + { + return getPathParams() < params.getPathParams(); + } + + if (getProfileParams() != params.getProfileParams()) + { + return getProfileParams() < params.getProfileParams(); + } + + if (mSculptID != params.mSculptID) + { + return mSculptID < params.mSculptID; + } - return mSculptType < params.mSculptType; + return mSculptType < params.mSculptType; } void LLVolumeParams::copyParams(const LLVolumeParams ¶ms) { - mProfileParams.copyParams(params.mProfileParams); - mPathParams.copyParams(params.mPathParams); - mSculptID = params.getSculptID(); - mSculptType = params.getSculptType(); + mProfileParams.copyParams(params.mProfileParams); + mPathParams.copyParams(params.mPathParams); + mSculptID = params.getSculptID(); + mSculptType = params.getSculptType(); } // Less restricitve approx 0 for volumes constexpr F32 APPROXIMATELY_ZERO = 0.001f; bool approx_zero( F32 f, F32 tolerance = APPROXIMATELY_ZERO) { - return (f >= -tolerance) && (f <= tolerance); + return (f >= -tolerance) && (f <= tolerance); } // return true if in range (or nearly so) static bool limit_range(F32& v, F32 min, F32 max, F32 tolerance = APPROXIMATELY_ZERO) { - F32 min_delta = v - min; - if (min_delta < 0.f) - { - v = min; - if (!approx_zero(min_delta, tolerance)) - return false; - } - F32 max_delta = max - v; - if (max_delta < 0.f) - { - v = max; - if (!approx_zero(max_delta, tolerance)) - return false; - } - return true; + F32 min_delta = v - min; + if (min_delta < 0.f) + { + v = min; + if (!approx_zero(min_delta, tolerance)) + return false; + } + F32 max_delta = max - v; + if (max_delta < 0.f) + { + v = max; + if (!approx_zero(max_delta, tolerance)) + return false; + } + return true; } bool LLVolumeParams::setBeginAndEndS(const F32 b, const F32 e) { - bool valid = true; + bool valid = true; - // First, clamp to valid ranges. - F32 begin = b; - valid &= limit_range(begin, 0.f, 1.f - MIN_CUT_DELTA); + // First, clamp to valid ranges. + F32 begin = b; + valid &= limit_range(begin, 0.f, 1.f - MIN_CUT_DELTA); - F32 end = e; - if (end >= .0149f && end < MIN_CUT_DELTA) end = MIN_CUT_DELTA; // eliminate warning for common rounding error - valid &= limit_range(end, MIN_CUT_DELTA, 1.f); + F32 end = e; + if (end >= .0149f && end < MIN_CUT_DELTA) end = MIN_CUT_DELTA; // eliminate warning for common rounding error + valid &= limit_range(end, MIN_CUT_DELTA, 1.f); - valid &= limit_range(begin, 0.f, end - MIN_CUT_DELTA, .01f); + valid &= limit_range(begin, 0.f, end - MIN_CUT_DELTA, .01f); - // Now set them. - mProfileParams.setBegin(begin); - mProfileParams.setEnd(end); + // Now set them. + mProfileParams.setBegin(begin); + mProfileParams.setEnd(end); - return valid; + return valid; } bool LLVolumeParams::setBeginAndEndT(const F32 b, const F32 e) { - bool valid = true; + bool valid = true; - // First, clamp to valid ranges. - F32 begin = b; - valid &= limit_range(begin, 0.f, 1.f - MIN_CUT_DELTA); + // First, clamp to valid ranges. + F32 begin = b; + valid &= limit_range(begin, 0.f, 1.f - MIN_CUT_DELTA); - F32 end = e; - valid &= limit_range(end, MIN_CUT_DELTA, 1.f); + F32 end = e; + valid &= limit_range(end, MIN_CUT_DELTA, 1.f); - valid &= limit_range(begin, 0.f, end - MIN_CUT_DELTA, .01f); + valid &= limit_range(begin, 0.f, end - MIN_CUT_DELTA, .01f); - // Now set them. - mPathParams.setBegin(begin); - mPathParams.setEnd(end); + // Now set them. + mPathParams.setBegin(begin); + mPathParams.setEnd(end); - return valid; -} + return valid; +} bool LLVolumeParams::setHollow(const F32 h) { - // Validate the hollow based on path and profile. - U8 profile = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; - U8 hole_type = mProfileParams.getCurveType() & LL_PCODE_HOLE_MASK; - - F32 max_hollow = HOLLOW_MAX; - - // Only square holes have trouble. - if (LL_PCODE_HOLE_SQUARE == hole_type) - { - switch(profile) - { - case LL_PCODE_PROFILE_CIRCLE: - case LL_PCODE_PROFILE_CIRCLE_HALF: - case LL_PCODE_PROFILE_EQUALTRI: - max_hollow = HOLLOW_MAX_SQUARE; - } - } - - F32 hollow = h; - bool valid = limit_range(hollow, HOLLOW_MIN, max_hollow); - mProfileParams.setHollow(hollow); - - return valid; -} + // Validate the hollow based on path and profile. + U8 profile = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; + U8 hole_type = mProfileParams.getCurveType() & LL_PCODE_HOLE_MASK; + + F32 max_hollow = HOLLOW_MAX; + + // Only square holes have trouble. + if (LL_PCODE_HOLE_SQUARE == hole_type) + { + switch(profile) + { + case LL_PCODE_PROFILE_CIRCLE: + case LL_PCODE_PROFILE_CIRCLE_HALF: + case LL_PCODE_PROFILE_EQUALTRI: + max_hollow = HOLLOW_MAX_SQUARE; + } + } + + F32 hollow = h; + bool valid = limit_range(hollow, HOLLOW_MIN, max_hollow); + mProfileParams.setHollow(hollow); + + return valid; +} bool LLVolumeParams::setTwistBegin(const F32 b) { - F32 twist_begin = b; - bool valid = limit_range(twist_begin, TWIST_MIN, TWIST_MAX); - mPathParams.setTwistBegin(twist_begin); - return valid; + F32 twist_begin = b; + bool valid = limit_range(twist_begin, TWIST_MIN, TWIST_MAX); + mPathParams.setTwistBegin(twist_begin); + return valid; } bool LLVolumeParams::setTwistEnd(const F32 e) -{ - F32 twist_end = e; - bool valid = limit_range(twist_end, TWIST_MIN, TWIST_MAX); - mPathParams.setTwistEnd(twist_end); - return valid; +{ + F32 twist_end = e; + bool valid = limit_range(twist_end, TWIST_MIN, TWIST_MAX); + mPathParams.setTwistEnd(twist_end); + return valid; } bool LLVolumeParams::setRatio(const F32 x, const F32 y) { - F32 min_x = RATIO_MIN; - F32 max_x = RATIO_MAX; - F32 min_y = RATIO_MIN; - F32 max_y = RATIO_MAX; - // If this is a circular path (and not a sphere) then 'ratio' is actually hole size. - U8 path_type = mPathParams.getCurveType(); - U8 profile_type = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; - if ( LL_PCODE_PATH_CIRCLE == path_type && - LL_PCODE_PROFILE_CIRCLE_HALF != profile_type) - { - // Holes are more restricted... - min_x = HOLE_X_MIN; - max_x = HOLE_X_MAX; - min_y = HOLE_Y_MIN; - max_y = HOLE_Y_MAX; - } - - F32 ratio_x = x; - bool valid = limit_range(ratio_x, min_x, max_x); - F32 ratio_y = y; - valid &= limit_range(ratio_y, min_y, max_y); - - mPathParams.setScale(ratio_x, ratio_y); - - return valid; + F32 min_x = RATIO_MIN; + F32 max_x = RATIO_MAX; + F32 min_y = RATIO_MIN; + F32 max_y = RATIO_MAX; + // If this is a circular path (and not a sphere) then 'ratio' is actually hole size. + U8 path_type = mPathParams.getCurveType(); + U8 profile_type = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; + if ( LL_PCODE_PATH_CIRCLE == path_type && + LL_PCODE_PROFILE_CIRCLE_HALF != profile_type) + { + // Holes are more restricted... + min_x = HOLE_X_MIN; + max_x = HOLE_X_MAX; + min_y = HOLE_Y_MIN; + max_y = HOLE_Y_MAX; + } + + F32 ratio_x = x; + bool valid = limit_range(ratio_x, min_x, max_x); + F32 ratio_y = y; + valid &= limit_range(ratio_y, min_y, max_y); + + mPathParams.setScale(ratio_x, ratio_y); + + return valid; } bool LLVolumeParams::setShear(const F32 x, const F32 y) { - F32 shear_x = x; - bool valid = limit_range(shear_x, SHEAR_MIN, SHEAR_MAX); - F32 shear_y = y; - valid &= limit_range(shear_y, SHEAR_MIN, SHEAR_MAX); - mPathParams.setShear(shear_x, shear_y); - return valid; + F32 shear_x = x; + bool valid = limit_range(shear_x, SHEAR_MIN, SHEAR_MAX); + F32 shear_y = y; + valid &= limit_range(shear_y, SHEAR_MIN, SHEAR_MAX); + mPathParams.setShear(shear_x, shear_y); + return valid; } bool LLVolumeParams::setTaperX(const F32 v) { - F32 taper = v; - bool valid = limit_range(taper, TAPER_MIN, TAPER_MAX); - mPathParams.setTaperX(taper); - return valid; + F32 taper = v; + bool valid = limit_range(taper, TAPER_MIN, TAPER_MAX); + mPathParams.setTaperX(taper); + return valid; } bool LLVolumeParams::setTaperY(const F32 v) { - F32 taper = v; - bool valid = limit_range(taper, TAPER_MIN, TAPER_MAX); - mPathParams.setTaperY(taper); - return valid; + F32 taper = v; + bool valid = limit_range(taper, TAPER_MIN, TAPER_MAX); + mPathParams.setTaperY(taper); + return valid; } bool LLVolumeParams::setRevolutions(const F32 r) { - F32 revolutions = r; - bool valid = limit_range(revolutions, REV_MIN, REV_MAX); - mPathParams.setRevolutions(revolutions); - return valid; + F32 revolutions = r; + bool valid = limit_range(revolutions, REV_MIN, REV_MAX); + mPathParams.setRevolutions(revolutions); + return valid; } bool LLVolumeParams::setRadiusOffset(const F32 offset) { - bool valid = true; - - // If this is a sphere, just set it to 0 and get out. - U8 path_type = mPathParams.getCurveType(); - U8 profile_type = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; - if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type || - LL_PCODE_PATH_CIRCLE != path_type ) - { - mPathParams.setRadiusOffset(0.f); - return true; - } - - // Limit radius offset, based on taper and hole size y. - F32 radius_offset = offset; - F32 taper_y = getTaperY(); - F32 radius_mag = fabs(radius_offset); - F32 hole_y_mag = fabs(getRatioY()); - F32 taper_y_mag = fabs(taper_y); - // Check to see if the taper effects us. - if ( (radius_offset > 0.f && taper_y < 0.f) || - (radius_offset < 0.f && taper_y > 0.f) ) - { - // The taper does not help increase the radius offset range. - taper_y_mag = 0.f; - } - F32 max_radius_mag = 1.f - hole_y_mag * (1.f - taper_y_mag) / (1.f - hole_y_mag); - - // Enforce the maximum magnitude. - F32 delta = max_radius_mag - radius_mag; - if (delta < 0.f) - { - // Check radius offset sign. - if (radius_offset < 0.f) - { - radius_offset = -max_radius_mag; - } - else - { - radius_offset = max_radius_mag; - } - valid = approx_zero(delta, .1f); - } - - mPathParams.setRadiusOffset(radius_offset); - return valid; + bool valid = true; + + // If this is a sphere, just set it to 0 and get out. + U8 path_type = mPathParams.getCurveType(); + U8 profile_type = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; + if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type || + LL_PCODE_PATH_CIRCLE != path_type ) + { + mPathParams.setRadiusOffset(0.f); + return true; + } + + // Limit radius offset, based on taper and hole size y. + F32 radius_offset = offset; + F32 taper_y = getTaperY(); + F32 radius_mag = fabs(radius_offset); + F32 hole_y_mag = fabs(getRatioY()); + F32 taper_y_mag = fabs(taper_y); + // Check to see if the taper effects us. + if ( (radius_offset > 0.f && taper_y < 0.f) || + (radius_offset < 0.f && taper_y > 0.f) ) + { + // The taper does not help increase the radius offset range. + taper_y_mag = 0.f; + } + F32 max_radius_mag = 1.f - hole_y_mag * (1.f - taper_y_mag) / (1.f - hole_y_mag); + + // Enforce the maximum magnitude. + F32 delta = max_radius_mag - radius_mag; + if (delta < 0.f) + { + // Check radius offset sign. + if (radius_offset < 0.f) + { + radius_offset = -max_radius_mag; + } + else + { + radius_offset = max_radius_mag; + } + valid = approx_zero(delta, .1f); + } + + mPathParams.setRadiusOffset(radius_offset); + return valid; } bool LLVolumeParams::setSkew(const F32 skew_value) { - bool valid = true; - - // Check the skew value against the revolutions. - F32 skew = llclamp(skew_value, SKEW_MIN, SKEW_MAX); - F32 skew_mag = fabs(skew); - F32 revolutions = getRevolutions(); - F32 scale_x = getRatioX(); - F32 min_skew_mag = 1.0f - 1.0f / (revolutions * scale_x + 1.0f); - // Discontinuity; A revolution of 1 allows skews below 0.5. - if ( fabs(revolutions - 1.0f) < 0.001) - min_skew_mag = 0.0f; - - // Clip skew. - F32 delta = skew_mag - min_skew_mag; - if (delta < 0.f) - { - // Check skew sign. - if (skew < 0.0f) - { - skew = -min_skew_mag; - } - else - { - skew = min_skew_mag; - } - valid = approx_zero(delta, .01f); - } - - mPathParams.setSkew(skew); - return valid; + bool valid = true; + + // Check the skew value against the revolutions. + F32 skew = llclamp(skew_value, SKEW_MIN, SKEW_MAX); + F32 skew_mag = fabs(skew); + F32 revolutions = getRevolutions(); + F32 scale_x = getRatioX(); + F32 min_skew_mag = 1.0f - 1.0f / (revolutions * scale_x + 1.0f); + // Discontinuity; A revolution of 1 allows skews below 0.5. + if ( fabs(revolutions - 1.0f) < 0.001) + min_skew_mag = 0.0f; + + // Clip skew. + F32 delta = skew_mag - min_skew_mag; + if (delta < 0.f) + { + // Check skew sign. + if (skew < 0.0f) + { + skew = -min_skew_mag; + } + else + { + skew = min_skew_mag; + } + valid = approx_zero(delta, .01f); + } + + mPathParams.setSkew(skew); + return valid; } bool LLVolumeParams::setSculptID(const LLUUID& sculpt_id, U8 sculpt_type) { - mSculptID = sculpt_id; - mSculptType = sculpt_type; - return true; + mSculptID = sculpt_id; + mSculptType = sculpt_type; + return true; } bool LLVolumeParams::setType(U8 profile, U8 path) { - bool result = true; - // First, check profile and path for validity. - U8 profile_type = profile & LL_PCODE_PROFILE_MASK; - U8 hole_type = (profile & LL_PCODE_HOLE_MASK) >> 4; - U8 path_type = path >> 4; - - if (profile_type > LL_PCODE_PROFILE_MAX) - { - // Bad profile. Make it square. - profile = LL_PCODE_PROFILE_SQUARE; - result = false; - LL_WARNS() << "LLVolumeParams::setType changing bad profile type (" << profile_type - << ") to be LL_PCODE_PROFILE_SQUARE" << LL_ENDL; - } - else if (hole_type > LL_PCODE_HOLE_MAX) - { - // Bad hole. Make it the same. - profile = profile_type; - result = false; - LL_WARNS() << "LLVolumeParams::setType changing bad hole type (" << hole_type - << ") to be LL_PCODE_HOLE_SAME" << LL_ENDL; - } - - if (path_type < LL_PCODE_PATH_MIN || - path_type > LL_PCODE_PATH_MAX) - { - // Bad path. Make it linear. - result = false; - LL_WARNS() << "LLVolumeParams::setType changing bad path (" << path - << ") to be LL_PCODE_PATH_LINE" << LL_ENDL; - path = LL_PCODE_PATH_LINE; - } - - mProfileParams.setCurveType(profile); - mPathParams.setCurveType(path); - return result; -} - -// static + bool result = true; + // First, check profile and path for validity. + U8 profile_type = profile & LL_PCODE_PROFILE_MASK; + U8 hole_type = (profile & LL_PCODE_HOLE_MASK) >> 4; + U8 path_type = path >> 4; + + if (profile_type > LL_PCODE_PROFILE_MAX) + { + // Bad profile. Make it square. + profile = LL_PCODE_PROFILE_SQUARE; + result = false; + LL_WARNS() << "LLVolumeParams::setType changing bad profile type (" << profile_type + << ") to be LL_PCODE_PROFILE_SQUARE" << LL_ENDL; + } + else if (hole_type > LL_PCODE_HOLE_MAX) + { + // Bad hole. Make it the same. + profile = profile_type; + result = false; + LL_WARNS() << "LLVolumeParams::setType changing bad hole type (" << hole_type + << ") to be LL_PCODE_HOLE_SAME" << LL_ENDL; + } + + if (path_type < LL_PCODE_PATH_MIN || + path_type > LL_PCODE_PATH_MAX) + { + // Bad path. Make it linear. + result = false; + LL_WARNS() << "LLVolumeParams::setType changing bad path (" << path + << ") to be LL_PCODE_PATH_LINE" << LL_ENDL; + path = LL_PCODE_PATH_LINE; + } + + mProfileParams.setCurveType(profile); + mPathParams.setCurveType(path); + return result; +} + +// static bool LLVolumeParams::validate(U8 prof_curve, F32 prof_begin, F32 prof_end, F32 hollow, - U8 path_curve, F32 path_begin, F32 path_end, - F32 scx, F32 scy, F32 shx, F32 shy, - F32 twistend, F32 twistbegin, F32 radiusoffset, - F32 tx, F32 ty, F32 revolutions, F32 skew) -{ - LLVolumeParams test_params; - if (!test_params.setType (prof_curve, path_curve)) - { - return false; - } - if (!test_params.setBeginAndEndS (prof_begin, prof_end)) - { - return false; - } - if (!test_params.setBeginAndEndT (path_begin, path_end)) - { - return false; - } - if (!test_params.setHollow (hollow)) - { - return false; - } - if (!test_params.setTwistBegin (twistbegin)) - { - return false; - } - if (!test_params.setTwistEnd (twistend)) - { - return false; - } - if (!test_params.setRatio (scx, scy)) - { - return false; - } - if (!test_params.setShear (shx, shy)) - { - return false; - } - if (!test_params.setTaper (tx, ty)) - { - return false; - } - if (!test_params.setRevolutions (revolutions)) - { - return false; - } - if (!test_params.setRadiusOffset (radiusoffset)) - { - return false; - } - if (!test_params.setSkew (skew)) - { - return false; - } - return true; + U8 path_curve, F32 path_begin, F32 path_end, + F32 scx, F32 scy, F32 shx, F32 shy, + F32 twistend, F32 twistbegin, F32 radiusoffset, + F32 tx, F32 ty, F32 revolutions, F32 skew) +{ + LLVolumeParams test_params; + if (!test_params.setType (prof_curve, path_curve)) + { + return false; + } + if (!test_params.setBeginAndEndS (prof_begin, prof_end)) + { + return false; + } + if (!test_params.setBeginAndEndT (path_begin, path_end)) + { + return false; + } + if (!test_params.setHollow (hollow)) + { + return false; + } + if (!test_params.setTwistBegin (twistbegin)) + { + return false; + } + if (!test_params.setTwistEnd (twistend)) + { + return false; + } + if (!test_params.setRatio (scx, scy)) + { + return false; + } + if (!test_params.setShear (shx, shy)) + { + return false; + } + if (!test_params.setTaper (tx, ty)) + { + return false; + } + if (!test_params.setRevolutions (revolutions)) + { + return false; + } + if (!test_params.setRadiusOffset (radiusoffset)) + { + return false; + } + if (!test_params.setSkew (skew)) + { + return false; + } + return true; } void LLVolume::getLoDTriangleCounts(const LLVolumeParams& params, S32* counts) -{ //attempt to approximate the number of triangles that will result from generating a volume LoD set for the - //supplied LLVolumeParams -- inaccurate, but a close enough approximation for determining streaming cost +{ //attempt to approximate the number of triangles that will result from generating a volume LoD set for the + //supplied LLVolumeParams -- inaccurate, but a close enough approximation for determining streaming cost LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; - F32 detail[] = {1.f, 1.5f, 2.5f, 4.f}; - for (S32 i = 0; i < 4; i++) - { - S32 count = 0; - S32 path_points = LLPath::getNumPoints(params.getPathParams(), detail[i]); - S32 profile_points = LLProfile::getNumPoints(params.getProfileParams(), false, detail[i]); + F32 detail[] = {1.f, 1.5f, 2.5f, 4.f}; + for (S32 i = 0; i < 4; i++) + { + S32 count = 0; + S32 path_points = LLPath::getNumPoints(params.getPathParams(), detail[i]); + S32 profile_points = LLProfile::getNumPoints(params.getProfileParams(), false, detail[i]); - count = (profile_points-1)*2*(path_points-1); - count += profile_points*2; + count = (profile_points-1)*2*(path_points-1); + count += profile_points*2; - counts[i] = count; - } + counts[i] = count; + } } S32 LLVolume::getNumTriangles(S32* vcount) const { - U32 triangle_count = 0; - U32 vertex_count = 0; + U32 triangle_count = 0; + U32 vertex_count = 0; - for (S32 i = 0; i < getNumVolumeFaces(); ++i) - { - const LLVolumeFace& face = getVolumeFace(i); - triangle_count += face.mNumIndices/3; + for (S32 i = 0; i < getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = getVolumeFace(i); + triangle_count += face.mNumIndices/3; - vertex_count += face.mNumVertices; - } + vertex_count += face.mNumVertices; + } - if (vcount) - { - *vcount = vertex_count; - } - - return triangle_count; + if (vcount) + { + *vcount = vertex_count; + } + + return triangle_count; } @@ -3735,988 +3735,988 @@ S32 LLVolume::getNumTriangles(S32* vcount) const // generateSilhouetteVertices() //----------------------------------------------------------------------------- void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices, - std::vector<LLVector3> &normals, - const LLVector3& obj_cam_vec_in, - const LLMatrix4& mat_in, - const LLMatrix3& norm_mat_in, - S32 face_mask) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME - - LLMatrix4a mat; - mat.loadu(mat_in); - - LLMatrix4a norm_mat; - norm_mat.loadu(norm_mat_in); - - LLVector4a obj_cam_vec; - obj_cam_vec.load3(obj_cam_vec_in.mV); - - vertices.clear(); - normals.clear(); - - if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) - { - return; - } - - S32 cur_index = 0; - //for each face - for (face_list_t::iterator iter = mVolumeFaces.begin(); - iter != mVolumeFaces.end(); ++iter) - { - LLVolumeFace& face = *iter; - - if (!(face_mask & (0x1 << cur_index++)) || - face.mNumIndices == 0 || face.mEdge.empty()) - { - continue; - } - - if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) - { - LLVector4a* v = (LLVector4a*)face.mPositions; - LLVector4a* n = (LLVector4a*)face.mNormals; - - for (U32 j = 0; j < face.mNumIndices / 3; j++) - { - for (S32 k = 0; k < 3; k++) - { - S32 index = face.mEdge[j * 3 + k]; - - if (index == -1) - { - // silhouette edge, currently only cubes, so no other conditions - - S32 v1 = face.mIndices[j * 3 + k]; - S32 v2 = face.mIndices[j * 3 + ((k + 1) % 3)]; - - LLVector4a t; - mat.affineTransform(v[v1], t); - vertices.push_back(LLVector3(t[0], t[1], t[2])); - - norm_mat.rotate(n[v1], t); - - t.normalize3fast(); - normals.push_back(LLVector3(t[0], t[1], t[2])); - - mat.affineTransform(v[v2], t); - vertices.push_back(LLVector3(t[0], t[1], t[2])); - - norm_mat.rotate(n[v2], t); - t.normalize3fast(); - normals.push_back(LLVector3(t[0], t[1], t[2])); - } - } - } - - } - else - { - //============================================== - //DEBUG draw edge map instead of silhouette edge - //============================================== + std::vector<LLVector3> &normals, + const LLVector3& obj_cam_vec_in, + const LLMatrix4& mat_in, + const LLMatrix3& norm_mat_in, + S32 face_mask) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME + + LLMatrix4a mat; + mat.loadu(mat_in); + + LLMatrix4a norm_mat; + norm_mat.loadu(norm_mat_in); + + LLVector4a obj_cam_vec; + obj_cam_vec.load3(obj_cam_vec_in.mV); + + vertices.clear(); + normals.clear(); + + if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + { + return; + } + + S32 cur_index = 0; + //for each face + for (face_list_t::iterator iter = mVolumeFaces.begin(); + iter != mVolumeFaces.end(); ++iter) + { + LLVolumeFace& face = *iter; + + if (!(face_mask & (0x1 << cur_index++)) || + face.mNumIndices == 0 || face.mEdge.empty()) + { + continue; + } + + if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) + { + LLVector4a* v = (LLVector4a*)face.mPositions; + LLVector4a* n = (LLVector4a*)face.mNormals; + + for (U32 j = 0; j < face.mNumIndices / 3; j++) + { + for (S32 k = 0; k < 3; k++) + { + S32 index = face.mEdge[j * 3 + k]; + + if (index == -1) + { + // silhouette edge, currently only cubes, so no other conditions + + S32 v1 = face.mIndices[j * 3 + k]; + S32 v2 = face.mIndices[j * 3 + ((k + 1) % 3)]; + + LLVector4a t; + mat.affineTransform(v[v1], t); + vertices.push_back(LLVector3(t[0], t[1], t[2])); + + norm_mat.rotate(n[v1], t); + + t.normalize3fast(); + normals.push_back(LLVector3(t[0], t[1], t[2])); + + mat.affineTransform(v[v2], t); + vertices.push_back(LLVector3(t[0], t[1], t[2])); + + norm_mat.rotate(n[v2], t); + t.normalize3fast(); + normals.push_back(LLVector3(t[0], t[1], t[2])); + } + } + } + + } + else + { + //============================================== + //DEBUG draw edge map instead of silhouette edge + //============================================== #if DEBUG_SILHOUETTE_EDGE_MAP - //for each triangle + //for each triangle U32 tri_count = face.mNumIndices / 3; for (U32 j = 0; j < tri_count; j++) { - //get vertices - S32 v1 = face.mIndices[j*3+0]; - S32 v2 = face.mIndices[j*3+1]; - S32 v3 = face.mIndices[j*3+2]; - - //get current face center - LLVector3 cCenter = (face.mVertices[v1].getPosition() + - face.mVertices[v2].getPosition() + - face.mVertices[v3].getPosition()) / 3.0f; - - //for each edge - for (S32 k = 0; k < 3; k++) { + //get vertices + S32 v1 = face.mIndices[j*3+0]; + S32 v2 = face.mIndices[j*3+1]; + S32 v3 = face.mIndices[j*3+2]; + + //get current face center + LLVector3 cCenter = (face.mVertices[v1].getPosition() + + face.mVertices[v2].getPosition() + + face.mVertices[v3].getPosition()) / 3.0f; + + //for each edge + for (S32 k = 0; k < 3; k++) { S32 nIndex = face.mEdge[j*3+k]; - if (nIndex <= -1) { - continue; - } + if (nIndex <= -1) { + continue; + } if (nIndex >= (S32)tri_count) { - continue; - } - //get neighbor vertices - v1 = face.mIndices[nIndex*3+0]; - v2 = face.mIndices[nIndex*3+1]; - v3 = face.mIndices[nIndex*3+2]; - - //get neighbor face center - LLVector3 nCenter = (face.mVertices[v1].getPosition() + - face.mVertices[v2].getPosition() + - face.mVertices[v3].getPosition()) / 3.0f; - - //draw line - vertices.push_back(cCenter); - vertices.push_back(nCenter); - normals.push_back(LLVector3(1,1,1)); - normals.push_back(LLVector3(1,1,1)); - segments.push_back(vertices.size()); - } - } - - continue; - - //============================================== - //DEBUG - //============================================== - - //============================================== - //DEBUG draw normals instead of silhouette edge - //============================================== + continue; + } + //get neighbor vertices + v1 = face.mIndices[nIndex*3+0]; + v2 = face.mIndices[nIndex*3+1]; + v3 = face.mIndices[nIndex*3+2]; + + //get neighbor face center + LLVector3 nCenter = (face.mVertices[v1].getPosition() + + face.mVertices[v2].getPosition() + + face.mVertices[v3].getPosition()) / 3.0f; + + //draw line + vertices.push_back(cCenter); + vertices.push_back(nCenter); + normals.push_back(LLVector3(1,1,1)); + normals.push_back(LLVector3(1,1,1)); + segments.push_back(vertices.size()); + } + } + + continue; + + //============================================== + //DEBUG + //============================================== + + //============================================== + //DEBUG draw normals instead of silhouette edge + //============================================== #elif DEBUG_SILHOUETTE_NORMALS - //for each vertex - for (U32 j = 0; j < face.mNumVertices; j++) { - vertices.push_back(face.mVertices[j].getPosition()); - vertices.push_back(face.mVertices[j].getPosition() + face.mVertices[j].getNormal()*0.1f); - normals.push_back(LLVector3(0,0,1)); - normals.push_back(LLVector3(0,0,1)); - segments.push_back(vertices.size()); + //for each vertex + for (U32 j = 0; j < face.mNumVertices; j++) { + vertices.push_back(face.mVertices[j].getPosition()); + vertices.push_back(face.mVertices[j].getPosition() + face.mVertices[j].getNormal()*0.1f); + normals.push_back(LLVector3(0,0,1)); + normals.push_back(LLVector3(0,0,1)); + segments.push_back(vertices.size()); #if DEBUG_SILHOUETTE_BINORMALS - vertices.push_back(face.mVertices[j].getPosition()); - vertices.push_back(face.mVertices[j].getPosition() + face.mVertices[j].mTangent*0.1f); - normals.push_back(LLVector3(0,0,1)); - normals.push_back(LLVector3(0,0,1)); - segments.push_back(vertices.size()); + vertices.push_back(face.mVertices[j].getPosition()); + vertices.push_back(face.mVertices[j].getPosition() + face.mVertices[j].mTangent*0.1f); + normals.push_back(LLVector3(0,0,1)); + normals.push_back(LLVector3(0,0,1)); + segments.push_back(vertices.size()); #endif - } - - continue; + } + + continue; #else - //============================================== - //DEBUG - //============================================== - - constexpr U8 AWAY = 0x01, - TOWARDS = 0x02; - - //for each triangle - std::vector<U8> fFacing; - vector_append(fFacing, face.mNumIndices/3); - - LLVector4a* v = (LLVector4a*) face.mPositions; - LLVector4a* n = (LLVector4a*) face.mNormals; - - for (U32 j = 0; j < face.mNumIndices/3; j++) - { - //approximate normal - S32 v1 = face.mIndices[j*3+0]; - S32 v2 = face.mIndices[j*3+1]; - S32 v3 = face.mIndices[j*3+2]; - - LLVector4a c1,c2; - c1.setSub(v[v1], v[v2]); - c2.setSub(v[v2], v[v3]); - - LLVector4a norm; - - norm.setCross3(c1, c2); - - if (norm.dot3(norm) < 0.00000001f) - { - fFacing[j] = AWAY | TOWARDS; - } - else - { - //get view vector - LLVector4a view; - view.setSub(obj_cam_vec, v[v1]); - bool away = view.dot3(norm) > 0.0f; - if (away) - { - fFacing[j] = AWAY; - } - else - { - fFacing[j] = TOWARDS; - } - } - } - - //for each triangle - for (U32 j = 0; j < face.mNumIndices/3; j++) - { - if (fFacing[j] == (AWAY | TOWARDS)) - { //this is a degenerate triangle - //take neighbor facing (degenerate faces get facing of one of their neighbors) - // *FIX IF NEEDED: this does not deal with neighboring degenerate faces - for (S32 k = 0; k < 3; k++) - { - S32 index = face.mEdge[j*3+k]; - if (index != -1) - { - fFacing[j] = fFacing[index]; - break; - } - } - continue; //skip degenerate face - } - - //for each edge - for (S32 k = 0; k < 3; k++) { - S32 index = face.mEdge[j*3+k]; - if (index != -1 && fFacing[index] == (AWAY | TOWARDS)) { - //our neighbor is degenerate, make him face our direction - fFacing[face.mEdge[j*3+k]] = fFacing[j]; - continue; - } - - if (index == -1 || //edge has no neighbor, MUST be a silhouette edge - (fFacing[index] & fFacing[j]) == 0) { //we found a silhouette edge - - S32 v1 = face.mIndices[j*3+k]; - S32 v2 = face.mIndices[j*3+((k+1)%3)]; - - LLVector4a t; - mat.affineTransform(v[v1], t); - vertices.push_back(LLVector3(t[0], t[1], t[2])); - - norm_mat.rotate(n[v1], t); - - t.normalize3fast(); - normals.push_back(LLVector3(t[0], t[1], t[2])); - - mat.affineTransform(v[v2], t); - vertices.push_back(LLVector3(t[0], t[1], t[2])); - - norm_mat.rotate(n[v2], t); - t.normalize3fast(); - normals.push_back(LLVector3(t[0], t[1], t[2])); - } - } - } + //============================================== + //DEBUG + //============================================== + + constexpr U8 AWAY = 0x01, + TOWARDS = 0x02; + + //for each triangle + std::vector<U8> fFacing; + vector_append(fFacing, face.mNumIndices/3); + + LLVector4a* v = (LLVector4a*) face.mPositions; + LLVector4a* n = (LLVector4a*) face.mNormals; + + for (U32 j = 0; j < face.mNumIndices/3; j++) + { + //approximate normal + S32 v1 = face.mIndices[j*3+0]; + S32 v2 = face.mIndices[j*3+1]; + S32 v3 = face.mIndices[j*3+2]; + + LLVector4a c1,c2; + c1.setSub(v[v1], v[v2]); + c2.setSub(v[v2], v[v3]); + + LLVector4a norm; + + norm.setCross3(c1, c2); + + if (norm.dot3(norm) < 0.00000001f) + { + fFacing[j] = AWAY | TOWARDS; + } + else + { + //get view vector + LLVector4a view; + view.setSub(obj_cam_vec, v[v1]); + bool away = view.dot3(norm) > 0.0f; + if (away) + { + fFacing[j] = AWAY; + } + else + { + fFacing[j] = TOWARDS; + } + } + } + + //for each triangle + for (U32 j = 0; j < face.mNumIndices/3; j++) + { + if (fFacing[j] == (AWAY | TOWARDS)) + { //this is a degenerate triangle + //take neighbor facing (degenerate faces get facing of one of their neighbors) + // *FIX IF NEEDED: this does not deal with neighboring degenerate faces + for (S32 k = 0; k < 3; k++) + { + S32 index = face.mEdge[j*3+k]; + if (index != -1) + { + fFacing[j] = fFacing[index]; + break; + } + } + continue; //skip degenerate face + } + + //for each edge + for (S32 k = 0; k < 3; k++) { + S32 index = face.mEdge[j*3+k]; + if (index != -1 && fFacing[index] == (AWAY | TOWARDS)) { + //our neighbor is degenerate, make him face our direction + fFacing[face.mEdge[j*3+k]] = fFacing[j]; + continue; + } + + if (index == -1 || //edge has no neighbor, MUST be a silhouette edge + (fFacing[index] & fFacing[j]) == 0) { //we found a silhouette edge + + S32 v1 = face.mIndices[j*3+k]; + S32 v2 = face.mIndices[j*3+((k+1)%3)]; + + LLVector4a t; + mat.affineTransform(v[v1], t); + vertices.push_back(LLVector3(t[0], t[1], t[2])); + + norm_mat.rotate(n[v1], t); + + t.normalize3fast(); + normals.push_back(LLVector3(t[0], t[1], t[2])); + + mat.affineTransform(v[v2], t); + vertices.push_back(LLVector3(t[0], t[1], t[2])); + + norm_mat.rotate(n[v2], t); + t.normalize3fast(); + normals.push_back(LLVector3(t[0], t[1], t[2])); + } + } + } #endif - } - } -} - -S32 LLVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, - S32 face, - LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent_out) -{ - S32 hit_face = -1; - - S32 start_face; - S32 end_face; - - if (face == -1) // ALL_SIDES - { - start_face = 0; - end_face = getNumVolumeFaces() - 1; - } - else - { - start_face = face; - end_face = face; - } - - LLVector4a dir; - dir.setSub(end, start); - - F32 closest_t = 2.f; // must be larger than 1 - - end_face = llmin(end_face, getNumVolumeFaces()-1); - - for (S32 i = start_face; i <= end_face; i++) - { - LLVolumeFace &face = mVolumeFaces[i]; - - LLVector4a box_center; - box_center.setAdd(face.mExtents[0], face.mExtents[1]); - box_center.mul(0.5f); - - LLVector4a box_size; - box_size.setSub(face.mExtents[1], face.mExtents[0]); + } + } +} + +S32 LLVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, + S32 face, + LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent_out) +{ + S32 hit_face = -1; + + S32 start_face; + S32 end_face; + + if (face == -1) // ALL_SIDES + { + start_face = 0; + end_face = getNumVolumeFaces() - 1; + } + else + { + start_face = face; + end_face = face; + } + + LLVector4a dir; + dir.setSub(end, start); + + F32 closest_t = 2.f; // must be larger than 1 + + end_face = llmin(end_face, getNumVolumeFaces()-1); + + for (S32 i = start_face; i <= end_face; i++) + { + LLVolumeFace &face = mVolumeFaces[i]; + + LLVector4a box_center; + box_center.setAdd(face.mExtents[0], face.mExtents[1]); + box_center.mul(0.5f); + + LLVector4a box_size; + box_size.setSub(face.mExtents[1], face.mExtents[0]); if (LLLineSegmentBoxIntersect(start, end, box_center, box_size)) - { - if (tangent_out != NULL) // if the caller wants tangents, we may need to generate them - { + { + if (tangent_out != NULL) // if the caller wants tangents, we may need to generate them + { genTangents(i); - } - - if (isUnique()) - { //don't bother with an octree for flexi volumes - U32 tri_count = face.mNumIndices/3; - - for (U32 j = 0; j < tri_count; ++j) - { - U16 idx0 = face.mIndices[j*3+0]; - U16 idx1 = face.mIndices[j*3+1]; - U16 idx2 = face.mIndices[j*3+2]; - - const LLVector4a& v0 = face.mPositions[idx0]; - const LLVector4a& v1 = face.mPositions[idx1]; - const LLVector4a& v2 = face.mPositions[idx2]; - - F32 a,b,t; - - if (LLTriangleRayIntersect(v0, v1, v2, - start, dir, a, b, t)) - { - if ((t >= 0.f) && // if hit is after start - (t <= 1.f) && // and before end - (t < closest_t)) // and this hit is closer - { - closest_t = t; - hit_face = i; - - if (intersection != NULL) - { - LLVector4a intersect = dir; - intersect.mul(closest_t); - intersect.add(start); - *intersection = intersect; - } - - - if (tex_coord != NULL) - { - LLVector2* tc = (LLVector2*) face.mTexCoords; - *tex_coord = ((1.f - a - b) * tc[idx0] + - a * tc[idx1] + - b * tc[idx2]); - - } - - if (normal!= NULL) - { - LLVector4a* norm = face.mNormals; - - LLVector4a n1,n2,n3; - n1 = norm[idx0]; - n1.mul(1.f-a-b); - - n2 = norm[idx1]; - n2.mul(a); - - n3 = norm[idx2]; - n3.mul(b); - - n1.add(n2); - n1.add(n3); - - *normal = n1; - } - - if (tangent_out != NULL) - { - LLVector4a* tangents = face.mTangents; - - LLVector4a t1,t2,t3; - t1 = tangents[idx0]; - t1.mul(1.f-a-b); - - t2 = tangents[idx1]; - t2.mul(a); - - t3 = tangents[idx2]; - t3.mul(b); - - t1.add(t2); - t1.add(t3); - - *tangent_out = t1; - } - } - } - } - } - else - { + } + + if (isUnique()) + { //don't bother with an octree for flexi volumes + U32 tri_count = face.mNumIndices/3; + + for (U32 j = 0; j < tri_count; ++j) + { + U16 idx0 = face.mIndices[j*3+0]; + U16 idx1 = face.mIndices[j*3+1]; + U16 idx2 = face.mIndices[j*3+2]; + + const LLVector4a& v0 = face.mPositions[idx0]; + const LLVector4a& v1 = face.mPositions[idx1]; + const LLVector4a& v2 = face.mPositions[idx2]; + + F32 a,b,t; + + if (LLTriangleRayIntersect(v0, v1, v2, + start, dir, a, b, t)) + { + if ((t >= 0.f) && // if hit is after start + (t <= 1.f) && // and before end + (t < closest_t)) // and this hit is closer + { + closest_t = t; + hit_face = i; + + if (intersection != NULL) + { + LLVector4a intersect = dir; + intersect.mul(closest_t); + intersect.add(start); + *intersection = intersect; + } + + + if (tex_coord != NULL) + { + LLVector2* tc = (LLVector2*) face.mTexCoords; + *tex_coord = ((1.f - a - b) * tc[idx0] + + a * tc[idx1] + + b * tc[idx2]); + + } + + if (normal!= NULL) + { + LLVector4a* norm = face.mNormals; + + LLVector4a n1,n2,n3; + n1 = norm[idx0]; + n1.mul(1.f-a-b); + + n2 = norm[idx1]; + n2.mul(a); + + n3 = norm[idx2]; + n3.mul(b); + + n1.add(n2); + n1.add(n3); + + *normal = n1; + } + + if (tangent_out != NULL) + { + LLVector4a* tangents = face.mTangents; + + LLVector4a t1,t2,t3; + t1 = tangents[idx0]; + t1.mul(1.f-a-b); + + t2 = tangents[idx1]; + t2.mul(a); + + t3 = tangents[idx2]; + t3.mul(b); + + t1.add(t2); + t1.add(t3); + + *tangent_out = t1; + } + } + } + } + } + else + { if (!face.getOctree()) - { - face.createOctree(); - } - - LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, tangent_out); + { + face.createOctree(); + } + + LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, tangent_out); intersect.traverse(face.getOctree()); - if (intersect.mHitFace) - { - hit_face = i; - } - } - } - } - - - return hit_face; + if (intersect.mHitFace) + { + hit_face = i; + } + } + } + } + + + return hit_face; } class LLVertexIndexPair { public: - LLVertexIndexPair(const LLVector3 &vertex, const S32 index); + LLVertexIndexPair(const LLVector3 &vertex, const S32 index); - LLVector3 mVertex; - S32 mIndex; + LLVector3 mVertex; + S32 mIndex; }; LLVertexIndexPair::LLVertexIndexPair(const LLVector3 &vertex, const S32 index) { - mVertex = vertex; - mIndex = index; + mVertex = vertex; + mIndex = index; } constexpr F32 VERTEX_SLOP = 0.00001f; struct lessVertex { - bool operator()(const LLVertexIndexPair *a, const LLVertexIndexPair *b) - { - const F32 slop = VERTEX_SLOP; - - if (a->mVertex.mV[0] + slop < b->mVertex.mV[0]) - { - return true; - } - else if (a->mVertex.mV[0] - slop > b->mVertex.mV[0]) - { - return false; - } - - if (a->mVertex.mV[1] + slop < b->mVertex.mV[1]) - { - return true; - } - else if (a->mVertex.mV[1] - slop > b->mVertex.mV[1]) - { - return false; - } - - if (a->mVertex.mV[2] + slop < b->mVertex.mV[2]) - { - return true; - } - else if (a->mVertex.mV[2] - slop > b->mVertex.mV[2]) - { - return false; - } - - return false; - } + bool operator()(const LLVertexIndexPair *a, const LLVertexIndexPair *b) + { + const F32 slop = VERTEX_SLOP; + + if (a->mVertex.mV[0] + slop < b->mVertex.mV[0]) + { + return true; + } + else if (a->mVertex.mV[0] - slop > b->mVertex.mV[0]) + { + return false; + } + + if (a->mVertex.mV[1] + slop < b->mVertex.mV[1]) + { + return true; + } + else if (a->mVertex.mV[1] - slop > b->mVertex.mV[1]) + { + return false; + } + + if (a->mVertex.mV[2] + slop < b->mVertex.mV[2]) + { + return true; + } + else if (a->mVertex.mV[2] - slop > b->mVertex.mV[2]) + { + return false; + } + + return false; + } }; struct lessTriangle { - bool operator()(const S32 *a, const S32 *b) - { - if (*a < *b) - { - return true; - } - else if (*a > *b) - { - return false; - } - - if (*(a+1) < *(b+1)) - { - return true; - } - else if (*(a+1) > *(b+1)) - { - return false; - } - - if (*(a+2) < *(b+2)) - { - return true; - } - else if (*(a+2) > *(b+2)) - { - return false; - } - - return false; - } + bool operator()(const S32 *a, const S32 *b) + { + if (*a < *b) + { + return true; + } + else if (*a > *b) + { + return false; + } + + if (*(a+1) < *(b+1)) + { + return true; + } + else if (*(a+1) > *(b+1)) + { + return false; + } + + if (*(a+2) < *(b+2)) + { + return true; + } + else if (*(a+2) > *(b+2)) + { + return false; + } + + return false; + } }; bool equalTriangle(const S32 *a, const S32 *b) { - if ((*a == *b) && (*(a+1) == *(b+1)) && (*(a+2) == *(b+2))) - { - return true; - } - return false; + if ((*a == *b) && (*(a+1) == *(b+1)) && (*(a+2) == *(b+2))) + { + return true; + } + return false; } bool LLVolumeParams::importFile(LLFILE *fp) { - //LL_INFOS() << "importing volume" << LL_ENDL; - const S32 BUFSIZE = 16384; - char buffer[BUFSIZE]; /* Flawfinder: ignore */ - // *NOTE: changing the size or type of this buffer will require - // changing the sscanf below. - char keyword[256]; /* Flawfinder: ignore */ - keyword[0] = 0; - - while (!feof(fp)) - { - if (fgets(buffer, BUFSIZE, fp) == NULL) - { - buffer[0] = '\0'; - } - - sscanf(buffer, " %255s", keyword); /* Flawfinder: ignore */ - if (!strcmp("{", keyword)) - { - continue; - } - if (!strcmp("}",keyword)) - { - break; - } - else if (!strcmp("profile", keyword)) - { - mProfileParams.importFile(fp); - } - else if (!strcmp("path",keyword)) - { - mPathParams.importFile(fp); - } - else - { - LL_WARNS() << "unknown keyword " << keyword << " in volume import" << LL_ENDL; - } - } - - return true; + //LL_INFOS() << "importing volume" << LL_ENDL; + const S32 BUFSIZE = 16384; + char buffer[BUFSIZE]; /* Flawfinder: ignore */ + // *NOTE: changing the size or type of this buffer will require + // changing the sscanf below. + char keyword[256]; /* Flawfinder: ignore */ + keyword[0] = 0; + + while (!feof(fp)) + { + if (fgets(buffer, BUFSIZE, fp) == NULL) + { + buffer[0] = '\0'; + } + + sscanf(buffer, " %255s", keyword); /* Flawfinder: ignore */ + if (!strcmp("{", keyword)) + { + continue; + } + if (!strcmp("}",keyword)) + { + break; + } + else if (!strcmp("profile", keyword)) + { + mProfileParams.importFile(fp); + } + else if (!strcmp("path",keyword)) + { + mPathParams.importFile(fp); + } + else + { + LL_WARNS() << "unknown keyword " << keyword << " in volume import" << LL_ENDL; + } + } + + return true; } bool LLVolumeParams::exportFile(LLFILE *fp) const { - fprintf(fp,"\tshape 0\n"); - fprintf(fp,"\t{\n"); - mPathParams.exportFile(fp); - mProfileParams.exportFile(fp); - fprintf(fp, "\t}\n"); - return true; + fprintf(fp,"\tshape 0\n"); + fprintf(fp,"\t{\n"); + mPathParams.exportFile(fp); + mProfileParams.exportFile(fp); + fprintf(fp, "\t}\n"); + return true; } bool LLVolumeParams::importLegacyStream(std::istream& input_stream) { - //LL_INFOS() << "importing volume" << LL_ENDL; - const S32 BUFSIZE = 16384; - // *NOTE: changing the size or type of this buffer will require - // changing the sscanf below. - char buffer[BUFSIZE]; /* Flawfinder: ignore */ - char keyword[256]; /* Flawfinder: ignore */ - keyword[0] = 0; - - while (input_stream.good()) - { - input_stream.getline(buffer, BUFSIZE); - sscanf(buffer, " %255s", keyword); - if (!strcmp("{", keyword)) - { - continue; - } - if (!strcmp("}",keyword)) - { - break; - } - else if (!strcmp("profile", keyword)) - { - mProfileParams.importLegacyStream(input_stream); - } - else if (!strcmp("path",keyword)) - { - mPathParams.importLegacyStream(input_stream); - } - else - { - LL_WARNS() << "unknown keyword " << keyword << " in volume import" << LL_ENDL; - } - } - - return true; + //LL_INFOS() << "importing volume" << LL_ENDL; + const S32 BUFSIZE = 16384; + // *NOTE: changing the size or type of this buffer will require + // changing the sscanf below. + char buffer[BUFSIZE]; /* Flawfinder: ignore */ + char keyword[256]; /* Flawfinder: ignore */ + keyword[0] = 0; + + while (input_stream.good()) + { + input_stream.getline(buffer, BUFSIZE); + sscanf(buffer, " %255s", keyword); + if (!strcmp("{", keyword)) + { + continue; + } + if (!strcmp("}",keyword)) + { + break; + } + else if (!strcmp("profile", keyword)) + { + mProfileParams.importLegacyStream(input_stream); + } + else if (!strcmp("path",keyword)) + { + mPathParams.importLegacyStream(input_stream); + } + else + { + LL_WARNS() << "unknown keyword " << keyword << " in volume import" << LL_ENDL; + } + } + + return true; } bool LLVolumeParams::exportLegacyStream(std::ostream& output_stream) const { - output_stream <<"\tshape 0\n"; - output_stream <<"\t{\n"; - mPathParams.exportLegacyStream(output_stream); - mProfileParams.exportLegacyStream(output_stream); - output_stream << "\t}\n"; - return true; + output_stream <<"\tshape 0\n"; + output_stream <<"\t{\n"; + mPathParams.exportLegacyStream(output_stream); + mProfileParams.exportLegacyStream(output_stream); + output_stream << "\t}\n"; + return true; } LLSD LLVolumeParams::sculptAsLLSD() const { - LLSD sd = LLSD(); - sd["id"] = getSculptID(); - sd["type"] = getSculptType(); + LLSD sd = LLSD(); + sd["id"] = getSculptID(); + sd["type"] = getSculptType(); - return sd; + return sd; } bool LLVolumeParams::sculptFromLLSD(LLSD& sd) { - setSculptID(sd["id"].asUUID(), (U8)sd["type"].asInteger()); - return true; + setSculptID(sd["id"].asUUID(), (U8)sd["type"].asInteger()); + return true; } LLSD LLVolumeParams::asLLSD() const { - LLSD sd = LLSD(); - sd["path"] = mPathParams; - sd["profile"] = mProfileParams; - sd["sculpt"] = sculptAsLLSD(); - - return sd; + LLSD sd = LLSD(); + sd["path"] = mPathParams; + sd["profile"] = mProfileParams; + sd["sculpt"] = sculptAsLLSD(); + + return sd; } bool LLVolumeParams::fromLLSD(LLSD& sd) { - mPathParams.fromLLSD(sd["path"]); - mProfileParams.fromLLSD(sd["profile"]); - sculptFromLLSD(sd["sculpt"]); - - return true; + mPathParams.fromLLSD(sd["path"]); + mProfileParams.fromLLSD(sd["profile"]); + sculptFromLLSD(sd["sculpt"]); + + return true; } void LLVolumeParams::reduceS(F32 begin, F32 end) { - begin = llclampf(begin); - end = llclampf(end); - if (begin > end) - { - F32 temp = begin; - begin = end; - end = temp; - } - F32 a = mProfileParams.getBegin(); - F32 b = mProfileParams.getEnd(); - mProfileParams.setBegin(a + begin * (b - a)); - mProfileParams.setEnd(a + end * (b - a)); + begin = llclampf(begin); + end = llclampf(end); + if (begin > end) + { + F32 temp = begin; + begin = end; + end = temp; + } + F32 a = mProfileParams.getBegin(); + F32 b = mProfileParams.getEnd(); + mProfileParams.setBegin(a + begin * (b - a)); + mProfileParams.setEnd(a + end * (b - a)); } void LLVolumeParams::reduceT(F32 begin, F32 end) { - begin = llclampf(begin); - end = llclampf(end); - if (begin > end) - { - F32 temp = begin; - begin = end; - end = temp; - } - F32 a = mPathParams.getBegin(); - F32 b = mPathParams.getEnd(); - mPathParams.setBegin(a + begin * (b - a)); - mPathParams.setEnd(a + end * (b - a)); + begin = llclampf(begin); + end = llclampf(end); + if (begin > end) + { + F32 temp = begin; + begin = end; + end = temp; + } + F32 a = mPathParams.getBegin(); + F32 b = mPathParams.getEnd(); + mPathParams.setBegin(a + begin * (b - a)); + mPathParams.setEnd(a + end * (b - a)); } -const F32 MIN_CONCAVE_PROFILE_WEDGE = 0.125f; // 1/8 unity -const F32 MIN_CONCAVE_PATH_WEDGE = 0.111111f; // 1/9 unity +const F32 MIN_CONCAVE_PROFILE_WEDGE = 0.125f; // 1/8 unity +const F32 MIN_CONCAVE_PATH_WEDGE = 0.111111f; // 1/9 unity -// returns true if the shape can be approximated with a convex shape +// returns true if the shape can be approximated with a convex shape // for collison purposes bool LLVolumeParams::isConvex() const { - if (!getSculptID().isNull()) - { - // can't determine, be safe and say no: - return false; - } - - F32 path_length = mPathParams.getEnd() - mPathParams.getBegin(); - F32 hollow = mProfileParams.getHollow(); - - U8 path_type = mPathParams.getCurveType(); - if ( path_length > MIN_CONCAVE_PATH_WEDGE - && ( mPathParams.getTwist() != mPathParams.getTwistBegin() - || (hollow > 0.f - && LL_PCODE_PATH_LINE != path_type) ) ) - { - // twist along a "not too short" path is concave - return false; - } - - F32 profile_length = mProfileParams.getEnd() - mProfileParams.getBegin(); - bool same_hole = hollow == 0.f - || (mProfileParams.getCurveType() & LL_PCODE_HOLE_MASK) == LL_PCODE_HOLE_SAME; - - F32 min_profile_wedge = MIN_CONCAVE_PROFILE_WEDGE; - U8 profile_type = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; - if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type ) - { - // it is a sphere and spheres get twice the minimum profile wedge - min_profile_wedge = 2.f * MIN_CONCAVE_PROFILE_WEDGE; - } - - bool convex_profile = ( ( profile_length == 1.f - || profile_length <= 0.5f ) - && hollow == 0.f ) // trivially convex - || ( profile_length <= min_profile_wedge - && same_hole ); // effectvely convex (even when hollow) - - if (!convex_profile) - { - // profile is concave - return false; - } - - if ( LL_PCODE_PATH_LINE == path_type ) - { - // straight paths with convex profile - return true; - } - - bool concave_path = (path_length < 1.0f) && (path_length > 0.5f); - if (concave_path) - { - return false; - } - - // we're left with spheres, toroids and tubes - if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type ) - { - // at this stage all spheres must be convex - return true; - } - - // it's a toroid or tube - if ( path_length <= MIN_CONCAVE_PATH_WEDGE ) - { - // effectively convex - return true; - } - - return false; + if (!getSculptID().isNull()) + { + // can't determine, be safe and say no: + return false; + } + + F32 path_length = mPathParams.getEnd() - mPathParams.getBegin(); + F32 hollow = mProfileParams.getHollow(); + + U8 path_type = mPathParams.getCurveType(); + if ( path_length > MIN_CONCAVE_PATH_WEDGE + && ( mPathParams.getTwist() != mPathParams.getTwistBegin() + || (hollow > 0.f + && LL_PCODE_PATH_LINE != path_type) ) ) + { + // twist along a "not too short" path is concave + return false; + } + + F32 profile_length = mProfileParams.getEnd() - mProfileParams.getBegin(); + bool same_hole = hollow == 0.f + || (mProfileParams.getCurveType() & LL_PCODE_HOLE_MASK) == LL_PCODE_HOLE_SAME; + + F32 min_profile_wedge = MIN_CONCAVE_PROFILE_WEDGE; + U8 profile_type = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; + if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type ) + { + // it is a sphere and spheres get twice the minimum profile wedge + min_profile_wedge = 2.f * MIN_CONCAVE_PROFILE_WEDGE; + } + + bool convex_profile = ( ( profile_length == 1.f + || profile_length <= 0.5f ) + && hollow == 0.f ) // trivially convex + || ( profile_length <= min_profile_wedge + && same_hole ); // effectvely convex (even when hollow) + + if (!convex_profile) + { + // profile is concave + return false; + } + + if ( LL_PCODE_PATH_LINE == path_type ) + { + // straight paths with convex profile + return true; + } + + bool concave_path = (path_length < 1.0f) && (path_length > 0.5f); + if (concave_path) + { + return false; + } + + // we're left with spheres, toroids and tubes + if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type ) + { + // at this stage all spheres must be convex + return true; + } + + // it's a toroid or tube + if ( path_length <= MIN_CONCAVE_PATH_WEDGE ) + { + // effectively convex + return true; + } + + return false; } // debug void LLVolumeParams::setCube() { - mProfileParams.setCurveType(LL_PCODE_PROFILE_SQUARE); - mProfileParams.setBegin(0.f); - mProfileParams.setEnd(1.f); - mProfileParams.setHollow(0.f); + mProfileParams.setCurveType(LL_PCODE_PROFILE_SQUARE); + mProfileParams.setBegin(0.f); + mProfileParams.setEnd(1.f); + mProfileParams.setHollow(0.f); - mPathParams.setBegin(0.f); - mPathParams.setEnd(1.f); - mPathParams.setScale(1.f, 1.f); - mPathParams.setShear(0.f, 0.f); - mPathParams.setCurveType(LL_PCODE_PATH_LINE); - mPathParams.setTwistBegin(0.f); - mPathParams.setTwistEnd(0.f); - mPathParams.setRadiusOffset(0.f); - mPathParams.setTaper(0.f, 0.f); - mPathParams.setRevolutions(0.f); - mPathParams.setSkew(0.f); + mPathParams.setBegin(0.f); + mPathParams.setEnd(1.f); + mPathParams.setScale(1.f, 1.f); + mPathParams.setShear(0.f, 0.f); + mPathParams.setCurveType(LL_PCODE_PATH_LINE); + mPathParams.setTwistBegin(0.f); + mPathParams.setTwistEnd(0.f); + mPathParams.setRadiusOffset(0.f); + mPathParams.setTaper(0.f, 0.f); + mPathParams.setRevolutions(0.f); + mPathParams.setSkew(0.f); } LLFaceID LLVolume::generateFaceMask() { - LLFaceID new_mask = 0x0000; - - switch(mParams.getProfileParams().getCurveType() & LL_PCODE_PROFILE_MASK) - { - case LL_PCODE_PROFILE_CIRCLE: - case LL_PCODE_PROFILE_CIRCLE_HALF: - new_mask |= LL_FACE_OUTER_SIDE_0; - break; - case LL_PCODE_PROFILE_SQUARE: - { - for(S32 side = (S32)(mParams.getProfileParams().getBegin() * 4.f); side < llceil(mParams.getProfileParams().getEnd() * 4.f); side++) - { - new_mask |= LL_FACE_OUTER_SIDE_0 << side; - } - } - break; - case LL_PCODE_PROFILE_ISOTRI: - case LL_PCODE_PROFILE_EQUALTRI: - case LL_PCODE_PROFILE_RIGHTTRI: - { - for(S32 side = (S32)(mParams.getProfileParams().getBegin() * 3.f); side < llceil(mParams.getProfileParams().getEnd() * 3.f); side++) - { - new_mask |= LL_FACE_OUTER_SIDE_0 << side; - } - } - break; - default: - LL_ERRS() << "Unknown profile!" << LL_ENDL; - break; - } - - // handle hollow objects - if (mParams.getProfileParams().getHollow() > 0) - { - new_mask |= LL_FACE_INNER_SIDE; - } - - // handle open profile curves - if (mProfilep->isOpen()) - { - new_mask |= LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END; - } - - // handle open path curves - if (mPathp->isOpen()) - { - new_mask |= LL_FACE_PATH_BEGIN | LL_FACE_PATH_END; - } - - return new_mask; + LLFaceID new_mask = 0x0000; + + switch(mParams.getProfileParams().getCurveType() & LL_PCODE_PROFILE_MASK) + { + case LL_PCODE_PROFILE_CIRCLE: + case LL_PCODE_PROFILE_CIRCLE_HALF: + new_mask |= LL_FACE_OUTER_SIDE_0; + break; + case LL_PCODE_PROFILE_SQUARE: + { + for(S32 side = (S32)(mParams.getProfileParams().getBegin() * 4.f); side < llceil(mParams.getProfileParams().getEnd() * 4.f); side++) + { + new_mask |= LL_FACE_OUTER_SIDE_0 << side; + } + } + break; + case LL_PCODE_PROFILE_ISOTRI: + case LL_PCODE_PROFILE_EQUALTRI: + case LL_PCODE_PROFILE_RIGHTTRI: + { + for(S32 side = (S32)(mParams.getProfileParams().getBegin() * 3.f); side < llceil(mParams.getProfileParams().getEnd() * 3.f); side++) + { + new_mask |= LL_FACE_OUTER_SIDE_0 << side; + } + } + break; + default: + LL_ERRS() << "Unknown profile!" << LL_ENDL; + break; + } + + // handle hollow objects + if (mParams.getProfileParams().getHollow() > 0) + { + new_mask |= LL_FACE_INNER_SIDE; + } + + // handle open profile curves + if (mProfilep->isOpen()) + { + new_mask |= LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END; + } + + // handle open path curves + if (mPathp->isOpen()) + { + new_mask |= LL_FACE_PATH_BEGIN | LL_FACE_PATH_END; + } + + return new_mask; } bool LLVolume::isFaceMaskValid(LLFaceID face_mask) { - LLFaceID test_mask = 0; - for(S32 i = 0; i < getNumFaces(); i++) - { - test_mask |= mProfilep->mFaces[i].mFaceID; - } + LLFaceID test_mask = 0; + for(S32 i = 0; i < getNumFaces(); i++) + { + test_mask |= mProfilep->mFaces[i].mFaceID; + } - return test_mask == face_mask; + return test_mask == face_mask; } bool LLVolume::isConvex() const { - // mParams.isConvex() may return false even though the final - // geometry is actually convex due to LOD approximations. - // TODO -- provide LLPath and LLProfile with isConvex() methods - // that correctly determine convexity. -- Leviathan - return mParams.isConvex(); + // mParams.isConvex() may return false even though the final + // geometry is actually convex due to LOD approximations. + // TODO -- provide LLPath and LLProfile with isConvex() methods + // that correctly determine convexity. -- Leviathan + return mParams.isConvex(); } std::ostream& operator<<(std::ostream &s, const LLProfileParams &profile_params) { - s << "{type=" << (U32) profile_params.mCurveType; - s << ", begin=" << profile_params.mBegin; - s << ", end=" << profile_params.mEnd; - s << ", hollow=" << profile_params.mHollow; - s << "}"; - return s; + s << "{type=" << (U32) profile_params.mCurveType; + s << ", begin=" << profile_params.mBegin; + s << ", end=" << profile_params.mEnd; + s << ", hollow=" << profile_params.mHollow; + s << "}"; + return s; } std::ostream& operator<<(std::ostream &s, const LLPathParams &path_params) { - s << "{type=" << (U32) path_params.mCurveType; - s << ", begin=" << path_params.mBegin; - s << ", end=" << path_params.mEnd; - s << ", twist=" << path_params.mTwistEnd; - s << ", scale=" << path_params.mScale; - s << ", shear=" << path_params.mShear; - s << ", twist_begin=" << path_params.mTwistBegin; - s << ", radius_offset=" << path_params.mRadiusOffset; - s << ", taper=" << path_params.mTaper; - s << ", revolutions=" << path_params.mRevolutions; - s << ", skew=" << path_params.mSkew; - s << "}"; - return s; + s << "{type=" << (U32) path_params.mCurveType; + s << ", begin=" << path_params.mBegin; + s << ", end=" << path_params.mEnd; + s << ", twist=" << path_params.mTwistEnd; + s << ", scale=" << path_params.mScale; + s << ", shear=" << path_params.mShear; + s << ", twist_begin=" << path_params.mTwistBegin; + s << ", radius_offset=" << path_params.mRadiusOffset; + s << ", taper=" << path_params.mTaper; + s << ", revolutions=" << path_params.mRevolutions; + s << ", skew=" << path_params.mSkew; + s << "}"; + return s; } std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params) { - s << "{profileparams = " << volume_params.mProfileParams; - s << ", pathparams = " << volume_params.mPathParams; - s << "}"; - return s; + s << "{profileparams = " << volume_params.mProfileParams; + s << ", pathparams = " << volume_params.mPathParams; + s << "}"; + return s; } std::ostream& operator<<(std::ostream &s, const LLProfile &profile) { - s << " {open=" << (U32) profile.mOpen; - s << ", dirty=" << profile.mDirty; - s << ", totalout=" << profile.mTotalOut; - s << ", total=" << profile.mTotal; - s << "}"; - return s; + s << " {open=" << (U32) profile.mOpen; + s << ", dirty=" << profile.mDirty; + s << ", totalout=" << profile.mTotalOut; + s << ", total=" << profile.mTotal; + s << "}"; + return s; } std::ostream& operator<<(std::ostream &s, const LLPath &path) { - s << "{open=" << (U32) path.mOpen; - s << ", dirty=" << path.mDirty; - s << ", step=" << path.mStep; - s << ", total=" << path.mTotal; - s << "}"; - return s; + s << "{open=" << (U32) path.mOpen; + s << ", dirty=" << path.mDirty; + s << ", step=" << path.mStep; + s << ", total=" << path.mTotal; + s << "}"; + return s; } std::ostream& operator<<(std::ostream &s, const LLVolume &volume) { - s << "{params = " << volume.getParams(); - s << ", path = " << *volume.mPathp; - s << ", profile = " << *volume.mProfilep; - s << "}"; - return s; + s << "{params = " << volume.getParams(); + s << ", path = " << *volume.mPathp; + s << ", profile = " << *volume.mProfilep; + s << "}"; + return s; } std::ostream& operator<<(std::ostream &s, const LLVolume *volumep) { - s << "{params = " << volumep->getParams(); - s << ", path = " << *(volumep->mPathp); - s << ", profile = " << *(volumep->mProfilep); - s << "}"; - return s; -} - -LLVolumeFace::LLVolumeFace() : - mID(0), - mTypeMask(0), - mBeginS(0), - mBeginT(0), - mNumS(0), - mNumT(0), - mNumVertices(0), - mNumAllocatedVertices(0), - mNumIndices(0), - mPositions(NULL), - mNormals(NULL), - mTangents(NULL), - mTexCoords(NULL), - mIndices(NULL), - mWeights(NULL), + s << "{params = " << volumep->getParams(); + s << ", path = " << *(volumep->mPathp); + s << ", profile = " << *(volumep->mProfilep); + s << "}"; + return s; +} + +LLVolumeFace::LLVolumeFace() : + mID(0), + mTypeMask(0), + mBeginS(0), + mBeginT(0), + mNumS(0), + mNumT(0), + mNumVertices(0), + mNumAllocatedVertices(0), + mNumIndices(0), + mPositions(NULL), + mNormals(NULL), + mTangents(NULL), + mTexCoords(NULL), + mIndices(NULL), + mWeights(NULL), #if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS mJustWeights(NULL), mJointIndices(NULL), #endif mWeightsScrubbed(false), - mOctree(NULL), + mOctree(NULL), mOctreeTriangles(NULL), - mOptimized(false) + mOptimized(false) { - mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3); - mExtents[0].splat(-0.5f); - mExtents[1].splat(0.5f); - mCenter = mExtents+2; + mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3); + mExtents[0].splat(-0.5f); + mExtents[1].splat(0.5f); + mCenter = mExtents+2; } LLVolumeFace::LLVolumeFace(const LLVolumeFace& src) -: mID(0), - mTypeMask(0), - mBeginS(0), - mBeginT(0), - mNumS(0), - mNumT(0), - mNumVertices(0), - mNumAllocatedVertices(0), - mNumIndices(0), - mPositions(NULL), - mNormals(NULL), - mTangents(NULL), - mTexCoords(NULL), - mIndices(NULL), - mWeights(NULL), +: mID(0), + mTypeMask(0), + mBeginS(0), + mBeginT(0), + mNumS(0), + mNumT(0), + mNumVertices(0), + mNumAllocatedVertices(0), + mNumIndices(0), + mPositions(NULL), + mNormals(NULL), + mTangents(NULL), + mTexCoords(NULL), + mIndices(NULL), + mWeights(NULL), #if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS mJustWeights(NULL), mJointIndices(NULL), @@ -4725,78 +4725,78 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src) mOctree(NULL), mOctreeTriangles(NULL) { - mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3); - mCenter = mExtents+2; - *this = src; + mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3); + mCenter = mExtents+2; + *this = src; } LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src) { - if (&src == this) - { //self assignment, do nothing - return *this; - } - - mID = src.mID; - mTypeMask = src.mTypeMask; - mBeginS = src.mBeginS; - mBeginT = src.mBeginT; - mNumS = src.mNumS; - mNumT = src.mNumT; - - mExtents[0] = src.mExtents[0]; - mExtents[1] = src.mExtents[1]; - *mCenter = *src.mCenter; - - mNumVertices = 0; - mNumIndices = 0; - - freeData(); - - resizeVertices(src.mNumVertices); - resizeIndices(src.mNumIndices); - - if (mNumVertices) - { - S32 vert_size = mNumVertices*sizeof(LLVector4a); - S32 tc_size = (mNumVertices*sizeof(LLVector2)+0xF) & ~0xF; - - LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) src.mPositions, vert_size); - - if (src.mNormals) - { - LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) src.mNormals, vert_size); - } - - if(src.mTexCoords) - { - LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size); - } - - if (src.mTangents) - { - allocateTangents(src.mNumVertices); - LLVector4a::memcpyNonAliased16((F32*) mTangents, (F32*) src.mTangents, vert_size); - } - else - { - ll_aligned_free_16(mTangents); - mTangents = NULL; - } - - if (src.mWeights) - { + if (&src == this) + { //self assignment, do nothing + return *this; + } + + mID = src.mID; + mTypeMask = src.mTypeMask; + mBeginS = src.mBeginS; + mBeginT = src.mBeginT; + mNumS = src.mNumS; + mNumT = src.mNumT; + + mExtents[0] = src.mExtents[0]; + mExtents[1] = src.mExtents[1]; + *mCenter = *src.mCenter; + + mNumVertices = 0; + mNumIndices = 0; + + freeData(); + + resizeVertices(src.mNumVertices); + resizeIndices(src.mNumIndices); + + if (mNumVertices) + { + S32 vert_size = mNumVertices*sizeof(LLVector4a); + S32 tc_size = (mNumVertices*sizeof(LLVector2)+0xF) & ~0xF; + + LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) src.mPositions, vert_size); + + if (src.mNormals) + { + LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) src.mNormals, vert_size); + } + + if(src.mTexCoords) + { + LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size); + } + + if (src.mTangents) + { + allocateTangents(src.mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mTangents, (F32*) src.mTangents, vert_size); + } + else + { + ll_aligned_free_16(mTangents); + mTangents = NULL; + } + + if (src.mWeights) + { llassert(!mWeights); // don't orphan an old alloc here accidentally - allocateWeights(src.mNumVertices); - LLVector4a::memcpyNonAliased16((F32*) mWeights, (F32*) src.mWeights, vert_size); + allocateWeights(src.mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mWeights, (F32*) src.mWeights, vert_size); mWeightsScrubbed = src.mWeightsScrubbed; - } - else - { - ll_aligned_free_16(mWeights); - mWeights = NULL; + } + else + { + ll_aligned_free_16(mWeights); + mWeights = NULL; mWeightsScrubbed = false; - } + } #if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS if (src.mJointIndices) @@ -4809,60 +4809,60 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src) { ll_aligned_free_16(mJointIndices); mJointIndices = NULL; - } + } #endif - } - - if (mNumIndices) - { - S32 idx_size = (mNumIndices*sizeof(U16)+0xF) & ~0xF; - - LLVector4a::memcpyNonAliased16((F32*) mIndices, (F32*) src.mIndices, idx_size); - } - else + } + + if (mNumIndices) + { + S32 idx_size = (mNumIndices*sizeof(U16)+0xF) & ~0xF; + + LLVector4a::memcpyNonAliased16((F32*) mIndices, (F32*) src.mIndices, idx_size); + } + else { ll_aligned_free_16(mIndices); mIndices = NULL; } - mOptimized = src.mOptimized; + mOptimized = src.mOptimized; mNormalizedScale = src.mNormalizedScale; - //delete - return *this; + //delete + return *this; } LLVolumeFace::~LLVolumeFace() { - ll_aligned_free_16(mExtents); - mExtents = NULL; - mCenter = NULL; + ll_aligned_free_16(mExtents); + mExtents = NULL; + mCenter = NULL; - freeData(); + freeData(); } void LLVolumeFace::freeData() { - ll_aligned_free<64>(mPositions); - mPositions = NULL; + ll_aligned_free<64>(mPositions); + mPositions = NULL; - //normals and texture coordinates are part of the same buffer as mPositions, do not free them separately - mNormals = NULL; - mTexCoords = NULL; + //normals and texture coordinates are part of the same buffer as mPositions, do not free them separately + mNormals = NULL; + mTexCoords = NULL; - ll_aligned_free_16(mIndices); - mIndices = NULL; - ll_aligned_free_16(mTangents); - mTangents = NULL; - ll_aligned_free_16(mWeights); - mWeights = NULL; + ll_aligned_free_16(mIndices); + mIndices = NULL; + ll_aligned_free_16(mTangents); + mTangents = NULL; + ll_aligned_free_16(mWeights); + mWeights = NULL; #if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS ll_aligned_free_16(mJointIndices); - mJointIndices = NULL; + mJointIndices = NULL; ll_aligned_free_16(mJustWeights); - mJustWeights = NULL; + mJustWeights = NULL; #endif destroyOctree(); @@ -4870,73 +4870,73 @@ void LLVolumeFace::freeData() bool LLVolumeFace::create(LLVolume* volume, bool partial_build) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME - //tree for this face is no longer valid + //tree for this face is no longer valid destroyOctree(); - LL_CHECK_MEMORY - bool ret = false ; - if (mTypeMask & CAP_MASK) - { - ret = createCap(volume, partial_build); - LL_CHECK_MEMORY - } - else if ((mTypeMask & END_MASK) || (mTypeMask & SIDE_MASK)) - { - ret = createSide(volume, partial_build); - LL_CHECK_MEMORY - } - else - { - LL_ERRS() << "Unknown/uninitialized face type!" << LL_ENDL; - } - - return ret ; + LL_CHECK_MEMORY + bool ret = false ; + if (mTypeMask & CAP_MASK) + { + ret = createCap(volume, partial_build); + LL_CHECK_MEMORY + } + else if ((mTypeMask & END_MASK) || (mTypeMask & SIDE_MASK)) + { + ret = createSide(volume, partial_build); + LL_CHECK_MEMORY + } + else + { + LL_ERRS() << "Unknown/uninitialized face type!" << LL_ENDL; + } + + return ret ; } void LLVolumeFace::getVertexData(U16 index, LLVolumeFace::VertexData& cv) { - cv.setPosition(mPositions[index]); - if (mNormals) - { - cv.setNormal(mNormals[index]); - } - else - { - cv.getNormal().clear(); - } - - if (mTexCoords) - { - cv.mTexCoord = mTexCoords[index]; - } - else - { - cv.mTexCoord.clear(); - } + cv.setPosition(mPositions[index]); + if (mNormals) + { + cv.setNormal(mNormals[index]); + } + else + { + cv.getNormal().clear(); + } + + if (mTexCoords) + { + cv.mTexCoord = mTexCoords[index]; + } + else + { + cv.mTexCoord.clear(); + } } bool LLVolumeFace::VertexMapData::operator==(const LLVolumeFace::VertexData& rhs) const { - return getPosition().equals3(rhs.getPosition()) && - mTexCoord == rhs.mTexCoord && - getNormal().equals3(rhs.getNormal()); + return getPosition().equals3(rhs.getPosition()) && + mTexCoord == rhs.mTexCoord && + getNormal().equals3(rhs.getNormal()); } bool LLVolumeFace::VertexMapData::ComparePosition::operator()(const LLVector3& a, const LLVector3& b) const { - if (a.mV[0] != b.mV[0]) - { - return a.mV[0] < b.mV[0]; - } - - if (a.mV[1] != b.mV[1]) - { - return a.mV[1] < b.mV[1]; - } - - return a.mV[2] < b.mV[2]; + if (a.mV[0] != b.mV[0]) + { + return a.mV[0] < b.mV[0]; + } + + if (a.mV[1] != b.mV[1]) + { + return a.mV[1] < b.mV[1]; + } + + return a.mV[2] < b.mV[2]; } void LLVolumeFace::remap() @@ -4985,18 +4985,18 @@ void LLVolumeFace::remap() void LLVolumeFace::optimize(F32 angle_cutoff) { - LLVolumeFace new_face; + LLVolumeFace new_face; - //map of points to vector of vertices at that point - std::map<U64, std::vector<VertexMapData> > point_map; + //map of points to vector of vertices at that point + std::map<U64, std::vector<VertexMapData> > point_map; - LLVector4a range; - range.setSub(mExtents[1],mExtents[0]); + LLVector4a range; + range.setSub(mExtents[1],mExtents[0]); - //remove redundant vertices - for (U32 i = 0; i < mNumIndices; ++i) - { - U16 index = mIndices[i]; + //remove redundant vertices + for (U32 i = 0; i < mNumIndices; ++i) + { + U16 index = mIndices[i]; if (index >= mNumVertices) { @@ -5009,81 +5009,81 @@ void LLVolumeFace::optimize(F32 angle_cutoff) LL_DEBUGS_ONCE("LLVOLUME") << "Invalid index, substituting" << LL_ENDL; } - LLVolumeFace::VertexData cv; - getVertexData(index, cv); - - bool found = false; - - LLVector4a pos; - pos.setSub(mPositions[index], mExtents[0]); - pos.div(range); - - U64 pos64 = 0; - - pos64 = (U16) (pos[0]*65535); - pos64 = pos64 | (((U64) (pos[1]*65535)) << 16); - pos64 = pos64 | (((U64) (pos[2]*65535)) << 32); - - std::map<U64, std::vector<VertexMapData> >::iterator point_iter = point_map.find(pos64); - - if (point_iter != point_map.end()) - { //duplicate point might exist - for (U32 j = 0; j < point_iter->second.size(); ++j) - { - LLVolumeFace::VertexData& tv = (point_iter->second)[j]; - if (tv.compareNormal(cv, angle_cutoff)) - { - found = true; - new_face.pushIndex((point_iter->second)[j].mIndex); - break; - } - } - } - - if (!found) - { - new_face.pushVertex(cv); - U16 index = (U16) new_face.mNumVertices-1; - new_face.pushIndex(index); - - VertexMapData d; - d.setPosition(cv.getPosition()); - d.mTexCoord = cv.mTexCoord; - d.setNormal(cv.getNormal()); - d.mIndex = index; - if (point_iter != point_map.end()) - { - point_iter->second.push_back(d); - } - else - { - point_map[pos64].push_back(d); - } - } - } - - - if (angle_cutoff > 1.f && !mNormals) - { - // Now alloc'd with positions - //ll_aligned_free_16(new_face.mNormals); - new_face.mNormals = NULL; - } - - if (!mTexCoords) - { - // Now alloc'd with positions - //ll_aligned_free_16(new_face.mTexCoords); - new_face.mTexCoords = NULL; - } - - // Only swap data if we've actually optimized the mesh - // - if (new_face.mNumVertices <= mNumVertices) - { + LLVolumeFace::VertexData cv; + getVertexData(index, cv); + + bool found = false; + + LLVector4a pos; + pos.setSub(mPositions[index], mExtents[0]); + pos.div(range); + + U64 pos64 = 0; + + pos64 = (U16) (pos[0]*65535); + pos64 = pos64 | (((U64) (pos[1]*65535)) << 16); + pos64 = pos64 | (((U64) (pos[2]*65535)) << 32); + + std::map<U64, std::vector<VertexMapData> >::iterator point_iter = point_map.find(pos64); + + if (point_iter != point_map.end()) + { //duplicate point might exist + for (U32 j = 0; j < point_iter->second.size(); ++j) + { + LLVolumeFace::VertexData& tv = (point_iter->second)[j]; + if (tv.compareNormal(cv, angle_cutoff)) + { + found = true; + new_face.pushIndex((point_iter->second)[j].mIndex); + break; + } + } + } + + if (!found) + { + new_face.pushVertex(cv); + U16 index = (U16) new_face.mNumVertices-1; + new_face.pushIndex(index); + + VertexMapData d; + d.setPosition(cv.getPosition()); + d.mTexCoord = cv.mTexCoord; + d.setNormal(cv.getNormal()); + d.mIndex = index; + if (point_iter != point_map.end()) + { + point_iter->second.push_back(d); + } + else + { + point_map[pos64].push_back(d); + } + } + } + + + if (angle_cutoff > 1.f && !mNormals) + { + // Now alloc'd with positions + //ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!mTexCoords) + { + // Now alloc'd with positions + //ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + + // Only swap data if we've actually optimized the mesh + // + if (new_face.mNumVertices <= mNumVertices) + { llassert(new_face.mNumIndices == mNumIndices); - swapData(new_face); - } + swapData(new_face); + } } @@ -5092,52 +5092,52 @@ class LLVCacheTriangleData; class LLVCacheVertexData { public: - S32 mIdx; - S32 mCacheTag; - F64 mScore; - U32 mActiveTriangles; - std::vector<LLVCacheTriangleData*> mTriangles; - - LLVCacheVertexData() - { - mCacheTag = -1; - mScore = 0.0; - mActiveTriangles = 0; - mIdx = -1; - } + S32 mIdx; + S32 mCacheTag; + F64 mScore; + U32 mActiveTriangles; + std::vector<LLVCacheTriangleData*> mTriangles; + + LLVCacheVertexData() + { + mCacheTag = -1; + mScore = 0.0; + mActiveTriangles = 0; + mIdx = -1; + } }; class LLVCacheTriangleData { public: - bool mActive; - F64 mScore; - LLVCacheVertexData* mVertex[3]; - - LLVCacheTriangleData() - { - mActive = true; - mScore = 0.0; - mVertex[0] = mVertex[1] = mVertex[2] = NULL; - } - - void complete() - { - mActive = false; - for (S32 i = 0; i < 3; ++i) - { - if (mVertex[i]) - { - llassert(mVertex[i]->mActiveTriangles > 0); - mVertex[i]->mActiveTriangles--; - } - } - } - - bool operator<(const LLVCacheTriangleData& rhs) const - { //highest score first - return rhs.mScore < mScore; - } + bool mActive; + F64 mScore; + LLVCacheVertexData* mVertex[3]; + + LLVCacheTriangleData() + { + mActive = true; + mScore = 0.0; + mVertex[0] = mVertex[1] = mVertex[2] = NULL; + } + + void complete() + { + mActive = false; + for (S32 i = 0; i < 3; ++i) + { + if (mVertex[i]) + { + llassert(mVertex[i]->mActiveTriangles > 0); + mVertex[i]->mActiveTriangles--; + } + } + } + + bool operator<(const LLVCacheTriangleData& rhs) const + { //highest score first + return rhs.mScore < mScore; + } }; constexpr F64 FindVertexScore_CacheDecayPower = 1.5; @@ -5149,205 +5149,205 @@ constexpr F64 FindVertexScore_Scaler = 1.0/(MaxSizeVertexCache-3); F64 find_vertex_score(LLVCacheVertexData& data) { - F64 score = -1.0; + F64 score = -1.0; - score = 0.0; + score = 0.0; - S32 cache_idx = data.mCacheTag; + S32 cache_idx = data.mCacheTag; - if (cache_idx < 0) - { - //not in cache - } - else - { - if (cache_idx < 3) - { //vertex was in the last triangle - score = FindVertexScore_LastTriScore; - } - else - { //more points for being higher in the cache - score = 1.0-((cache_idx-3)*FindVertexScore_Scaler); - score = pow(score, FindVertexScore_CacheDecayPower); - } - } + if (cache_idx < 0) + { + //not in cache + } + else + { + if (cache_idx < 3) + { //vertex was in the last triangle + score = FindVertexScore_LastTriScore; + } + else + { //more points for being higher in the cache + score = 1.0-((cache_idx-3)*FindVertexScore_Scaler); + score = pow(score, FindVertexScore_CacheDecayPower); + } + } - //bonus points for having low valence - F64 valence_boost = pow((F64)data.mActiveTriangles, -FindVertexScore_ValenceBoostPower); - score += FindVertexScore_ValenceBoostScale * valence_boost; + //bonus points for having low valence + F64 valence_boost = pow((F64)data.mActiveTriangles, -FindVertexScore_ValenceBoostPower); + score += FindVertexScore_ValenceBoostScale * valence_boost; - return score; + return score; } class LLVCacheFIFO { public: - LLVCacheVertexData* mCache[MaxSizeVertexCache]; - U32 mMisses; - - LLVCacheFIFO() - { - mMisses = 0; - for (U32 i = 0; i < MaxSizeVertexCache; ++i) - { - mCache[i] = NULL; - } - } - - void addVertex(LLVCacheVertexData* data) - { - if (data->mCacheTag == -1) - { - mMisses++; - - S32 end = MaxSizeVertexCache-1; - - if (mCache[end]) - { - mCache[end]->mCacheTag = -1; - } - - for (S32 i = end; i > 0; --i) - { - mCache[i] = mCache[i-1]; - if (mCache[i]) - { - mCache[i]->mCacheTag = i; - } - } - - mCache[0] = data; - data->mCacheTag = 0; - } - } + LLVCacheVertexData* mCache[MaxSizeVertexCache]; + U32 mMisses; + + LLVCacheFIFO() + { + mMisses = 0; + for (U32 i = 0; i < MaxSizeVertexCache; ++i) + { + mCache[i] = NULL; + } + } + + void addVertex(LLVCacheVertexData* data) + { + if (data->mCacheTag == -1) + { + mMisses++; + + S32 end = MaxSizeVertexCache-1; + + if (mCache[end]) + { + mCache[end]->mCacheTag = -1; + } + + for (S32 i = end; i > 0; --i) + { + mCache[i] = mCache[i-1]; + if (mCache[i]) + { + mCache[i]->mCacheTag = i; + } + } + + mCache[0] = data; + data->mCacheTag = 0; + } + } }; class LLVCacheLRU { public: - LLVCacheVertexData* mCache[MaxSizeVertexCache+3]; - - LLVCacheTriangleData* mBestTriangle; - - U32 mMisses; - - LLVCacheLRU() - { - for (U32 i = 0; i < MaxSizeVertexCache+3; ++i) - { - mCache[i] = NULL; - } - - mBestTriangle = NULL; - mMisses = 0; - } - - void addVertex(LLVCacheVertexData* data) - { - S32 end = MaxSizeVertexCache+2; - if (data->mCacheTag != -1) - { //just moving a vertex to the front of the cache - end = data->mCacheTag; - } - else - { - mMisses++; - if (mCache[end]) - { //adding a new vertex, vertex at end of cache falls off - mCache[end]->mCacheTag = -1; - } - } - - for (S32 i = end; i > 0; --i) - { //adjust cache pointers and tags - mCache[i] = mCache[i-1]; - - if (mCache[i]) - { - mCache[i]->mCacheTag = i; - } - } - - mCache[0] = data; - mCache[0]->mCacheTag = 0; - } - - void addTriangle(LLVCacheTriangleData* data) - { - addVertex(data->mVertex[0]); - addVertex(data->mVertex[1]); - addVertex(data->mVertex[2]); - } - - void updateScores() - { - LLVCacheVertexData** data_iter = mCache+MaxSizeVertexCache; - LLVCacheVertexData** end_data = mCache+MaxSizeVertexCache+3; - - while(data_iter != end_data) - { - LLVCacheVertexData* data = *data_iter++; - //trailing 3 vertices aren't actually in the cache for scoring purposes - if (data) - { - data->mCacheTag = -1; - } - } - - data_iter = mCache; - end_data = mCache+MaxSizeVertexCache; - - while (data_iter != end_data) - { //update scores of vertices in cache - LLVCacheVertexData* data = *data_iter++; - if (data) - { - data->mScore = find_vertex_score(*data); - } - } - - mBestTriangle = NULL; - //update triangle scores - data_iter = mCache; - end_data = mCache+MaxSizeVertexCache+3; - - while (data_iter != end_data) - { - LLVCacheVertexData* data = *data_iter++; - if (data) - { - for (std::vector<LLVCacheTriangleData*>::iterator iter = data->mTriangles.begin(), end_iter = data->mTriangles.end(); iter != end_iter; ++iter) - { - LLVCacheTriangleData* tri = *iter; - if (tri->mActive) - { - tri->mScore = tri->mVertex[0] ? tri->mVertex[0]->mScore : 0; - tri->mScore += tri->mVertex[1] ? tri->mVertex[1]->mScore : 0; - tri->mScore += tri->mVertex[2] ? tri->mVertex[2]->mScore : 0; - - if (!mBestTriangle || mBestTriangle->mScore < tri->mScore) - { - mBestTriangle = tri; - } - } - } - } - } - - //knock trailing 3 vertices off the cache - data_iter = mCache+MaxSizeVertexCache; - end_data = mCache+MaxSizeVertexCache+3; - while (data_iter != end_data) - { - LLVCacheVertexData* data = *data_iter; - if (data) - { - llassert(data->mCacheTag == -1); - *data_iter = NULL; - } - ++data_iter; - } - } + LLVCacheVertexData* mCache[MaxSizeVertexCache+3]; + + LLVCacheTriangleData* mBestTriangle; + + U32 mMisses; + + LLVCacheLRU() + { + for (U32 i = 0; i < MaxSizeVertexCache+3; ++i) + { + mCache[i] = NULL; + } + + mBestTriangle = NULL; + mMisses = 0; + } + + void addVertex(LLVCacheVertexData* data) + { + S32 end = MaxSizeVertexCache+2; + if (data->mCacheTag != -1) + { //just moving a vertex to the front of the cache + end = data->mCacheTag; + } + else + { + mMisses++; + if (mCache[end]) + { //adding a new vertex, vertex at end of cache falls off + mCache[end]->mCacheTag = -1; + } + } + + for (S32 i = end; i > 0; --i) + { //adjust cache pointers and tags + mCache[i] = mCache[i-1]; + + if (mCache[i]) + { + mCache[i]->mCacheTag = i; + } + } + + mCache[0] = data; + mCache[0]->mCacheTag = 0; + } + + void addTriangle(LLVCacheTriangleData* data) + { + addVertex(data->mVertex[0]); + addVertex(data->mVertex[1]); + addVertex(data->mVertex[2]); + } + + void updateScores() + { + LLVCacheVertexData** data_iter = mCache+MaxSizeVertexCache; + LLVCacheVertexData** end_data = mCache+MaxSizeVertexCache+3; + + while(data_iter != end_data) + { + LLVCacheVertexData* data = *data_iter++; + //trailing 3 vertices aren't actually in the cache for scoring purposes + if (data) + { + data->mCacheTag = -1; + } + } + + data_iter = mCache; + end_data = mCache+MaxSizeVertexCache; + + while (data_iter != end_data) + { //update scores of vertices in cache + LLVCacheVertexData* data = *data_iter++; + if (data) + { + data->mScore = find_vertex_score(*data); + } + } + + mBestTriangle = NULL; + //update triangle scores + data_iter = mCache; + end_data = mCache+MaxSizeVertexCache+3; + + while (data_iter != end_data) + { + LLVCacheVertexData* data = *data_iter++; + if (data) + { + for (std::vector<LLVCacheTriangleData*>::iterator iter = data->mTriangles.begin(), end_iter = data->mTriangles.end(); iter != end_iter; ++iter) + { + LLVCacheTriangleData* tri = *iter; + if (tri->mActive) + { + tri->mScore = tri->mVertex[0] ? tri->mVertex[0]->mScore : 0; + tri->mScore += tri->mVertex[1] ? tri->mVertex[1]->mScore : 0; + tri->mScore += tri->mVertex[2] ? tri->mVertex[2]->mScore : 0; + + if (!mBestTriangle || mBestTriangle->mScore < tri->mScore) + { + mBestTriangle = tri; + } + } + } + } + } + + //knock trailing 3 vertices off the cache + data_iter = mCache+MaxSizeVertexCache; + end_data = mCache+MaxSizeVertexCache+3; + while (data_iter != end_data) + { + LLVCacheVertexData* data = *data_iter; + if (data) + { + llassert(data->mCacheTag == -1); + *data_iter = NULL; + } + ++data_iter; + } + } }; // data structures for tangent generation @@ -5378,7 +5378,7 @@ struct MikktData LLVector3 inv_scale(1.f / face->mNormalizedScale.mV[0], 1.f / face->mNormalizedScale.mV[1], 1.f / face->mNormalizedScale.mV[2]); - + for (int i = 0; i < face->mNumIndices; ++i) { @@ -5409,54 +5409,54 @@ struct MikktData } } - uint32_t GetNumFaces() - { - return uint32_t(face->mNumIndices / 3); - } - - uint32_t GetNumVerticesOfFace(const uint32_t face_num) - { - return 3; - } - - mikk::float3 GetPosition(const uint32_t face_num, const uint32_t vert_num) - { - F32* v = p[face_num * 3 + vert_num].mV; - return mikk::float3(v); - } - - mikk::float3 GetTexCoord(const uint32_t face_num, const uint32_t vert_num) - { - F32* uv = tc[face_num * 3 + vert_num].mV; - return mikk::float3(uv[0], uv[1], 1.0f); - } - - mikk::float3 GetNormal(const uint32_t face_num, const uint32_t vert_num) - { - F32* normal = n[face_num * 3 + vert_num].mV; - return mikk::float3(normal); - } - - void SetTangentSpace(const uint32_t face_num, const uint32_t vert_num, mikk::float3 T, bool orientation) - { - S32 i = face_num * 3 + vert_num; - t[i].set(T.x, T.y, T.z, orientation ? 1.0f : -1.0f); - } + uint32_t GetNumFaces() + { + return uint32_t(face->mNumIndices / 3); + } + + uint32_t GetNumVerticesOfFace(const uint32_t face_num) + { + return 3; + } + + mikk::float3 GetPosition(const uint32_t face_num, const uint32_t vert_num) + { + F32* v = p[face_num * 3 + vert_num].mV; + return mikk::float3(v); + } + + mikk::float3 GetTexCoord(const uint32_t face_num, const uint32_t vert_num) + { + F32* uv = tc[face_num * 3 + vert_num].mV; + return mikk::float3(uv[0], uv[1], 1.0f); + } + + mikk::float3 GetNormal(const uint32_t face_num, const uint32_t vert_num) + { + F32* normal = n[face_num * 3 + vert_num].mV; + return mikk::float3(normal); + } + + void SetTangentSpace(const uint32_t face_num, const uint32_t vert_num, mikk::float3 T, bool orientation) + { + S32 i = face_num * 3 + vert_num; + t[i].set(T.x, T.y, T.z, orientation ? 1.0f : -1.0f); + } }; bool LLVolumeFace::cacheOptimize(bool gen_tangents) -{ //optimize for vertex cache according to Forsyth method: +{ //optimize for vertex cache according to Forsyth method: LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; - llassert(!mOptimized); - mOptimized = true; + llassert(!mOptimized); + mOptimized = true; if (gen_tangents && mNormals && mTexCoords) { // generate mikkt space tangents before cache optimizing since the index buffer may change // a bit of a hack to do this here, but this function gets called exactly once for the lifetime of a mesh // and is executed on a background thread MikktData data(this); - mikk::Mikktspace ctx(data); - ctx.genTangSpace(); + mikk::Mikktspace ctx(data); + ctx.genTangSpace(); //re-weld meshopt_Stream mos[] = @@ -5548,20 +5548,20 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents) resizeIndices(mNumIndices); meshopt_optimizeVertexCache<U16>(mIndices, src_indices, mNumIndices, mNumVertices); - + ll_aligned_free_16(src_indices); - return true; + return true; } void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVector4a& size) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME if (getOctree()) - { - return; - } + { + return; + } llassert(mNumIndices % 3 == 0); @@ -5571,63 +5571,63 @@ void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVe mOctreeTriangles = new LLVolumeTriangle[num_triangles]; for (U32 triangle_index = 0; triangle_index < num_triangles; ++triangle_index) - { //for each triangle + { //for each triangle const U32 index = triangle_index * 3; LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index]; - - const LLVector4a& v0 = mPositions[mIndices[index]]; - const LLVector4a& v1 = mPositions[mIndices[index + 1]]; - const LLVector4a& v2 = mPositions[mIndices[index + 2]]; - - //store pointers to vertex data - tri->mV[0] = &v0; - tri->mV[1] = &v1; - tri->mV[2] = &v2; - - //store indices - tri->mIndex[0] = mIndices[index]; - tri->mIndex[1] = mIndices[index + 1]; - tri->mIndex[2] = mIndices[index + 2]; - - //get minimum point - LLVector4a min = v0; - min.setMin(min, v1); - min.setMin(min, v2); - - //get maximum point - LLVector4a max = v0; - max.setMax(max, v1); - max.setMax(max, v2); - - //compute center - LLVector4a center; - center.setAdd(min, max); - center.mul(0.5f); - - tri->mPositionGroup = center; - - //compute "radius" - LLVector4a size; - size.setSub(max,min); - - tri->mRadius = size.getLength3().getF32() * scaler; - - //insert - mOctree->insert(tri); - } - - //remove unneeded octree layers - while (!mOctree->balance()) { } - - //calculate AABB for each node - LLVolumeOctreeRebound rebound; - rebound.traverse(mOctree); - - if (gDebugGL) - { - LLVolumeOctreeValidate validate; - validate.traverse(mOctree); - } + + const LLVector4a& v0 = mPositions[mIndices[index]]; + const LLVector4a& v1 = mPositions[mIndices[index + 1]]; + const LLVector4a& v2 = mPositions[mIndices[index + 2]]; + + //store pointers to vertex data + tri->mV[0] = &v0; + tri->mV[1] = &v1; + tri->mV[2] = &v2; + + //store indices + tri->mIndex[0] = mIndices[index]; + tri->mIndex[1] = mIndices[index + 1]; + tri->mIndex[2] = mIndices[index + 2]; + + //get minimum point + LLVector4a min = v0; + min.setMin(min, v1); + min.setMin(min, v2); + + //get maximum point + LLVector4a max = v0; + max.setMax(max, v1); + max.setMax(max, v2); + + //compute center + LLVector4a center; + center.setAdd(min, max); + center.mul(0.5f); + + tri->mPositionGroup = center; + + //compute "radius" + LLVector4a size; + size.setSub(max,min); + + tri->mRadius = size.getLength3().getF32() * scaler; + + //insert + mOctree->insert(tri); + } + + //remove unneeded octree layers + while (!mOctree->balance()) { } + + //calculate AABB for each node + LLVolumeOctreeRebound rebound; + rebound.traverse(mOctree); + + if (gDebugGL) + { + LLVolumeOctreeValidate validate; + validate.traverse(mOctree); + } } void LLVolumeFace::destroyOctree() @@ -5646,145 +5646,145 @@ const LLVolumeOctree* LLVolumeFace::getOctree() const void LLVolumeFace::swapData(LLVolumeFace& rhs) { - llswap(rhs.mPositions, mPositions); - llswap(rhs.mNormals, mNormals); - llswap(rhs.mTangents, mTangents); - llswap(rhs.mTexCoords, mTexCoords); - llswap(rhs.mIndices,mIndices); - llswap(rhs.mNumVertices, mNumVertices); - llswap(rhs.mNumIndices, mNumIndices); + llswap(rhs.mPositions, mPositions); + llswap(rhs.mNormals, mNormals); + llswap(rhs.mTangents, mTangents); + llswap(rhs.mTexCoords, mTexCoords); + llswap(rhs.mIndices,mIndices); + llswap(rhs.mNumVertices, mNumVertices); + llswap(rhs.mNumIndices, mNumIndices); } -void LerpPlanarVertex(LLVolumeFace::VertexData& v0, - LLVolumeFace::VertexData& v1, - LLVolumeFace::VertexData& v2, - LLVolumeFace::VertexData& vout, - F32 coef01, - F32 coef02) +void LerpPlanarVertex(LLVolumeFace::VertexData& v0, + LLVolumeFace::VertexData& v1, + LLVolumeFace::VertexData& v2, + LLVolumeFace::VertexData& vout, + F32 coef01, + F32 coef02) { - LLVector4a lhs; - lhs.setSub(v1.getPosition(), v0.getPosition()); - lhs.mul(coef01); - LLVector4a rhs; - rhs.setSub(v2.getPosition(), v0.getPosition()); - rhs.mul(coef02); + LLVector4a lhs; + lhs.setSub(v1.getPosition(), v0.getPosition()); + lhs.mul(coef01); + LLVector4a rhs; + rhs.setSub(v2.getPosition(), v0.getPosition()); + rhs.mul(coef02); + + rhs.add(lhs); + rhs.add(v0.getPosition()); - rhs.add(lhs); - rhs.add(v0.getPosition()); + vout.setPosition(rhs); - vout.setPosition(rhs); - - vout.mTexCoord = v0.mTexCoord + ((v1.mTexCoord-v0.mTexCoord)*coef01)+((v2.mTexCoord-v0.mTexCoord)*coef02); - vout.setNormal(v0.getNormal()); + vout.mTexCoord = v0.mTexCoord + ((v1.mTexCoord-v0.mTexCoord)*coef01)+((v2.mTexCoord-v0.mTexCoord)*coef02); + vout.setNormal(v0.getNormal()); } bool LLVolumeFace::createUnCutCubeCap(LLVolume* volume, bool partial_build) { - LL_CHECK_MEMORY - - const LLAlignedArray<LLVector4a,64>& mesh = volume->getMesh(); - const LLAlignedArray<LLVector4a,64>& profile = volume->getProfile().mProfile; - S32 max_s = volume->getProfile().getTotal(); - S32 max_t = volume->getPath().mPath.size(); - - // S32 i; - S32 grid_size = (profile.size()-1)/4; - // VFExtents change - LLVector4a& min = mExtents[0]; - LLVector4a& max = mExtents[1]; - - S32 offset = 0; - if (mTypeMask & TOP_MASK) - { - offset = (max_t-1) * max_s; - } - else - { - offset = mBeginS; - } - - { - VertexData corners[4]; - VertexData baseVert; - for(S32 t = 0; t < 4; t++) - { - corners[t].getPosition().load4a(mesh[offset + (grid_size*t)].getF32ptr()); - corners[t].mTexCoord.mV[0] = profile[grid_size*t][0]+0.5f; - corners[t].mTexCoord.mV[1] = 0.5f - profile[grid_size*t][1]; - } - - { - LLVector4a lhs; - lhs.setSub(corners[1].getPosition(), corners[0].getPosition()); - LLVector4a rhs; - rhs.setSub(corners[2].getPosition(), corners[1].getPosition()); - baseVert.getNormal().setCross3(lhs, rhs); - baseVert.getNormal().normalize3fast(); - } - - if(!(mTypeMask & TOP_MASK)) - { - baseVert.getNormal().mul(-1.0f); - } - else - { - //Swap the UVs on the U(X) axis for top face - LLVector2 swap; - swap = corners[0].mTexCoord; - corners[0].mTexCoord=corners[3].mTexCoord; - corners[3].mTexCoord=swap; - swap = corners[1].mTexCoord; - corners[1].mTexCoord=corners[2].mTexCoord; - corners[2].mTexCoord=swap; - } - - S32 size = (grid_size+1)*(grid_size+1); - resizeVertices(size); - - LLVector4a* pos = (LLVector4a*) mPositions; - LLVector4a* norm = (LLVector4a*) mNormals; - LLVector2* tc = (LLVector2*) mTexCoords; - - for(int gx = 0;gx<grid_size+1;gx++) - { - for(int gy = 0;gy<grid_size+1;gy++) - { - VertexData newVert; - LerpPlanarVertex( - corners[0], - corners[1], - corners[3], - newVert, - (F32)gx/(F32)grid_size, - (F32)gy/(F32)grid_size); - - *pos++ = newVert.getPosition(); - *norm++ = baseVert.getNormal(); - *tc++ = newVert.mTexCoord; - - if (gx == 0 && gy == 0) - { - min = newVert.getPosition(); - max = min; - } - else - { - min.setMin(min, newVert.getPosition()); - max.setMax(max, newVert.getPosition()); - } - } - } - - mCenter->setAdd(min, max); - mCenter->mul(0.5f); - } - - if (!partial_build) - { - resizeIndices(grid_size*grid_size*6); - if (!volume->isMeshAssetLoaded()) - { + LL_CHECK_MEMORY + + const LLAlignedArray<LLVector4a,64>& mesh = volume->getMesh(); + const LLAlignedArray<LLVector4a,64>& profile = volume->getProfile().mProfile; + S32 max_s = volume->getProfile().getTotal(); + S32 max_t = volume->getPath().mPath.size(); + + // S32 i; + S32 grid_size = (profile.size()-1)/4; + // VFExtents change + LLVector4a& min = mExtents[0]; + LLVector4a& max = mExtents[1]; + + S32 offset = 0; + if (mTypeMask & TOP_MASK) + { + offset = (max_t-1) * max_s; + } + else + { + offset = mBeginS; + } + + { + VertexData corners[4]; + VertexData baseVert; + for(S32 t = 0; t < 4; t++) + { + corners[t].getPosition().load4a(mesh[offset + (grid_size*t)].getF32ptr()); + corners[t].mTexCoord.mV[0] = profile[grid_size*t][0]+0.5f; + corners[t].mTexCoord.mV[1] = 0.5f - profile[grid_size*t][1]; + } + + { + LLVector4a lhs; + lhs.setSub(corners[1].getPosition(), corners[0].getPosition()); + LLVector4a rhs; + rhs.setSub(corners[2].getPosition(), corners[1].getPosition()); + baseVert.getNormal().setCross3(lhs, rhs); + baseVert.getNormal().normalize3fast(); + } + + if(!(mTypeMask & TOP_MASK)) + { + baseVert.getNormal().mul(-1.0f); + } + else + { + //Swap the UVs on the U(X) axis for top face + LLVector2 swap; + swap = corners[0].mTexCoord; + corners[0].mTexCoord=corners[3].mTexCoord; + corners[3].mTexCoord=swap; + swap = corners[1].mTexCoord; + corners[1].mTexCoord=corners[2].mTexCoord; + corners[2].mTexCoord=swap; + } + + S32 size = (grid_size+1)*(grid_size+1); + resizeVertices(size); + + LLVector4a* pos = (LLVector4a*) mPositions; + LLVector4a* norm = (LLVector4a*) mNormals; + LLVector2* tc = (LLVector2*) mTexCoords; + + for(int gx = 0;gx<grid_size+1;gx++) + { + for(int gy = 0;gy<grid_size+1;gy++) + { + VertexData newVert; + LerpPlanarVertex( + corners[0], + corners[1], + corners[3], + newVert, + (F32)gx/(F32)grid_size, + (F32)gy/(F32)grid_size); + + *pos++ = newVert.getPosition(); + *norm++ = baseVert.getNormal(); + *tc++ = newVert.mTexCoord; + + if (gx == 0 && gy == 0) + { + min = newVert.getPosition(); + max = min; + } + else + { + min.setMin(min, newVert.getPosition()); + max.setMax(max, newVert.getPosition()); + } + } + } + + mCenter->setAdd(min, max); + mCenter->mul(0.5f); + } + + if (!partial_build) + { + resizeIndices(grid_size*grid_size*6); + if (!volume->isMeshAssetLoaded()) + { S32 size = grid_size * grid_size * 6; try { @@ -5795,562 +5795,562 @@ bool LLVolumeFace::createUnCutCubeCap(LLVolume* volume, bool partial_build) LL_WARNS("LLVOLUME") << "Resize of mEdge to " << size << " failed" << LL_ENDL; return false; } - } - - U16* out = mIndices; - - S32 idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0}; - - int cur_edge = 0; - - for(S32 gx = 0;gx<grid_size;gx++) - { - - for(S32 gy = 0;gy<grid_size;gy++) - { - if (mTypeMask & TOP_MASK) - { - for(S32 i=5;i>=0;i--) - { - *out++ = ((gy*(grid_size+1))+gx+idxs[i]); - } - - S32 edge_value = grid_size * 2 * gy + gx * 2; - - if (gx > 0) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; // Mark face to higlight it - } - - if (gy < grid_size - 1) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; - } - - mEdge[cur_edge++] = edge_value; - - if (gx < grid_size - 1) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; - } - - if (gy > 0) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; - } - - mEdge[cur_edge++] = edge_value; - } - else - { - for(S32 i=0;i<6;i++) - { - *out++ = ((gy*(grid_size+1))+gx+idxs[i]); - } - - S32 edge_value = grid_size * 2 * gy + gx * 2; - - if (gy > 0) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; - } - - if (gx < grid_size - 1) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; - } - - mEdge[cur_edge++] = edge_value; - - if (gy < grid_size - 1) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; - } - - if (gx > 0) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; - } - - mEdge[cur_edge++] = edge_value; - } - } - } - } - - LL_CHECK_MEMORY - return true; + } + + U16* out = mIndices; + + S32 idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0}; + + int cur_edge = 0; + + for(S32 gx = 0;gx<grid_size;gx++) + { + + for(S32 gy = 0;gy<grid_size;gy++) + { + if (mTypeMask & TOP_MASK) + { + for(S32 i=5;i>=0;i--) + { + *out++ = ((gy*(grid_size+1))+gx+idxs[i]); + } + + S32 edge_value = grid_size * 2 * gy + gx * 2; + + if (gx > 0) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; // Mark face to higlight it + } + + if (gy < grid_size - 1) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; + } + + mEdge[cur_edge++] = edge_value; + + if (gx < grid_size - 1) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; + } + + if (gy > 0) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; + } + + mEdge[cur_edge++] = edge_value; + } + else + { + for(S32 i=0;i<6;i++) + { + *out++ = ((gy*(grid_size+1))+gx+idxs[i]); + } + + S32 edge_value = grid_size * 2 * gy + gx * 2; + + if (gy > 0) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; + } + + if (gx < grid_size - 1) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; + } + + mEdge[cur_edge++] = edge_value; + + if (gy < grid_size - 1) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; + } + + if (gx > 0) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; + } + + mEdge[cur_edge++] = edge_value; + } + } + } + } + + LL_CHECK_MEMORY + return true; } bool LLVolumeFace::createCap(LLVolume* volume, bool partial_build) { - if (!(mTypeMask & HOLLOW_MASK) && - !(mTypeMask & OPEN_MASK) && - ((volume->getParams().getPathParams().getBegin()==0.0f)&& - (volume->getParams().getPathParams().getEnd()==1.0f))&& - (volume->getParams().getProfileParams().getCurveType()==LL_PCODE_PROFILE_SQUARE && - volume->getParams().getPathParams().getCurveType()==LL_PCODE_PATH_LINE) - ){ - return createUnCutCubeCap(volume, partial_build); - } - - S32 num_vertices = 0, num_indices = 0; - - const LLAlignedArray<LLVector4a,64>& mesh = volume->getMesh(); - const LLAlignedArray<LLVector4a,64>& profile = volume->getProfile().mProfile; - - // All types of caps have the same number of vertices and indices - num_vertices = profile.size(); - num_indices = (profile.size() - 2)*3; - - if (!(mTypeMask & HOLLOW_MASK) && !(mTypeMask & OPEN_MASK)) - { - resizeVertices(num_vertices+1); - - //if (!partial_build) - { - resizeIndices(num_indices+3); - } - } - else - { - resizeVertices(num_vertices); - //if (!partial_build) - { - resizeIndices(num_indices); - } - } - - LL_CHECK_MEMORY; - - S32 max_s = volume->getProfile().getTotal(); - S32 max_t = volume->getPath().mPath.size(); - - mCenter->clear(); - - S32 offset = 0; - if (mTypeMask & TOP_MASK) - { - offset = (max_t-1) * max_s; - } - else - { - offset = mBeginS; - } - - // Figure out the normal, assume all caps are flat faces. - // Cross product to get normals. - - LLVector2 cuv; - LLVector2 min_uv, max_uv; - // VFExtents change - LLVector4a& min = mExtents[0]; - LLVector4a& max = mExtents[1]; - - LLVector2* tc = (LLVector2*) mTexCoords; - LLVector4a* pos = (LLVector4a*) mPositions; - LLVector4a* norm = (LLVector4a*) mNormals; - - // Copy the vertices into the array - - const LLVector4a* src = mesh.mArray+offset; - const LLVector4a* end = src+num_vertices; - - min = *src; - max = min; - - - const LLVector4a* p = profile.mArray; - - if (mTypeMask & TOP_MASK) - { - min_uv.set((*p)[0]+0.5f, - (*p)[1]+0.5f); - - max_uv = min_uv; - - while(src < end) - { - tc->mV[0] = (*p)[0]+0.5f; - tc->mV[1] = (*p)[1]+0.5f; - - llassert(src->isFinite3()); // MAINT-5660; don't know why this happens, does not affect Release builds - update_min_max(min,max,*src); - update_min_max(min_uv, max_uv, *tc); - - *pos = *src; - - llassert(pos->isFinite3()); - - ++p; - ++tc; - ++src; - ++pos; - } - } - else - { - - min_uv.set((*p)[0]+0.5f, - 0.5f - (*p)[1]); - max_uv = min_uv; - - while(src < end) - { - // Mirror for underside. - tc->mV[0] = (*p)[0]+0.5f; - tc->mV[1] = 0.5f - (*p)[1]; - - llassert(src->isFinite3()); - update_min_max(min,max,*src); - update_min_max(min_uv, max_uv, *tc); - - *pos = *src; - - llassert(pos->isFinite3()); - - ++p; - ++tc; - ++src; - ++pos; - } - } - - LL_CHECK_MEMORY - - mCenter->setAdd(min, max); - mCenter->mul(0.5f); - - cuv = (min_uv + max_uv)*0.5f; - - - VertexData vd; - vd.setPosition(*mCenter); - vd.mTexCoord = cuv; - - if (!(mTypeMask & HOLLOW_MASK) && !(mTypeMask & OPEN_MASK)) - { - *pos++ = *mCenter; - *tc++ = cuv; - num_vertices++; - } - - LL_CHECK_MEMORY - - //if (partial_build) - //{ - // return true; - //} - - if (mTypeMask & HOLLOW_MASK) - { - if (mTypeMask & TOP_MASK) - { - // HOLLOW TOP - // Does it matter if it's open or closed? - djs - - S32 pt1 = 0, pt2 = num_vertices - 1; - S32 i = 0; - while (pt2 - pt1 > 1) - { - // Use the profile points instead of the mesh, since you want - // the un-transformed profile distances. - const LLVector4a& p1 = profile[pt1]; - const LLVector4a& p2 = profile[pt2]; - const LLVector4a& pa = profile[pt1+1]; - const LLVector4a& pb = profile[pt2-1]; - - const F32* p1V = p1.getF32ptr(); - const F32* p2V = p2.getF32ptr(); - const F32* paV = pa.getF32ptr(); - const F32* pbV = pb.getF32ptr(); - - //p1.mV[VZ] = 0.f; - //p2.mV[VZ] = 0.f; - //pa.mV[VZ] = 0.f; - //pb.mV[VZ] = 0.f; - - // Use area of triangle to determine backfacing - F32 area_1a2, area_1ba, area_21b, area_2ab; - area_1a2 = (p1V[0]*paV[1] - paV[0]*p1V[1]) + - (paV[0]*p2V[1] - p2V[0]*paV[1]) + - (p2V[0]*p1V[1] - p1V[0]*p2V[1]); - - area_1ba = (p1V[0]*pbV[1] - pbV[0]*p1V[1]) + - (pbV[0]*paV[1] - paV[0]*pbV[1]) + - (paV[0]*p1V[1] - p1V[0]*paV[1]); - - area_21b = (p2V[0]*p1V[1] - p1V[0]*p2V[1]) + - (p1V[0]*pbV[1] - pbV[0]*p1V[1]) + - (pbV[0]*p2V[1] - p2V[0]*pbV[1]); - - area_2ab = (p2V[0]*paV[1] - paV[0]*p2V[1]) + - (paV[0]*pbV[1] - pbV[0]*paV[1]) + - (pbV[0]*p2V[1] - p2V[0]*pbV[1]); - - bool use_tri1a2 = true; - bool tri_1a2 = true; - bool tri_21b = true; - - if (area_1a2 < 0) - { - tri_1a2 = false; - } - if (area_2ab < 0) - { - // Can't use, because it contains point b - tri_1a2 = false; - } - if (area_21b < 0) - { - tri_21b = false; - } - if (area_1ba < 0) - { - // Can't use, because it contains point b - tri_21b = false; - } - - if (!tri_1a2) - { - use_tri1a2 = false; - } - else if (!tri_21b) - { - use_tri1a2 = true; - } - else - { - LLVector4a d1; - d1.setSub(p1, pa); - - LLVector4a d2; - d2.setSub(p2, pb); - - if (d1.dot3(d1) < d2.dot3(d2)) - { - use_tri1a2 = true; - } - else - { - use_tri1a2 = false; - } - } - - if (use_tri1a2) - { - mIndices[i++] = pt1; - mIndices[i++] = pt1 + 1; - mIndices[i++] = pt2; - pt1++; - } - else - { - mIndices[i++] = pt1; - mIndices[i++] = pt2 - 1; - mIndices[i++] = pt2; - pt2--; - } - } - } - else - { - // HOLLOW BOTTOM - // Does it matter if it's open or closed? - djs - - llassert(mTypeMask & BOTTOM_MASK); - S32 pt1 = 0, pt2 = num_vertices - 1; - - S32 i = 0; - while (pt2 - pt1 > 1) - { - // Use the profile points instead of the mesh, since you want - // the un-transformed profile distances. - const LLVector4a& p1 = profile[pt1]; - const LLVector4a& p2 = profile[pt2]; - const LLVector4a& pa = profile[pt1+1]; - const LLVector4a& pb = profile[pt2-1]; - - const F32* p1V = p1.getF32ptr(); - const F32* p2V = p2.getF32ptr(); - const F32* paV = pa.getF32ptr(); - const F32* pbV = pb.getF32ptr(); - - // Use area of triangle to determine backfacing - F32 area_1a2, area_1ba, area_21b, area_2ab; - area_1a2 = (p1V[0]*paV[1] - paV[0]*p1V[1]) + - (paV[0]*p2V[1] - p2V[0]*paV[1]) + - (p2V[0]*p1V[1] - p1V[0]*p2V[1]); - - area_1ba = (p1V[0]*pbV[1] - pbV[0]*p1V[1]) + - (pbV[0]*paV[1] - paV[0]*pbV[1]) + - (paV[0]*p1V[1] - p1V[0]*paV[1]); - - area_21b = (p2V[0]*p1V[1] - p1V[0]*p2V[1]) + - (p1V[0]*pbV[1] - pbV[0]*p1V[1]) + - (pbV[0]*p2V[1] - p2V[0]*pbV[1]); - - area_2ab = (p2V[0]*paV[1] - paV[0]*p2V[1]) + - (paV[0]*pbV[1] - pbV[0]*paV[1]) + - (pbV[0]*p2V[1] - p2V[0]*pbV[1]); - - bool use_tri1a2 = true; - bool tri_1a2 = true; - bool tri_21b = true; - - if (area_1a2 < 0) - { - tri_1a2 = false; - } - if (area_2ab < 0) - { - // Can't use, because it contains point b - tri_1a2 = false; - } - if (area_21b < 0) - { - tri_21b = false; - } - if (area_1ba < 0) - { - // Can't use, because it contains point b - tri_21b = false; - } - - if (!tri_1a2) - { - use_tri1a2 = false; - } - else if (!tri_21b) - { - use_tri1a2 = true; - } - else - { - LLVector4a d1; - d1.setSub(p1,pa); - LLVector4a d2; - d2.setSub(p2,pb); - - if (d1.dot3(d1) < d2.dot3(d2)) - { - use_tri1a2 = true; - } - else - { - use_tri1a2 = false; - } - } - - // Flipped backfacing from top - if (use_tri1a2) - { - mIndices[i++] = pt1; - mIndices[i++] = pt2; - mIndices[i++] = pt1 + 1; - pt1++; - } - else - { - mIndices[i++] = pt1; - mIndices[i++] = pt2; - mIndices[i++] = pt2 - 1; - pt2--; - } - } - } - } - else - { - // Not hollow, generate the triangle fan. - U16 v1 = 2; - U16 v2 = 1; - - if (mTypeMask & TOP_MASK) - { - v1 = 1; - v2 = 2; - } - - for (S32 i = 0; i < (num_vertices - 2); i++) - { - mIndices[3*i] = num_vertices - 1; - mIndices[3*i+v1] = i; - mIndices[3*i+v2] = i + 1; - } - - - } - - LLVector4a d0,d1; - LL_CHECK_MEMORY - - - d0.setSub(mPositions[mIndices[1]], mPositions[mIndices[0]]); - d1.setSub(mPositions[mIndices[2]], mPositions[mIndices[0]]); - - LLVector4a normal; - normal.setCross3(d0,d1); - - if (normal.dot3(normal).getF32() > F_APPROXIMATELY_ZERO) - { - normal.normalize3fast(); - } - else - { //degenerate, make up a value - if(normal.getF32ptr()[2] >= 0) - normal.set(0.f,0.f,1.f); - else - normal.set(0.f,0.f,-1.f); - } - - llassert(llfinite(normal.getF32ptr()[0])); - llassert(llfinite(normal.getF32ptr()[1])); - llassert(llfinite(normal.getF32ptr()[2])); - - llassert(!llisnan(normal.getF32ptr()[0])); - llassert(!llisnan(normal.getF32ptr()[1])); - llassert(!llisnan(normal.getF32ptr()[2])); - - for (S32 i = 0; i < num_vertices; i++) - { - norm[i].load4a(normal.getF32ptr()); - } - - return true; + if (!(mTypeMask & HOLLOW_MASK) && + !(mTypeMask & OPEN_MASK) && + ((volume->getParams().getPathParams().getBegin()==0.0f)&& + (volume->getParams().getPathParams().getEnd()==1.0f))&& + (volume->getParams().getProfileParams().getCurveType()==LL_PCODE_PROFILE_SQUARE && + volume->getParams().getPathParams().getCurveType()==LL_PCODE_PATH_LINE) + ){ + return createUnCutCubeCap(volume, partial_build); + } + + S32 num_vertices = 0, num_indices = 0; + + const LLAlignedArray<LLVector4a,64>& mesh = volume->getMesh(); + const LLAlignedArray<LLVector4a,64>& profile = volume->getProfile().mProfile; + + // All types of caps have the same number of vertices and indices + num_vertices = profile.size(); + num_indices = (profile.size() - 2)*3; + + if (!(mTypeMask & HOLLOW_MASK) && !(mTypeMask & OPEN_MASK)) + { + resizeVertices(num_vertices+1); + + //if (!partial_build) + { + resizeIndices(num_indices+3); + } + } + else + { + resizeVertices(num_vertices); + //if (!partial_build) + { + resizeIndices(num_indices); + } + } + + LL_CHECK_MEMORY; + + S32 max_s = volume->getProfile().getTotal(); + S32 max_t = volume->getPath().mPath.size(); + + mCenter->clear(); + + S32 offset = 0; + if (mTypeMask & TOP_MASK) + { + offset = (max_t-1) * max_s; + } + else + { + offset = mBeginS; + } + + // Figure out the normal, assume all caps are flat faces. + // Cross product to get normals. + + LLVector2 cuv; + LLVector2 min_uv, max_uv; + // VFExtents change + LLVector4a& min = mExtents[0]; + LLVector4a& max = mExtents[1]; + + LLVector2* tc = (LLVector2*) mTexCoords; + LLVector4a* pos = (LLVector4a*) mPositions; + LLVector4a* norm = (LLVector4a*) mNormals; + + // Copy the vertices into the array + + const LLVector4a* src = mesh.mArray+offset; + const LLVector4a* end = src+num_vertices; + + min = *src; + max = min; + + + const LLVector4a* p = profile.mArray; + + if (mTypeMask & TOP_MASK) + { + min_uv.set((*p)[0]+0.5f, + (*p)[1]+0.5f); + + max_uv = min_uv; + + while(src < end) + { + tc->mV[0] = (*p)[0]+0.5f; + tc->mV[1] = (*p)[1]+0.5f; + + llassert(src->isFinite3()); // MAINT-5660; don't know why this happens, does not affect Release builds + update_min_max(min,max,*src); + update_min_max(min_uv, max_uv, *tc); + + *pos = *src; + + llassert(pos->isFinite3()); + + ++p; + ++tc; + ++src; + ++pos; + } + } + else + { + + min_uv.set((*p)[0]+0.5f, + 0.5f - (*p)[1]); + max_uv = min_uv; + + while(src < end) + { + // Mirror for underside. + tc->mV[0] = (*p)[0]+0.5f; + tc->mV[1] = 0.5f - (*p)[1]; + + llassert(src->isFinite3()); + update_min_max(min,max,*src); + update_min_max(min_uv, max_uv, *tc); + + *pos = *src; + + llassert(pos->isFinite3()); + + ++p; + ++tc; + ++src; + ++pos; + } + } + + LL_CHECK_MEMORY + + mCenter->setAdd(min, max); + mCenter->mul(0.5f); + + cuv = (min_uv + max_uv)*0.5f; + + + VertexData vd; + vd.setPosition(*mCenter); + vd.mTexCoord = cuv; + + if (!(mTypeMask & HOLLOW_MASK) && !(mTypeMask & OPEN_MASK)) + { + *pos++ = *mCenter; + *tc++ = cuv; + num_vertices++; + } + + LL_CHECK_MEMORY + + //if (partial_build) + //{ + // return true; + //} + + if (mTypeMask & HOLLOW_MASK) + { + if (mTypeMask & TOP_MASK) + { + // HOLLOW TOP + // Does it matter if it's open or closed? - djs + + S32 pt1 = 0, pt2 = num_vertices - 1; + S32 i = 0; + while (pt2 - pt1 > 1) + { + // Use the profile points instead of the mesh, since you want + // the un-transformed profile distances. + const LLVector4a& p1 = profile[pt1]; + const LLVector4a& p2 = profile[pt2]; + const LLVector4a& pa = profile[pt1+1]; + const LLVector4a& pb = profile[pt2-1]; + + const F32* p1V = p1.getF32ptr(); + const F32* p2V = p2.getF32ptr(); + const F32* paV = pa.getF32ptr(); + const F32* pbV = pb.getF32ptr(); + + //p1.mV[VZ] = 0.f; + //p2.mV[VZ] = 0.f; + //pa.mV[VZ] = 0.f; + //pb.mV[VZ] = 0.f; + + // Use area of triangle to determine backfacing + F32 area_1a2, area_1ba, area_21b, area_2ab; + area_1a2 = (p1V[0]*paV[1] - paV[0]*p1V[1]) + + (paV[0]*p2V[1] - p2V[0]*paV[1]) + + (p2V[0]*p1V[1] - p1V[0]*p2V[1]); + + area_1ba = (p1V[0]*pbV[1] - pbV[0]*p1V[1]) + + (pbV[0]*paV[1] - paV[0]*pbV[1]) + + (paV[0]*p1V[1] - p1V[0]*paV[1]); + + area_21b = (p2V[0]*p1V[1] - p1V[0]*p2V[1]) + + (p1V[0]*pbV[1] - pbV[0]*p1V[1]) + + (pbV[0]*p2V[1] - p2V[0]*pbV[1]); + + area_2ab = (p2V[0]*paV[1] - paV[0]*p2V[1]) + + (paV[0]*pbV[1] - pbV[0]*paV[1]) + + (pbV[0]*p2V[1] - p2V[0]*pbV[1]); + + bool use_tri1a2 = true; + bool tri_1a2 = true; + bool tri_21b = true; + + if (area_1a2 < 0) + { + tri_1a2 = false; + } + if (area_2ab < 0) + { + // Can't use, because it contains point b + tri_1a2 = false; + } + if (area_21b < 0) + { + tri_21b = false; + } + if (area_1ba < 0) + { + // Can't use, because it contains point b + tri_21b = false; + } + + if (!tri_1a2) + { + use_tri1a2 = false; + } + else if (!tri_21b) + { + use_tri1a2 = true; + } + else + { + LLVector4a d1; + d1.setSub(p1, pa); + + LLVector4a d2; + d2.setSub(p2, pb); + + if (d1.dot3(d1) < d2.dot3(d2)) + { + use_tri1a2 = true; + } + else + { + use_tri1a2 = false; + } + } + + if (use_tri1a2) + { + mIndices[i++] = pt1; + mIndices[i++] = pt1 + 1; + mIndices[i++] = pt2; + pt1++; + } + else + { + mIndices[i++] = pt1; + mIndices[i++] = pt2 - 1; + mIndices[i++] = pt2; + pt2--; + } + } + } + else + { + // HOLLOW BOTTOM + // Does it matter if it's open or closed? - djs + + llassert(mTypeMask & BOTTOM_MASK); + S32 pt1 = 0, pt2 = num_vertices - 1; + + S32 i = 0; + while (pt2 - pt1 > 1) + { + // Use the profile points instead of the mesh, since you want + // the un-transformed profile distances. + const LLVector4a& p1 = profile[pt1]; + const LLVector4a& p2 = profile[pt2]; + const LLVector4a& pa = profile[pt1+1]; + const LLVector4a& pb = profile[pt2-1]; + + const F32* p1V = p1.getF32ptr(); + const F32* p2V = p2.getF32ptr(); + const F32* paV = pa.getF32ptr(); + const F32* pbV = pb.getF32ptr(); + + // Use area of triangle to determine backfacing + F32 area_1a2, area_1ba, area_21b, area_2ab; + area_1a2 = (p1V[0]*paV[1] - paV[0]*p1V[1]) + + (paV[0]*p2V[1] - p2V[0]*paV[1]) + + (p2V[0]*p1V[1] - p1V[0]*p2V[1]); + + area_1ba = (p1V[0]*pbV[1] - pbV[0]*p1V[1]) + + (pbV[0]*paV[1] - paV[0]*pbV[1]) + + (paV[0]*p1V[1] - p1V[0]*paV[1]); + + area_21b = (p2V[0]*p1V[1] - p1V[0]*p2V[1]) + + (p1V[0]*pbV[1] - pbV[0]*p1V[1]) + + (pbV[0]*p2V[1] - p2V[0]*pbV[1]); + + area_2ab = (p2V[0]*paV[1] - paV[0]*p2V[1]) + + (paV[0]*pbV[1] - pbV[0]*paV[1]) + + (pbV[0]*p2V[1] - p2V[0]*pbV[1]); + + bool use_tri1a2 = true; + bool tri_1a2 = true; + bool tri_21b = true; + + if (area_1a2 < 0) + { + tri_1a2 = false; + } + if (area_2ab < 0) + { + // Can't use, because it contains point b + tri_1a2 = false; + } + if (area_21b < 0) + { + tri_21b = false; + } + if (area_1ba < 0) + { + // Can't use, because it contains point b + tri_21b = false; + } + + if (!tri_1a2) + { + use_tri1a2 = false; + } + else if (!tri_21b) + { + use_tri1a2 = true; + } + else + { + LLVector4a d1; + d1.setSub(p1,pa); + LLVector4a d2; + d2.setSub(p2,pb); + + if (d1.dot3(d1) < d2.dot3(d2)) + { + use_tri1a2 = true; + } + else + { + use_tri1a2 = false; + } + } + + // Flipped backfacing from top + if (use_tri1a2) + { + mIndices[i++] = pt1; + mIndices[i++] = pt2; + mIndices[i++] = pt1 + 1; + pt1++; + } + else + { + mIndices[i++] = pt1; + mIndices[i++] = pt2; + mIndices[i++] = pt2 - 1; + pt2--; + } + } + } + } + else + { + // Not hollow, generate the triangle fan. + U16 v1 = 2; + U16 v2 = 1; + + if (mTypeMask & TOP_MASK) + { + v1 = 1; + v2 = 2; + } + + for (S32 i = 0; i < (num_vertices - 2); i++) + { + mIndices[3*i] = num_vertices - 1; + mIndices[3*i+v1] = i; + mIndices[3*i+v2] = i + 1; + } + + + } + + LLVector4a d0,d1; + LL_CHECK_MEMORY + + + d0.setSub(mPositions[mIndices[1]], mPositions[mIndices[0]]); + d1.setSub(mPositions[mIndices[2]], mPositions[mIndices[0]]); + + LLVector4a normal; + normal.setCross3(d0,d1); + + if (normal.dot3(normal).getF32() > F_APPROXIMATELY_ZERO) + { + normal.normalize3fast(); + } + else + { //degenerate, make up a value + if(normal.getF32ptr()[2] >= 0) + normal.set(0.f,0.f,1.f); + else + normal.set(0.f,0.f,-1.f); + } + + llassert(llfinite(normal.getF32ptr()[0])); + llassert(llfinite(normal.getF32ptr()[1])); + llassert(llfinite(normal.getF32ptr()[2])); + + llassert(!llisnan(normal.getF32ptr()[0])); + llassert(!llisnan(normal.getF32ptr()[1])); + llassert(!llisnan(normal.getF32ptr()[2])); + + for (S32 i = 0; i < num_vertices; i++) + { + norm[i].load4a(normal.getF32ptr()); + } + + return true; } void LLVolumeFace::createTangents() @@ -6360,7 +6360,7 @@ void LLVolumeFace::createTangents() if (!mTangents) { allocateTangents(mNumVertices); - + //generate tangents LLVector4a* ptr = (LLVector4a*)mTangents; @@ -6384,29 +6384,29 @@ void LLVolumeFace::createTangents() void LLVolumeFace::resizeVertices(S32 num_verts) { - ll_aligned_free<64>(mPositions); - //DO NOT free mNormals and mTexCoords as they are part of mPositions buffer - ll_aligned_free_16(mTangents); + ll_aligned_free<64>(mPositions); + //DO NOT free mNormals and mTexCoords as they are part of mPositions buffer + ll_aligned_free_16(mTangents); - mTangents = NULL; + mTangents = NULL; - if (num_verts) - { - //pad texture coordinate block end to allow for QWORD reads - S32 tc_size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF; + if (num_verts) + { + //pad texture coordinate block end to allow for QWORD reads + S32 tc_size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF; - mPositions = (LLVector4a*) ll_aligned_malloc<64>(sizeof(LLVector4a)*2*num_verts+tc_size); - mNormals = mPositions+num_verts; - mTexCoords = (LLVector2*) (mNormals+num_verts); + mPositions = (LLVector4a*) ll_aligned_malloc<64>(sizeof(LLVector4a)*2*num_verts+tc_size); + mNormals = mPositions+num_verts; + mTexCoords = (LLVector2*) (mNormals+num_verts); - ll_assert_aligned(mPositions, 64); - } - else - { - mPositions = NULL; - mNormals = NULL; - mTexCoords = NULL; - } + ll_assert_aligned(mPositions, 64); + } + else + { + mPositions = NULL; + mNormals = NULL; + mTexCoords = NULL; + } if (mPositions) @@ -6427,70 +6427,70 @@ void LLVolumeFace::resizeVertices(S32 num_verts) void LLVolumeFace::pushVertex(const LLVolumeFace::VertexData& cv) { - pushVertex(cv.getPosition(), cv.getNormal(), cv.mTexCoord); + pushVertex(cv.getPosition(), cv.getNormal(), cv.mTexCoord); } void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, const LLVector2& tc) { - S32 new_verts = mNumVertices+1; + S32 new_verts = mNumVertices+1; + + if (new_verts > mNumAllocatedVertices) + { + // double buffer size on expansion + new_verts *= 2; - if (new_verts > mNumAllocatedVertices) - { - // double buffer size on expansion - new_verts *= 2; + S32 new_tc_size = ((new_verts*8)+0xF) & ~0xF; + S32 old_tc_size = ((mNumVertices*8)+0xF) & ~0xF; - S32 new_tc_size = ((new_verts*8)+0xF) & ~0xF; - S32 old_tc_size = ((mNumVertices*8)+0xF) & ~0xF; + S32 old_vsize = mNumVertices*16; - S32 old_vsize = mNumVertices*16; - - S32 new_size = new_verts*16*2+new_tc_size; + S32 new_size = new_verts*16*2+new_tc_size; - LLVector4a* old_buf = mPositions; + LLVector4a* old_buf = mPositions; - mPositions = (LLVector4a*) ll_aligned_malloc<64>(new_size); - mNormals = mPositions+new_verts; - mTexCoords = (LLVector2*) (mNormals+new_verts); + mPositions = (LLVector4a*) ll_aligned_malloc<64>(new_size); + mNormals = mPositions+new_verts; + mTexCoords = (LLVector2*) (mNormals+new_verts); - if (old_buf != NULL) - { - // copy old positions into new buffer - LLVector4a::memcpyNonAliased16((F32*)mPositions, (F32*)old_buf, old_vsize); + if (old_buf != NULL) + { + // copy old positions into new buffer + LLVector4a::memcpyNonAliased16((F32*)mPositions, (F32*)old_buf, old_vsize); - // normals - LLVector4a::memcpyNonAliased16((F32*)mNormals, (F32*)(old_buf + mNumVertices), old_vsize); + // normals + LLVector4a::memcpyNonAliased16((F32*)mNormals, (F32*)(old_buf + mNumVertices), old_vsize); - // tex coords - LLVector4a::memcpyNonAliased16((F32*)mTexCoords, (F32*)(old_buf + mNumVertices * 2), old_tc_size); - } + // tex coords + LLVector4a::memcpyNonAliased16((F32*)mTexCoords, (F32*)(old_buf + mNumVertices * 2), old_tc_size); + } - // just clear tangents - ll_aligned_free_16(mTangents); - mTangents = NULL; - ll_aligned_free<64>(old_buf); + // just clear tangents + ll_aligned_free_16(mTangents); + mTangents = NULL; + ll_aligned_free<64>(old_buf); - mNumAllocatedVertices = new_verts; + mNumAllocatedVertices = new_verts; - } + } - mPositions[mNumVertices] = pos; - mNormals[mNumVertices] = norm; - mTexCoords[mNumVertices] = tc; + mPositions[mNumVertices] = pos; + mNormals[mNumVertices] = norm; + mTexCoords[mNumVertices] = tc; - mNumVertices++; + mNumVertices++; } void LLVolumeFace::allocateTangents(S32 num_verts) { - ll_aligned_free_16(mTangents); - mTangents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); + ll_aligned_free_16(mTangents); + mTangents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); } void LLVolumeFace::allocateWeights(S32 num_verts) { - ll_aligned_free_16(mWeights); - mWeights = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); - + ll_aligned_free_16(mWeights); + mWeights = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); + } void LLVolumeFace::allocateJointIndices(S32 num_verts) @@ -6499,27 +6499,27 @@ void LLVolumeFace::allocateJointIndices(S32 num_verts) ll_aligned_free_16(mJointIndices); ll_aligned_free_16(mJustWeights); - mJointIndices = (U8*)ll_aligned_malloc_16(sizeof(U8) * 4 * num_verts); - mJustWeights = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a) * num_verts); + mJointIndices = (U8*)ll_aligned_malloc_16(sizeof(U8) * 4 * num_verts); + mJustWeights = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a) * num_verts); #endif } void LLVolumeFace::resizeIndices(S32 num_indices) { - ll_aligned_free_16(mIndices); + ll_aligned_free_16(mIndices); llassert(num_indices % 3 == 0); - - if (num_indices) - { - //pad index block end to allow for QWORD reads - S32 size = ((num_indices*sizeof(U16)) + 0xF) & ~0xF; - - mIndices = (U16*) ll_aligned_malloc_16(size); - } - else - { - mIndices = NULL; - } + + if (num_indices) + { + //pad index block end to allow for QWORD reads + S32 size = ((num_indices*sizeof(U16)) + 0xF) & ~0xF; + + mIndices = (U16*) ll_aligned_malloc_16(size); + } + else + { + mIndices = NULL; + } if (mIndices) { @@ -6534,73 +6534,73 @@ void LLVolumeFace::resizeIndices(S32 num_indices) void LLVolumeFace::pushIndex(const U16& idx) { - S32 new_count = mNumIndices + 1; - S32 new_size = ((new_count*2)+0xF) & ~0xF; + S32 new_count = mNumIndices + 1; + S32 new_size = ((new_count*2)+0xF) & ~0xF; - S32 old_size = ((mNumIndices*2)+0xF) & ~0xF; - if (new_size != old_size) - { - mIndices = (U16*) ll_aligned_realloc_16(mIndices, new_size, old_size); - ll_assert_aligned(mIndices,16); - } - - mIndices[mNumIndices++] = idx; + S32 old_size = ((mNumIndices*2)+0xF) & ~0xF; + if (new_size != old_size) + { + mIndices = (U16*) ll_aligned_realloc_16(mIndices, new_size, old_size); + ll_assert_aligned(mIndices,16); + } + + mIndices[mNumIndices++] = idx; } void LLVolumeFace::fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v, std::vector<U16>& idx) { - resizeVertices(v.size()); - resizeIndices(idx.size()); + resizeVertices(v.size()); + resizeIndices(idx.size()); - for (U32 i = 0; i < v.size(); ++i) - { - mPositions[i] = v[i].getPosition(); - mNormals[i] = v[i].getNormal(); - mTexCoords[i] = v[i].mTexCoord; - } + for (U32 i = 0; i < v.size(); ++i) + { + mPositions[i] = v[i].getPosition(); + mNormals[i] = v[i].getNormal(); + mTexCoords[i] = v[i].mTexCoord; + } - for (U32 i = 0; i < idx.size(); ++i) - { - mIndices[i] = idx[i]; - } + for (U32 i = 0; i < idx.size(); ++i) + { + mIndices[i] = idx[i]; + } } bool LLVolumeFace::createSide(LLVolume* volume, bool partial_build) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME - LL_CHECK_MEMORY - bool flat = mTypeMask & FLAT_MASK; + LL_CHECK_MEMORY + bool flat = mTypeMask & FLAT_MASK; - U8 sculpt_type = volume->getParams().getSculptType(); - U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK; - bool sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT; - bool sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR; - bool sculpt_reverse_horizontal = (sculpt_invert ? !sculpt_mirror : sculpt_mirror); // XOR - - S32 num_vertices, num_indices; + U8 sculpt_type = volume->getParams().getSculptType(); + U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK; + bool sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT; + bool sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR; + bool sculpt_reverse_horizontal = (sculpt_invert ? !sculpt_mirror : sculpt_mirror); // XOR - const LLAlignedArray<LLVector4a,64>& mesh = volume->getMesh(); - const LLAlignedArray<LLVector4a,64>& profile = volume->getProfile().mProfile; - const LLAlignedArray<LLPath::PathPt,64>& path_data = volume->getPath().mPath; + S32 num_vertices, num_indices; - S32 max_s = volume->getProfile().getTotal(); + const LLAlignedArray<LLVector4a,64>& mesh = volume->getMesh(); + const LLAlignedArray<LLVector4a,64>& profile = volume->getProfile().mProfile; + const LLAlignedArray<LLPath::PathPt,64>& path_data = volume->getPath().mPath; - S32 s, t, i; - F32 ss, tt; + S32 max_s = volume->getProfile().getTotal(); - num_vertices = mNumS*mNumT; - num_indices = (mNumS-1)*(mNumT-1)*6; + S32 s, t, i; + F32 ss, tt; - partial_build = (num_vertices > mNumVertices || num_indices > mNumIndices) ? false : partial_build; + num_vertices = mNumS*mNumT; + num_indices = (mNumS-1)*(mNumT-1)*6; - if (!partial_build) - { - resizeVertices(num_vertices); - resizeIndices(num_indices); + partial_build = (num_vertices > mNumVertices || num_indices > mNumIndices) ? false : partial_build; - if (!volume->isMeshAssetLoaded()) - { + if (!partial_build) + { + resizeVertices(num_vertices); + resizeIndices(num_indices); + + if (!volume->isMeshAssetLoaded()) + { try { mEdge.resize(num_indices); @@ -6610,255 +6610,255 @@ bool LLVolumeFace::createSide(LLVolume* volume, bool partial_build) LL_WARNS("LLVOLUME") << "Resize of mEdge to " << num_indices << " failed" << LL_ENDL; return false; } - } - } - - LL_CHECK_MEMORY - - LLVector4a* pos = (LLVector4a*) mPositions; - LLVector2* tc = (LLVector2*) mTexCoords; - F32 begin_stex = floorf(profile[mBeginS][2]); - S32 num_s = ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2) ? mNumS/2 : mNumS; - - S32 cur_vertex = 0; - S32 end_t = mBeginT+mNumT; - bool test = (mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2; - - // Copy the vertices into the array - for (t = mBeginT; t < end_t; t++) - { - tt = path_data[t].mTexT; - for (s = 0; s < num_s; s++) - { - if (mTypeMask & END_MASK) - { - if (s) - { - ss = 1.f; - } - else - { - ss = 0.f; - } - } - else - { - // Get s value for tex-coord. + } + } + + LL_CHECK_MEMORY + + LLVector4a* pos = (LLVector4a*) mPositions; + LLVector2* tc = (LLVector2*) mTexCoords; + F32 begin_stex = floorf(profile[mBeginS][2]); + S32 num_s = ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2) ? mNumS/2 : mNumS; + + S32 cur_vertex = 0; + S32 end_t = mBeginT+mNumT; + bool test = (mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2; + + // Copy the vertices into the array + for (t = mBeginT; t < end_t; t++) + { + tt = path_data[t].mTexT; + for (s = 0; s < num_s; s++) + { + if (mTypeMask & END_MASK) + { + if (s) + { + ss = 1.f; + } + else + { + ss = 0.f; + } + } + else + { + // Get s value for tex-coord. S32 index = mBeginS + s; if (index >= profile.size()) { // edge? ss = flat ? 1.f - begin_stex : 1.f; } - else if (!flat) - { - ss = profile[index][2]; - } - else - { - ss = profile[index][2] - begin_stex; - } - } - - if (sculpt_reverse_horizontal) - { - ss = 1.f - ss; - } - - // Check to see if this triangle wraps around the array. - if (mBeginS + s >= max_s) - { - // We're wrapping - i = mBeginS + s + max_s*(t-1); - } - else - { - i = mBeginS + s + max_s*t; - } - - mesh[i].store4a((F32*)(pos+cur_vertex)); - tc[cur_vertex].set(ss,tt); - - cur_vertex++; - - if (test && s > 0) - { - mesh[i].store4a((F32*)(pos+cur_vertex)); - tc[cur_vertex].set(ss,tt); - cur_vertex++; - } - } - - if ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2) - { - if (mTypeMask & OPEN_MASK) - { - s = num_s-1; - } - else - { - s = 0; - } - - i = mBeginS + s + max_s*t; - ss = profile[mBeginS + s][2] - begin_stex; - - mesh[i].store4a((F32*)(pos+cur_vertex)); - tc[cur_vertex].set(ss,tt); - - cur_vertex++; - } - } - LL_CHECK_MEMORY - - mCenter->clear(); - - LLVector4a* cur_pos = pos; - LLVector4a* end_pos = pos + mNumVertices; - - //get bounding box for this side - LLVector4a face_min; - LLVector4a face_max; - - face_min = face_max = *cur_pos++; - - while (cur_pos < end_pos) - { - update_min_max(face_min, face_max, *cur_pos++); - } - // VFExtents change - mExtents[0] = face_min; - mExtents[1] = face_max; - - U32 tc_count = mNumVertices; - if (tc_count%2 == 1) - { //odd number of texture coordinates, duplicate last entry to padded end of array - tc_count++; - mTexCoords[mNumVertices] = mTexCoords[mNumVertices-1]; - } - - LLVector4a* cur_tc = (LLVector4a*) mTexCoords; - LLVector4a* end_tc = (LLVector4a*) (mTexCoords+tc_count); - - LLVector4a tc_min; - LLVector4a tc_max; - - tc_min = tc_max = *cur_tc++; - - while (cur_tc < end_tc) - { - update_min_max(tc_min, tc_max, *cur_tc++); - } - - F32* minp = tc_min.getF32ptr(); - F32* maxp = tc_max.getF32ptr(); - - mTexCoordExtents[0].mV[0] = llmin(minp[0], minp[2]); - mTexCoordExtents[0].mV[1] = llmin(minp[1], minp[3]); - mTexCoordExtents[1].mV[0] = llmax(maxp[0], maxp[2]); - mTexCoordExtents[1].mV[1] = llmax(maxp[1], maxp[3]); - - mCenter->setAdd(face_min, face_max); - mCenter->mul(0.5f); - - S32 cur_index = 0; - S32 cur_edge = 0; - bool flat_face = mTypeMask & FLAT_MASK; - - if (!partial_build) - { - // Now we generate the indices. - for (t = 0; t < (mNumT-1); t++) - { - for (s = 0; s < (mNumS-1); s++) - { - mIndices[cur_index++] = s + mNumS*t; //bottom left - mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right - mIndices[cur_index++] = s + mNumS*(t+1); //top left - mIndices[cur_index++] = s + mNumS*t; //bottom left - mIndices[cur_index++] = s+1 + mNumS*t; //bottom right - mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right - - // bottom left/top right neighbor face - mEdge[cur_edge++] = (mNumS-1)*2*t+s*2+1; - - if (t < mNumT-2) - { // top right/top left neighbor face - mEdge[cur_edge++] = (mNumS-1)*2*(t+1)+s*2+1; - } - else if (mNumT <= 3 || volume->getPath().isOpen()) - { // no neighbor - mEdge[cur_edge++] = -1; - } - else - { // wrap on T - mEdge[cur_edge++] = s*2+1; - } - - if (s > 0) - { // top left/bottom left neighbor face - mEdge[cur_edge++] = (mNumS-1)*2*t+s*2-1; - } - else if (flat_face || volume->getProfile().isOpen()) - { // no neighbor - mEdge[cur_edge++] = -1; - } - else - { // wrap on S - mEdge[cur_edge++] = (mNumS-1)*2*t+(mNumS-2)*2+1; - } - - if (t > 0) - { // bottom left/bottom right neighbor face - mEdge[cur_edge++] = (mNumS-1)*2*(t-1)+s*2; - } - else if (mNumT <= 3 || volume->getPath().isOpen()) - { // no neighbor - mEdge[cur_edge++] = -1; - } - else - { // wrap on T - mEdge[cur_edge++] = (mNumS-1)*2*(mNumT-2)+s*2; - } - - if (s < mNumS-2) - { // bottom right/top right neighbor face - mEdge[cur_edge++] = (mNumS-1)*2*t+(s+1)*2; - } - else if (flat_face || volume->getProfile().isOpen()) - { // no neighbor - mEdge[cur_edge++] = -1; - } - else - { // wrap on S - mEdge[cur_edge++] = (mNumS-1)*2*t; - } - - // top right/bottom left neighbor face - mEdge[cur_edge++] = (mNumS-1)*2*t+s*2; - } - } - } - - LL_CHECK_MEMORY - - //clear normals - F32* dst = (F32*) mNormals; - F32* end = (F32*) (mNormals+mNumVertices); - LLVector4a zero = LLVector4a::getZero(); - - while (dst < end) - { - zero.store4a(dst); - dst += 4; - } - - LL_CHECK_MEMORY - - //generate normals - U32 count = mNumIndices/3; - - LLVector4a* norm = mNormals; + else if (!flat) + { + ss = profile[index][2]; + } + else + { + ss = profile[index][2] - begin_stex; + } + } + + if (sculpt_reverse_horizontal) + { + ss = 1.f - ss; + } + + // Check to see if this triangle wraps around the array. + if (mBeginS + s >= max_s) + { + // We're wrapping + i = mBeginS + s + max_s*(t-1); + } + else + { + i = mBeginS + s + max_s*t; + } + + mesh[i].store4a((F32*)(pos+cur_vertex)); + tc[cur_vertex].set(ss,tt); + + cur_vertex++; + + if (test && s > 0) + { + mesh[i].store4a((F32*)(pos+cur_vertex)); + tc[cur_vertex].set(ss,tt); + cur_vertex++; + } + } + + if ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2) + { + if (mTypeMask & OPEN_MASK) + { + s = num_s-1; + } + else + { + s = 0; + } + + i = mBeginS + s + max_s*t; + ss = profile[mBeginS + s][2] - begin_stex; + + mesh[i].store4a((F32*)(pos+cur_vertex)); + tc[cur_vertex].set(ss,tt); + + cur_vertex++; + } + } + LL_CHECK_MEMORY + + mCenter->clear(); + + LLVector4a* cur_pos = pos; + LLVector4a* end_pos = pos + mNumVertices; + + //get bounding box for this side + LLVector4a face_min; + LLVector4a face_max; + + face_min = face_max = *cur_pos++; + + while (cur_pos < end_pos) + { + update_min_max(face_min, face_max, *cur_pos++); + } + // VFExtents change + mExtents[0] = face_min; + mExtents[1] = face_max; + + U32 tc_count = mNumVertices; + if (tc_count%2 == 1) + { //odd number of texture coordinates, duplicate last entry to padded end of array + tc_count++; + mTexCoords[mNumVertices] = mTexCoords[mNumVertices-1]; + } + + LLVector4a* cur_tc = (LLVector4a*) mTexCoords; + LLVector4a* end_tc = (LLVector4a*) (mTexCoords+tc_count); + + LLVector4a tc_min; + LLVector4a tc_max; + + tc_min = tc_max = *cur_tc++; + + while (cur_tc < end_tc) + { + update_min_max(tc_min, tc_max, *cur_tc++); + } + + F32* minp = tc_min.getF32ptr(); + F32* maxp = tc_max.getF32ptr(); + + mTexCoordExtents[0].mV[0] = llmin(minp[0], minp[2]); + mTexCoordExtents[0].mV[1] = llmin(minp[1], minp[3]); + mTexCoordExtents[1].mV[0] = llmax(maxp[0], maxp[2]); + mTexCoordExtents[1].mV[1] = llmax(maxp[1], maxp[3]); + + mCenter->setAdd(face_min, face_max); + mCenter->mul(0.5f); + + S32 cur_index = 0; + S32 cur_edge = 0; + bool flat_face = mTypeMask & FLAT_MASK; + + if (!partial_build) + { + // Now we generate the indices. + for (t = 0; t < (mNumT-1); t++) + { + for (s = 0; s < (mNumS-1); s++) + { + mIndices[cur_index++] = s + mNumS*t; //bottom left + mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right + mIndices[cur_index++] = s + mNumS*(t+1); //top left + mIndices[cur_index++] = s + mNumS*t; //bottom left + mIndices[cur_index++] = s+1 + mNumS*t; //bottom right + mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right + + // bottom left/top right neighbor face + mEdge[cur_edge++] = (mNumS-1)*2*t+s*2+1; + + if (t < mNumT-2) + { // top right/top left neighbor face + mEdge[cur_edge++] = (mNumS-1)*2*(t+1)+s*2+1; + } + else if (mNumT <= 3 || volume->getPath().isOpen()) + { // no neighbor + mEdge[cur_edge++] = -1; + } + else + { // wrap on T + mEdge[cur_edge++] = s*2+1; + } + + if (s > 0) + { // top left/bottom left neighbor face + mEdge[cur_edge++] = (mNumS-1)*2*t+s*2-1; + } + else if (flat_face || volume->getProfile().isOpen()) + { // no neighbor + mEdge[cur_edge++] = -1; + } + else + { // wrap on S + mEdge[cur_edge++] = (mNumS-1)*2*t+(mNumS-2)*2+1; + } + + if (t > 0) + { // bottom left/bottom right neighbor face + mEdge[cur_edge++] = (mNumS-1)*2*(t-1)+s*2; + } + else if (mNumT <= 3 || volume->getPath().isOpen()) + { // no neighbor + mEdge[cur_edge++] = -1; + } + else + { // wrap on T + mEdge[cur_edge++] = (mNumS-1)*2*(mNumT-2)+s*2; + } + + if (s < mNumS-2) + { // bottom right/top right neighbor face + mEdge[cur_edge++] = (mNumS-1)*2*t+(s+1)*2; + } + else if (flat_face || volume->getProfile().isOpen()) + { // no neighbor + mEdge[cur_edge++] = -1; + } + else + { // wrap on S + mEdge[cur_edge++] = (mNumS-1)*2*t; + } + + // top right/bottom left neighbor face + mEdge[cur_edge++] = (mNumS-1)*2*t+s*2; + } + } + } + + LL_CHECK_MEMORY + + //clear normals + F32* dst = (F32*) mNormals; + F32* end = (F32*) (mNormals+mNumVertices); + LLVector4a zero = LLVector4a::getZero(); + + while (dst < end) + { + zero.store4a(dst); + dst += 4; + } + + LL_CHECK_MEMORY + + //generate normals + U32 count = mNumIndices/3; + + LLVector4a* norm = mNormals; static thread_local LLAlignedArray<LLVector4a, 64> triangle_normals; try @@ -6870,242 +6870,242 @@ bool LLVolumeFace::createSide(LLVolume* volume, bool partial_build) LL_WARNS("LLVOLUME") << "Resize of triangle_normals to " << count << " failed" << LL_ENDL; return false; } - LLVector4a* output = triangle_normals.mArray; - LLVector4a* end_output = output+count; - - U16* idx = mIndices; - - while (output < end_output) - { - LLVector4a b,v1,v2; - b.load4a((F32*) (pos+idx[0])); - v1.load4a((F32*) (pos+idx[1])); - v2.load4a((F32*) (pos+idx[2])); - - //calculate triangle normal - LLVector4a a; - - a.setSub(b, v1); - b.sub(v2); - - - LLQuad& vector1 = *((LLQuad*) &v1); - LLQuad& vector2 = *((LLQuad*) &v2); - - LLQuad& amQ = *((LLQuad*) &a); - LLQuad& bmQ = *((LLQuad*) &b); - - //v1.setCross3(t,v0); - //setCross3(const LLVector4a& a, const LLVector4a& b) - // Vectors are stored in memory in w, z, y, x order from high to low - // Set vector1 = { a[W], a[X], a[Z], a[Y] } - vector1 = _mm_shuffle_ps( amQ, amQ, _MM_SHUFFLE( 3, 0, 2, 1 )); - // Set vector2 = { b[W], b[Y], b[X], b[Z] } - vector2 = _mm_shuffle_ps( bmQ, bmQ, _MM_SHUFFLE( 3, 1, 0, 2 )); - // mQ = { a[W]*b[W], a[X]*b[Y], a[Z]*b[X], a[Y]*b[Z] } - vector2 = _mm_mul_ps( vector1, vector2 ); - // vector3 = { a[W], a[Y], a[X], a[Z] } - amQ = _mm_shuffle_ps( amQ, amQ, _MM_SHUFFLE( 3, 1, 0, 2 )); - // vector4 = { b[W], b[X], b[Z], b[Y] } - bmQ = _mm_shuffle_ps( bmQ, bmQ, _MM_SHUFFLE( 3, 0, 2, 1 )); - // mQ = { 0, a[X]*b[Y] - a[Y]*b[X], a[Z]*b[X] - a[X]*b[Z], a[Y]*b[Z] - a[Z]*b[Y] } - vector1 = _mm_sub_ps( vector2, _mm_mul_ps( amQ, bmQ )); - - llassert(v1.isFinite3()); - - v1.store4a((F32*) output); - - - output++; - idx += 3; - } - - idx = mIndices; - - LLVector4a* src = triangle_normals.mArray; - - for (U32 i = 0; i < count; i++) //for each triangle - { - LLVector4a c; - c.load4a((F32*) (src++)); - - LLVector4a* n0p = norm+idx[0]; - LLVector4a* n1p = norm+idx[1]; - LLVector4a* n2p = norm+idx[2]; - - idx += 3; - - LLVector4a n0,n1,n2; - n0.load4a((F32*) n0p); - n1.load4a((F32*) n1p); - n2.load4a((F32*) n2p); - - n0.add(c); - n1.add(c); - n2.add(c); - - llassert(c.isFinite3()); - - //even out quad contributions - switch (i%2+1) - { - case 0: n0.add(c); break; - case 1: n1.add(c); break; - case 2: n2.add(c); break; - }; - - n0.store4a((F32*) n0p); - n1.store4a((F32*) n1p); - n2.store4a((F32*) n2p); - } - - LL_CHECK_MEMORY - - // adjust normals based on wrapping and stitching - - LLVector4a top; - top.setSub(pos[0], pos[mNumS*(mNumT-2)]); - bool s_bottom_converges = (top.dot3(top) < 0.000001f); - - top.setSub(pos[mNumS-1], pos[mNumS*(mNumT-2)+mNumS-1]); - bool s_top_converges = (top.dot3(top) < 0.000001f); - - if (sculpt_stitching == LL_SCULPT_TYPE_NONE) // logic for non-sculpt volumes - { - if (!volume->getPath().isOpen()) - { //wrap normals on T - for (S32 i = 0; i < mNumS; i++) - { - LLVector4a n; - n.setAdd(norm[i], norm[mNumS*(mNumT-1)+i]); - norm[i] = n; - norm[mNumS*(mNumT-1)+i] = n; - } - } - - if (!volume->getProfile().isOpen() && !s_bottom_converges) - { //wrap normals on S - for (S32 i = 0; i < mNumT; i++) - { - LLVector4a n; - n.setAdd(norm[mNumS*i], norm[mNumS*i+mNumS-1]); - norm[mNumS * i] = n; - norm[mNumS * i+mNumS-1] = n; - } - } - - if (volume->getPathType() == LL_PCODE_PATH_CIRCLE && - ((volume->getProfileType() & LL_PCODE_PROFILE_MASK) == LL_PCODE_PROFILE_CIRCLE_HALF)) - { - if (s_bottom_converges) - { //all lower S have same normal - for (S32 i = 0; i < mNumT; i++) - { - norm[mNumS*i].set(1,0,0); - } - } - - if (s_top_converges) - { //all upper S have same normal - for (S32 i = 0; i < mNumT; i++) - { - norm[mNumS*i+mNumS-1].set(-1,0,0); - } - } - } - } - else // logic for sculpt volumes - { - bool average_poles = false; - bool wrap_s = false; - bool wrap_t = false; - - if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE) - average_poles = true; - - if ((sculpt_stitching == LL_SCULPT_TYPE_SPHERE) || - (sculpt_stitching == LL_SCULPT_TYPE_TORUS) || - (sculpt_stitching == LL_SCULPT_TYPE_CYLINDER)) - wrap_s = true; - - if (sculpt_stitching == LL_SCULPT_TYPE_TORUS) - wrap_t = true; - - - if (average_poles) - { - // average normals for north pole - - LLVector4a average; - average.clear(); - - for (S32 i = 0; i < mNumS; i++) - { - average.add(norm[i]); - } - - // set average - for (S32 i = 0; i < mNumS; i++) - { - norm[i] = average; - } - - // average normals for south pole - - average.clear(); - - for (S32 i = 0; i < mNumS; i++) - { - average.add(norm[i + mNumS * (mNumT - 1)]); - } - - // set average - for (S32 i = 0; i < mNumS; i++) - { - norm[i + mNumS * (mNumT - 1)] = average; - } - - } - - - if (wrap_s) - { - for (S32 i = 0; i < mNumT; i++) - { - LLVector4a n; - n.setAdd(norm[mNumS*i], norm[mNumS*i+mNumS-1]); - norm[mNumS * i] = n; - norm[mNumS * i+mNumS-1] = n; - } - } - - if (wrap_t) - { - for (S32 i = 0; i < mNumS; i++) - { - LLVector4a n; - n.setAdd(norm[i], norm[mNumS*(mNumT-1)+i]); - norm[i] = n; - norm[mNumS*(mNumT-1)+i] = n; - } - } - - } - - LL_CHECK_MEMORY - - return true; + LLVector4a* output = triangle_normals.mArray; + LLVector4a* end_output = output+count; + + U16* idx = mIndices; + + while (output < end_output) + { + LLVector4a b,v1,v2; + b.load4a((F32*) (pos+idx[0])); + v1.load4a((F32*) (pos+idx[1])); + v2.load4a((F32*) (pos+idx[2])); + + //calculate triangle normal + LLVector4a a; + + a.setSub(b, v1); + b.sub(v2); + + + LLQuad& vector1 = *((LLQuad*) &v1); + LLQuad& vector2 = *((LLQuad*) &v2); + + LLQuad& amQ = *((LLQuad*) &a); + LLQuad& bmQ = *((LLQuad*) &b); + + //v1.setCross3(t,v0); + //setCross3(const LLVector4a& a, const LLVector4a& b) + // Vectors are stored in memory in w, z, y, x order from high to low + // Set vector1 = { a[W], a[X], a[Z], a[Y] } + vector1 = _mm_shuffle_ps( amQ, amQ, _MM_SHUFFLE( 3, 0, 2, 1 )); + // Set vector2 = { b[W], b[Y], b[X], b[Z] } + vector2 = _mm_shuffle_ps( bmQ, bmQ, _MM_SHUFFLE( 3, 1, 0, 2 )); + // mQ = { a[W]*b[W], a[X]*b[Y], a[Z]*b[X], a[Y]*b[Z] } + vector2 = _mm_mul_ps( vector1, vector2 ); + // vector3 = { a[W], a[Y], a[X], a[Z] } + amQ = _mm_shuffle_ps( amQ, amQ, _MM_SHUFFLE( 3, 1, 0, 2 )); + // vector4 = { b[W], b[X], b[Z], b[Y] } + bmQ = _mm_shuffle_ps( bmQ, bmQ, _MM_SHUFFLE( 3, 0, 2, 1 )); + // mQ = { 0, a[X]*b[Y] - a[Y]*b[X], a[Z]*b[X] - a[X]*b[Z], a[Y]*b[Z] - a[Z]*b[Y] } + vector1 = _mm_sub_ps( vector2, _mm_mul_ps( amQ, bmQ )); + + llassert(v1.isFinite3()); + + v1.store4a((F32*) output); + + + output++; + idx += 3; + } + + idx = mIndices; + + LLVector4a* src = triangle_normals.mArray; + + for (U32 i = 0; i < count; i++) //for each triangle + { + LLVector4a c; + c.load4a((F32*) (src++)); + + LLVector4a* n0p = norm+idx[0]; + LLVector4a* n1p = norm+idx[1]; + LLVector4a* n2p = norm+idx[2]; + + idx += 3; + + LLVector4a n0,n1,n2; + n0.load4a((F32*) n0p); + n1.load4a((F32*) n1p); + n2.load4a((F32*) n2p); + + n0.add(c); + n1.add(c); + n2.add(c); + + llassert(c.isFinite3()); + + //even out quad contributions + switch (i%2+1) + { + case 0: n0.add(c); break; + case 1: n1.add(c); break; + case 2: n2.add(c); break; + }; + + n0.store4a((F32*) n0p); + n1.store4a((F32*) n1p); + n2.store4a((F32*) n2p); + } + + LL_CHECK_MEMORY + + // adjust normals based on wrapping and stitching + + LLVector4a top; + top.setSub(pos[0], pos[mNumS*(mNumT-2)]); + bool s_bottom_converges = (top.dot3(top) < 0.000001f); + + top.setSub(pos[mNumS-1], pos[mNumS*(mNumT-2)+mNumS-1]); + bool s_top_converges = (top.dot3(top) < 0.000001f); + + if (sculpt_stitching == LL_SCULPT_TYPE_NONE) // logic for non-sculpt volumes + { + if (!volume->getPath().isOpen()) + { //wrap normals on T + for (S32 i = 0; i < mNumS; i++) + { + LLVector4a n; + n.setAdd(norm[i], norm[mNumS*(mNumT-1)+i]); + norm[i] = n; + norm[mNumS*(mNumT-1)+i] = n; + } + } + + if (!volume->getProfile().isOpen() && !s_bottom_converges) + { //wrap normals on S + for (S32 i = 0; i < mNumT; i++) + { + LLVector4a n; + n.setAdd(norm[mNumS*i], norm[mNumS*i+mNumS-1]); + norm[mNumS * i] = n; + norm[mNumS * i+mNumS-1] = n; + } + } + + if (volume->getPathType() == LL_PCODE_PATH_CIRCLE && + ((volume->getProfileType() & LL_PCODE_PROFILE_MASK) == LL_PCODE_PROFILE_CIRCLE_HALF)) + { + if (s_bottom_converges) + { //all lower S have same normal + for (S32 i = 0; i < mNumT; i++) + { + norm[mNumS*i].set(1,0,0); + } + } + + if (s_top_converges) + { //all upper S have same normal + for (S32 i = 0; i < mNumT; i++) + { + norm[mNumS*i+mNumS-1].set(-1,0,0); + } + } + } + } + else // logic for sculpt volumes + { + bool average_poles = false; + bool wrap_s = false; + bool wrap_t = false; + + if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE) + average_poles = true; + + if ((sculpt_stitching == LL_SCULPT_TYPE_SPHERE) || + (sculpt_stitching == LL_SCULPT_TYPE_TORUS) || + (sculpt_stitching == LL_SCULPT_TYPE_CYLINDER)) + wrap_s = true; + + if (sculpt_stitching == LL_SCULPT_TYPE_TORUS) + wrap_t = true; + + + if (average_poles) + { + // average normals for north pole + + LLVector4a average; + average.clear(); + + for (S32 i = 0; i < mNumS; i++) + { + average.add(norm[i]); + } + + // set average + for (S32 i = 0; i < mNumS; i++) + { + norm[i] = average; + } + + // average normals for south pole + + average.clear(); + + for (S32 i = 0; i < mNumS; i++) + { + average.add(norm[i + mNumS * (mNumT - 1)]); + } + + // set average + for (S32 i = 0; i < mNumS; i++) + { + norm[i + mNumS * (mNumT - 1)] = average; + } + + } + + + if (wrap_s) + { + for (S32 i = 0; i < mNumT; i++) + { + LLVector4a n; + n.setAdd(norm[mNumS*i], norm[mNumS*i+mNumS-1]); + norm[mNumS * i] = n; + norm[mNumS * i+mNumS-1] = n; + } + } + + if (wrap_t) + { + for (S32 i = 0; i < mNumS; i++) + { + LLVector4a n; + n.setAdd(norm[i], norm[mNumS*(mNumT-1)+i]); + norm[i] = n; + norm[mNumS*(mNumT-1)+i] = n; + } + } + + } + + LL_CHECK_MEMORY + + return true; } //adapted from Lengyel, Eric. "Computing Tangent Space Basis Vectors for an Arbitrary Mesh". Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html void LLCalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVector4a *normal, const LLVector2 *texcoord, U32 triangleCount, const U16* index_array, LLVector4a *tangent) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME //LLVector4a *tan1 = new LLVector4a[vertexCount * 2]; - LLVector4a* tan1 = (LLVector4a*) ll_aligned_malloc_16(vertexCount*2*sizeof(LLVector4a)); - // new(tan1) LLVector4a; + LLVector4a* tan1 = (LLVector4a*) ll_aligned_malloc_16(vertexCount*2*sizeof(LLVector4a)); + // new(tan1) LLVector4a; LLVector4a* tan2 = tan1 + vertexCount; @@ -7120,86 +7120,86 @@ void LLCalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LL U32 i1 = *index_array++; U32 i2 = *index_array++; U32 i3 = *index_array++; - + const LLVector4a& v1 = vertex[i1]; const LLVector4a& v2 = vertex[i2]; const LLVector4a& v3 = vertex[i3]; - + const LLVector2& w1 = texcoord[i1]; const LLVector2& w2 = texcoord[i2]; const LLVector2& w3 = texcoord[i3]; - - const F32* v1ptr = v1.getF32ptr(); - const F32* v2ptr = v2.getF32ptr(); - const F32* v3ptr = v3.getF32ptr(); - + + const F32* v1ptr = v1.getF32ptr(); + const F32* v2ptr = v2.getF32ptr(); + const F32* v3ptr = v3.getF32ptr(); + float x1 = v2ptr[0] - v1ptr[0]; float x2 = v3ptr[0] - v1ptr[0]; float y1 = v2ptr[1] - v1ptr[1]; float y2 = v3ptr[1] - v1ptr[1]; float z1 = v2ptr[2] - v1ptr[2]; float z2 = v3ptr[2] - v1ptr[2]; - + float s1 = w2.mV[0] - w1.mV[0]; float s2 = w3.mV[0] - w1.mV[0]; float t1 = w2.mV[1] - w1.mV[1]; float t2 = w3.mV[1] - w1.mV[1]; - - F32 rd = s1*t2-s2*t1; - - float r = ((rd*rd) > FLT_EPSILON) ? (1.0f / rd) - : ((rd > 0.0f) ? 1024.f : -1024.f); //some made up large ratio for division by zero - - llassert(llfinite(r)); - llassert(!llisnan(r)); - - LLVector4a sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, - (t2 * z1 - t1 * z2) * r); - LLVector4a tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, - (s1 * z2 - s2 * z1) * r); - - tan1[i1].add(sdir); - tan1[i2].add(sdir); - tan1[i3].add(sdir); - - tan2[i1].add(tdir); - tan2[i2].add(tdir); - tan2[i3].add(tdir); - } - + + F32 rd = s1*t2-s2*t1; + + float r = ((rd*rd) > FLT_EPSILON) ? (1.0f / rd) + : ((rd > 0.0f) ? 1024.f : -1024.f); //some made up large ratio for division by zero + + llassert(llfinite(r)); + llassert(!llisnan(r)); + + LLVector4a sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, + (t2 * z1 - t1 * z2) * r); + LLVector4a tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, + (s1 * z2 - s2 * z1) * r); + + tan1[i1].add(sdir); + tan1[i2].add(sdir); + tan1[i3].add(sdir); + + tan2[i1].add(tdir); + tan2[i2].add(tdir); + tan2[i3].add(tdir); + } + for (U32 a = 0; a < vertexCount; a++) { LLVector4a n = normal[a]; - const LLVector4a& t = tan1[a]; + const LLVector4a& t = tan1[a]; - LLVector4a ncrosst; - ncrosst.setCross3(n,t); + LLVector4a ncrosst; + ncrosst.setCross3(n,t); // Gram-Schmidt orthogonalize n.mul(n.dot3(t).getF32()); - LLVector4a tsubn; - tsubn.setSub(t,n); - - if (tsubn.dot3(tsubn).getF32() > F_APPROXIMATELY_ZERO) - { - tsubn.normalize3fast(); - - // Calculate handedness - F32 handedness = ncrosst.dot3(tan2[a]).getF32() < 0.f ? -1.f : 1.f; - - tsubn.getF32ptr()[3] = handedness; - - tangent[a] = tsubn; - } - else - { //degenerate, make up a value - tangent[a].set(0,0,1,1); - } - } - - ll_aligned_free_16(tan1); + LLVector4a tsubn; + tsubn.setSub(t,n); + + if (tsubn.dot3(tsubn).getF32() > F_APPROXIMATELY_ZERO) + { + tsubn.normalize3fast(); + + // Calculate handedness + F32 handedness = ncrosst.dot3(tan2[a]).getF32() < 0.f ? -1.f : 1.f; + + tsubn.getF32ptr()[3] = handedness; + + tangent[a] = tsubn; + } + else + { //degenerate, make up a value + tangent[a].set(0,0,1,1); + } + } + + ll_aligned_free_16(tan1); } diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 98ad456396..e9261c540c 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -1,25 +1,25 @@ -/** +/** * @file llvolume.h * @brief LLVolume base class. * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -70,8 +70,8 @@ constexpr S32 MAX_LOD = 3; // These are defined here but are not enforced at this level, // rather they are here for the convenience of code that uses // the LLVolume class. -constexpr F32 MIN_VOLUME_PROFILE_WIDTH = 0.05f; -constexpr F32 MIN_VOLUME_PATH_WIDTH = 0.05f; +constexpr F32 MIN_VOLUME_PROFILE_WIDTH = 0.05f; +constexpr F32 MIN_VOLUME_PATH_WIDTH = 0.05f; constexpr F32 CUT_QUANTA = 0.00002f; constexpr F32 SCALE_QUANTA = 0.01f; @@ -85,100 +85,100 @@ constexpr S32 MAX_VOLUME_TRIANGLE_INDICES = 10000; //============================================================================ // useful masks -constexpr LLPCode LL_PCODE_HOLLOW_MASK = 0x80; // has a thickness -constexpr LLPCode LL_PCODE_SEGMENT_MASK = 0x40; // segments (1 angle) -constexpr LLPCode LL_PCODE_PATCH_MASK = 0x20; // segmented segments (2 angles) -constexpr LLPCode LL_PCODE_HEMI_MASK = 0x10; // half-primitives get their own type per PR's dictum -constexpr LLPCode LL_PCODE_BASE_MASK = 0x0F; - - // primitive shapes -constexpr LLPCode LL_PCODE_CUBE = 1; -constexpr LLPCode LL_PCODE_PRISM = 2; -constexpr LLPCode LL_PCODE_TETRAHEDRON = 3; -constexpr LLPCode LL_PCODE_PYRAMID = 4; -constexpr LLPCode LL_PCODE_CYLINDER = 5; -constexpr LLPCode LL_PCODE_CONE = 6; -constexpr LLPCode LL_PCODE_SPHERE = 7; -constexpr LLPCode LL_PCODE_TORUS = 8; -constexpr LLPCode LL_PCODE_VOLUME = 9; - - // surfaces -//constexpr LLPCode LL_PCODE_SURFACE_TRIANGLE = 10; -//constexpr LLPCode LL_PCODE_SURFACE_SQUARE = 11; -//constexpr LLPCode LL_PCODE_SURFACE_DISC = 12; - -constexpr LLPCode LL_PCODE_APP = 14; // App specific pcode (for viewer/sim side only objects) -constexpr LLPCode LL_PCODE_LEGACY = 15; +constexpr LLPCode LL_PCODE_HOLLOW_MASK = 0x80; // has a thickness +constexpr LLPCode LL_PCODE_SEGMENT_MASK = 0x40; // segments (1 angle) +constexpr LLPCode LL_PCODE_PATCH_MASK = 0x20; // segmented segments (2 angles) +constexpr LLPCode LL_PCODE_HEMI_MASK = 0x10; // half-primitives get their own type per PR's dictum +constexpr LLPCode LL_PCODE_BASE_MASK = 0x0F; + + // primitive shapes +constexpr LLPCode LL_PCODE_CUBE = 1; +constexpr LLPCode LL_PCODE_PRISM = 2; +constexpr LLPCode LL_PCODE_TETRAHEDRON = 3; +constexpr LLPCode LL_PCODE_PYRAMID = 4; +constexpr LLPCode LL_PCODE_CYLINDER = 5; +constexpr LLPCode LL_PCODE_CONE = 6; +constexpr LLPCode LL_PCODE_SPHERE = 7; +constexpr LLPCode LL_PCODE_TORUS = 8; +constexpr LLPCode LL_PCODE_VOLUME = 9; + + // surfaces +//constexpr LLPCode LL_PCODE_SURFACE_TRIANGLE = 10; +//constexpr LLPCode LL_PCODE_SURFACE_SQUARE = 11; +//constexpr LLPCode LL_PCODE_SURFACE_DISC = 12; + +constexpr LLPCode LL_PCODE_APP = 14; // App specific pcode (for viewer/sim side only objects) +constexpr LLPCode LL_PCODE_LEGACY = 15; // Pcodes for legacy objects -//constexpr LLPCode LL_PCODE_LEGACY_ATOR = 0x10 | LL_PCODE_LEGACY; // ATOR -constexpr LLPCode LL_PCODE_LEGACY_AVATAR = 0x20 | LL_PCODE_LEGACY; // PLAYER -//constexpr LLPCode LL_PCODE_LEGACY_BIRD = 0x30 | LL_PCODE_LEGACY; // BIRD -//constexpr LLPCode LL_PCODE_LEGACY_DEMON = 0x40 | LL_PCODE_LEGACY; // DEMON -constexpr LLPCode LL_PCODE_LEGACY_GRASS = 0x50 | LL_PCODE_LEGACY; // GRASS -constexpr LLPCode LL_PCODE_TREE_NEW = 0x60 | LL_PCODE_LEGACY; // new trees -//constexpr LLPCode LL_PCODE_LEGACY_ORACLE = 0x70 | LL_PCODE_LEGACY; // ORACLE -constexpr LLPCode LL_PCODE_LEGACY_PART_SYS = 0x80 | LL_PCODE_LEGACY; // PART_SYS -constexpr LLPCode LL_PCODE_LEGACY_ROCK = 0x90 | LL_PCODE_LEGACY; // ROCK -//constexpr LLPCode LL_PCODE_LEGACY_SHOT = 0xA0 | LL_PCODE_LEGACY; // BASIC_SHOT -//constexpr LLPCode LL_PCODE_LEGACY_SHOT_BIG = 0xB0 | LL_PCODE_LEGACY; -//constexpr LLPCode LL_PCODE_LEGACY_SMOKE = 0xC0 | LL_PCODE_LEGACY; // SMOKE -//constexpr LLPCode LL_PCODE_LEGACY_SPARK = 0xD0 | LL_PCODE_LEGACY;// SPARK -constexpr LLPCode LL_PCODE_LEGACY_TEXT_BUBBLE = 0xE0 | LL_PCODE_LEGACY; // TEXTBUBBLE -constexpr LLPCode LL_PCODE_LEGACY_TREE = 0xF0 | LL_PCODE_LEGACY; // TREE - - // hemis -constexpr LLPCode LL_PCODE_CYLINDER_HEMI = LL_PCODE_CYLINDER | LL_PCODE_HEMI_MASK; -constexpr LLPCode LL_PCODE_CONE_HEMI = LL_PCODE_CONE | LL_PCODE_HEMI_MASK; -constexpr LLPCode LL_PCODE_SPHERE_HEMI = LL_PCODE_SPHERE | LL_PCODE_HEMI_MASK; -constexpr LLPCode LL_PCODE_TORUS_HEMI = LL_PCODE_TORUS | LL_PCODE_HEMI_MASK; +//constexpr LLPCode LL_PCODE_LEGACY_ATOR = 0x10 | LL_PCODE_LEGACY; // ATOR +constexpr LLPCode LL_PCODE_LEGACY_AVATAR = 0x20 | LL_PCODE_LEGACY; // PLAYER +//constexpr LLPCode LL_PCODE_LEGACY_BIRD = 0x30 | LL_PCODE_LEGACY; // BIRD +//constexpr LLPCode LL_PCODE_LEGACY_DEMON = 0x40 | LL_PCODE_LEGACY; // DEMON +constexpr LLPCode LL_PCODE_LEGACY_GRASS = 0x50 | LL_PCODE_LEGACY; // GRASS +constexpr LLPCode LL_PCODE_TREE_NEW = 0x60 | LL_PCODE_LEGACY; // new trees +//constexpr LLPCode LL_PCODE_LEGACY_ORACLE = 0x70 | LL_PCODE_LEGACY; // ORACLE +constexpr LLPCode LL_PCODE_LEGACY_PART_SYS = 0x80 | LL_PCODE_LEGACY; // PART_SYS +constexpr LLPCode LL_PCODE_LEGACY_ROCK = 0x90 | LL_PCODE_LEGACY; // ROCK +//constexpr LLPCode LL_PCODE_LEGACY_SHOT = 0xA0 | LL_PCODE_LEGACY; // BASIC_SHOT +//constexpr LLPCode LL_PCODE_LEGACY_SHOT_BIG = 0xB0 | LL_PCODE_LEGACY; +//constexpr LLPCode LL_PCODE_LEGACY_SMOKE = 0xC0 | LL_PCODE_LEGACY; // SMOKE +//constexpr LLPCode LL_PCODE_LEGACY_SPARK = 0xD0 | LL_PCODE_LEGACY;// SPARK +constexpr LLPCode LL_PCODE_LEGACY_TEXT_BUBBLE = 0xE0 | LL_PCODE_LEGACY; // TEXTBUBBLE +constexpr LLPCode LL_PCODE_LEGACY_TREE = 0xF0 | LL_PCODE_LEGACY; // TREE + + // hemis +constexpr LLPCode LL_PCODE_CYLINDER_HEMI = LL_PCODE_CYLINDER | LL_PCODE_HEMI_MASK; +constexpr LLPCode LL_PCODE_CONE_HEMI = LL_PCODE_CONE | LL_PCODE_HEMI_MASK; +constexpr LLPCode LL_PCODE_SPHERE_HEMI = LL_PCODE_SPHERE | LL_PCODE_HEMI_MASK; +constexpr LLPCode LL_PCODE_TORUS_HEMI = LL_PCODE_TORUS | LL_PCODE_HEMI_MASK; // Volumes consist of a profile at the base that is swept around // a path to make a volume. // The profile code -constexpr U8 LL_PCODE_PROFILE_MASK = 0x0f; -constexpr U8 LL_PCODE_PROFILE_MIN = 0x00; -constexpr U8 LL_PCODE_PROFILE_CIRCLE = 0x00; -constexpr U8 LL_PCODE_PROFILE_SQUARE = 0x01; -constexpr U8 LL_PCODE_PROFILE_ISOTRI = 0x02; -constexpr U8 LL_PCODE_PROFILE_EQUALTRI = 0x03; -constexpr U8 LL_PCODE_PROFILE_RIGHTTRI = 0x04; -constexpr U8 LL_PCODE_PROFILE_CIRCLE_HALF = 0x05; -constexpr U8 LL_PCODE_PROFILE_MAX = 0x05; +constexpr U8 LL_PCODE_PROFILE_MASK = 0x0f; +constexpr U8 LL_PCODE_PROFILE_MIN = 0x00; +constexpr U8 LL_PCODE_PROFILE_CIRCLE = 0x00; +constexpr U8 LL_PCODE_PROFILE_SQUARE = 0x01; +constexpr U8 LL_PCODE_PROFILE_ISOTRI = 0x02; +constexpr U8 LL_PCODE_PROFILE_EQUALTRI = 0x03; +constexpr U8 LL_PCODE_PROFILE_RIGHTTRI = 0x04; +constexpr U8 LL_PCODE_PROFILE_CIRCLE_HALF = 0x05; +constexpr U8 LL_PCODE_PROFILE_MAX = 0x05; // Stored in the profile byte -constexpr U8 LL_PCODE_HOLE_MASK = 0xf0; -constexpr U8 LL_PCODE_HOLE_MIN = 0x00; -constexpr U8 LL_PCODE_HOLE_SAME = 0x00; // same as outside profile -constexpr U8 LL_PCODE_HOLE_CIRCLE = 0x10; -constexpr U8 LL_PCODE_HOLE_SQUARE = 0x20; -constexpr U8 LL_PCODE_HOLE_TRIANGLE = 0x30; -constexpr U8 LL_PCODE_HOLE_MAX = 0x03; // min/max needs to be >> 4 of real min/max +constexpr U8 LL_PCODE_HOLE_MASK = 0xf0; +constexpr U8 LL_PCODE_HOLE_MIN = 0x00; +constexpr U8 LL_PCODE_HOLE_SAME = 0x00; // same as outside profile +constexpr U8 LL_PCODE_HOLE_CIRCLE = 0x10; +constexpr U8 LL_PCODE_HOLE_SQUARE = 0x20; +constexpr U8 LL_PCODE_HOLE_TRIANGLE = 0x30; +constexpr U8 LL_PCODE_HOLE_MAX = 0x03; // min/max needs to be >> 4 of real min/max constexpr U8 LL_PCODE_PATH_IGNORE = 0x00; -constexpr U8 LL_PCODE_PATH_MIN = 0x01; // min/max needs to be >> 4 of real min/max +constexpr U8 LL_PCODE_PATH_MIN = 0x01; // min/max needs to be >> 4 of real min/max constexpr U8 LL_PCODE_PATH_LINE = 0x10; constexpr U8 LL_PCODE_PATH_CIRCLE = 0x20; constexpr U8 LL_PCODE_PATH_CIRCLE2 = 0x30; constexpr U8 LL_PCODE_PATH_TEST = 0x40; constexpr U8 LL_PCODE_PATH_FLEXIBLE = 0x80; -constexpr U8 LL_PCODE_PATH_MAX = 0x08; +constexpr U8 LL_PCODE_PATH_MAX = 0x08; //============================================================================ // face identifiers typedef U16 LLFaceID; -constexpr LLFaceID LL_FACE_PATH_BEGIN = 0x1 << 0; -constexpr LLFaceID LL_FACE_PATH_END = 0x1 << 1; -constexpr LLFaceID LL_FACE_INNER_SIDE = 0x1 << 2; -constexpr LLFaceID LL_FACE_PROFILE_BEGIN = 0x1 << 3; -constexpr LLFaceID LL_FACE_PROFILE_END = 0x1 << 4; -constexpr LLFaceID LL_FACE_OUTER_SIDE_0 = 0x1 << 5; -constexpr LLFaceID LL_FACE_OUTER_SIDE_1 = 0x1 << 6; -constexpr LLFaceID LL_FACE_OUTER_SIDE_2 = 0x1 << 7; -constexpr LLFaceID LL_FACE_OUTER_SIDE_3 = 0x1 << 8; +constexpr LLFaceID LL_FACE_PATH_BEGIN = 0x1 << 0; +constexpr LLFaceID LL_FACE_PATH_END = 0x1 << 1; +constexpr LLFaceID LL_FACE_INNER_SIDE = 0x1 << 2; +constexpr LLFaceID LL_FACE_PROFILE_BEGIN = 0x1 << 3; +constexpr LLFaceID LL_FACE_PROFILE_END = 0x1 << 4; +constexpr LLFaceID LL_FACE_OUTER_SIDE_0 = 0x1 << 5; +constexpr LLFaceID LL_FACE_OUTER_SIDE_1 = 0x1 << 6; +constexpr LLFaceID LL_FACE_OUTER_SIDE_2 = 0x1 << 7; +constexpr LLFaceID LL_FACE_OUTER_SIDE_3 = 0x1 << 8; //============================================================================ @@ -191,7 +191,7 @@ constexpr U8 LL_SCULPT_TYPE_PLANE = 3; constexpr U8 LL_SCULPT_TYPE_CYLINDER = 4; constexpr U8 LL_SCULPT_TYPE_MESH = 5; constexpr U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE | - LL_SCULPT_TYPE_CYLINDER | LL_SCULPT_TYPE_MESH; + LL_SCULPT_TYPE_CYLINDER | LL_SCULPT_TYPE_MESH; // for value checks, assign new value after adding new types constexpr U8 LL_SCULPT_TYPE_MAX = LL_SCULPT_TYPE_MESH; @@ -207,125 +207,125 @@ extern bool gDebugGL; class LLProfileParams { public: - LLProfileParams() - : mCurveType(LL_PCODE_PROFILE_SQUARE), - mBegin(0.f), - mEnd(1.f), - mHollow(0.f), - mCRC(0) - { - } - - LLProfileParams(U8 curve, F32 begin, F32 end, F32 hollow) - : mCurveType(curve), - mBegin(begin), - mEnd(end), - mHollow(hollow), - mCRC(0) - { - } - - LLProfileParams(U8 curve, U16 begin, U16 end, U16 hollow) - { - mCurveType = curve; - F32 temp_f32 = begin * CUT_QUANTA; - if (temp_f32 > 1.f) - { - temp_f32 = 1.f; - } - mBegin = temp_f32; - temp_f32 = end * CUT_QUANTA; - if (temp_f32 > 1.f) - { - temp_f32 = 1.f; - } - mEnd = 1.f - temp_f32; - temp_f32 = hollow * HOLLOW_QUANTA; - if (temp_f32 > 1.f) - { - temp_f32 = 1.f; - } - mHollow = temp_f32; - mCRC = 0; - } - - bool operator==(const LLProfileParams ¶ms) const; - bool operator!=(const LLProfileParams ¶ms) const; - bool operator<(const LLProfileParams ¶ms) const; - - void copyParams(const LLProfileParams ¶ms); - - bool importFile(LLFILE *fp); - bool exportFile(LLFILE *fp) const; - - bool importLegacyStream(std::istream& input_stream); - bool exportLegacyStream(std::ostream& output_stream) const; - - LLSD asLLSD() const; - operator LLSD() const { return asLLSD(); } - bool fromLLSD(LLSD& sd); - - const F32& getBegin () const { return mBegin; } - const F32& getEnd () const { return mEnd; } - const F32& getHollow() const { return mHollow; } - const U8& getCurveType () const { return mCurveType; } - - void setCurveType(const U32 type) { mCurveType = type;} - void setBegin(const F32 begin) { mBegin = (begin >= 1.0f) ? 0.0f : ((int) (begin * 100000))/100000.0f;} - void setEnd(const F32 end) { mEnd = (end <= 0.0f) ? 1.0f : ((int) (end * 100000))/100000.0f;} - void setHollow(const F32 hollow) { mHollow = ((int) (hollow * 100000))/100000.0f;} - - friend std::ostream& operator<<(std::ostream &s, const LLProfileParams &profile_params); + LLProfileParams() + : mCurveType(LL_PCODE_PROFILE_SQUARE), + mBegin(0.f), + mEnd(1.f), + mHollow(0.f), + mCRC(0) + { + } + + LLProfileParams(U8 curve, F32 begin, F32 end, F32 hollow) + : mCurveType(curve), + mBegin(begin), + mEnd(end), + mHollow(hollow), + mCRC(0) + { + } + + LLProfileParams(U8 curve, U16 begin, U16 end, U16 hollow) + { + mCurveType = curve; + F32 temp_f32 = begin * CUT_QUANTA; + if (temp_f32 > 1.f) + { + temp_f32 = 1.f; + } + mBegin = temp_f32; + temp_f32 = end * CUT_QUANTA; + if (temp_f32 > 1.f) + { + temp_f32 = 1.f; + } + mEnd = 1.f - temp_f32; + temp_f32 = hollow * HOLLOW_QUANTA; + if (temp_f32 > 1.f) + { + temp_f32 = 1.f; + } + mHollow = temp_f32; + mCRC = 0; + } + + bool operator==(const LLProfileParams ¶ms) const; + bool operator!=(const LLProfileParams ¶ms) const; + bool operator<(const LLProfileParams ¶ms) const; + + void copyParams(const LLProfileParams ¶ms); + + bool importFile(LLFILE *fp); + bool exportFile(LLFILE *fp) const; + + bool importLegacyStream(std::istream& input_stream); + bool exportLegacyStream(std::ostream& output_stream) const; + + LLSD asLLSD() const; + operator LLSD() const { return asLLSD(); } + bool fromLLSD(LLSD& sd); + + const F32& getBegin () const { return mBegin; } + const F32& getEnd () const { return mEnd; } + const F32& getHollow() const { return mHollow; } + const U8& getCurveType () const { return mCurveType; } + + void setCurveType(const U32 type) { mCurveType = type;} + void setBegin(const F32 begin) { mBegin = (begin >= 1.0f) ? 0.0f : ((int) (begin * 100000))/100000.0f;} + void setEnd(const F32 end) { mEnd = (end <= 0.0f) ? 1.0f : ((int) (end * 100000))/100000.0f;} + void setHollow(const F32 hollow) { mHollow = ((int) (hollow * 100000))/100000.0f;} + + friend std::ostream& operator<<(std::ostream &s, const LLProfileParams &profile_params); protected: - // Profile params - U8 mCurveType; - F32 mBegin; - F32 mEnd; - F32 mHollow; + // Profile params + U8 mCurveType; + F32 mBegin; + F32 mEnd; + F32 mHollow; - U32 mCRC; + U32 mCRC; }; inline bool LLProfileParams::operator==(const LLProfileParams ¶ms) const { - return - (getCurveType() == params.getCurveType()) && - (getBegin() == params.getBegin()) && - (getEnd() == params.getEnd()) && - (getHollow() == params.getHollow()); + return + (getCurveType() == params.getCurveType()) && + (getBegin() == params.getBegin()) && + (getEnd() == params.getEnd()) && + (getHollow() == params.getHollow()); } inline bool LLProfileParams::operator!=(const LLProfileParams ¶ms) const { - return - (getCurveType() != params.getCurveType()) || - (getBegin() != params.getBegin()) || - (getEnd() != params.getEnd()) || - (getHollow() != params.getHollow()); + return + (getCurveType() != params.getCurveType()) || + (getBegin() != params.getBegin()) || + (getEnd() != params.getEnd()) || + (getHollow() != params.getHollow()); } inline bool LLProfileParams::operator<(const LLProfileParams ¶ms) const { - if (getCurveType() != params.getCurveType()) - { - return getCurveType() < params.getCurveType(); - } - else - if (getBegin() != params.getBegin()) - { - return getBegin() < params.getBegin(); - } - else - if (getEnd() != params.getEnd()) - { - return getEnd() < params.getEnd(); - } - else - { - return getHollow() < params.getHollow(); - } + if (getCurveType() != params.getCurveType()) + { + return getCurveType() < params.getCurveType(); + } + else + if (getBegin() != params.getBegin()) + { + return getBegin() < params.getBegin(); + } + else + if (getEnd() != params.getEnd()) + { + return getEnd() < params.getEnd(); + } + else + { + return getHollow() < params.getHollow(); + } } #define U8_TO_F32(x) (F32)(*((S8 *)&x)) @@ -333,225 +333,225 @@ inline bool LLProfileParams::operator<(const LLProfileParams ¶ms) const class LLPathParams { public: - LLPathParams() - : - mCurveType(LL_PCODE_PATH_LINE), - mBegin(0.f), - mEnd(1.f), - mScale(1.f,1.f), - mShear(0.f,0.f), - mTwistBegin(0.f), - mTwistEnd(0.f), - mRadiusOffset(0.f), - mTaper(0.f,0.f), - mRevolutions(1.f), - mSkew(0.f), - mCRC(0) - { - } - - LLPathParams(U8 curve, F32 begin, F32 end, F32 scx, F32 scy, F32 shx, F32 shy, F32 twistend, F32 twistbegin, F32 radiusoffset, F32 tx, F32 ty, F32 revolutions, F32 skew) - : mCurveType(curve), - mBegin(begin), - mEnd(end), - mScale(scx,scy), - mShear(shx,shy), - mTwistBegin(twistbegin), - mTwistEnd(twistend), - mRadiusOffset(radiusoffset), - mTaper(tx,ty), - mRevolutions(revolutions), - mSkew(skew), - mCRC(0) - { - } - - LLPathParams(U8 curve, U16 begin, U16 end, U8 scx, U8 scy, U8 shx, U8 shy, U8 twistend, U8 twistbegin, U8 radiusoffset, U8 tx, U8 ty, U8 revolutions, U8 skew) - { - mCurveType = curve; - mBegin = (F32)(begin * CUT_QUANTA); - mEnd = (F32)(100.f - end) * CUT_QUANTA; - if (mEnd > 1.f) - mEnd = 1.f; - mScale.setVec((F32) (200 - scx) * SCALE_QUANTA,(F32) (200 - scy) * SCALE_QUANTA); - mShear.setVec(U8_TO_F32(shx) * SHEAR_QUANTA,U8_TO_F32(shy) * SHEAR_QUANTA); - mTwistBegin = U8_TO_F32(twistbegin) * SCALE_QUANTA; - mTwistEnd = U8_TO_F32(twistend) * SCALE_QUANTA; - mRadiusOffset = U8_TO_F32(radiusoffset) * SCALE_QUANTA; - mTaper.setVec(U8_TO_F32(tx) * TAPER_QUANTA,U8_TO_F32(ty) * TAPER_QUANTA); - mRevolutions = ((F32)revolutions) * REV_QUANTA + 1.0f; - mSkew = U8_TO_F32(skew) * SCALE_QUANTA; - - mCRC = 0; - } - - bool operator==(const LLPathParams ¶ms) const; - bool operator!=(const LLPathParams ¶ms) const; - bool operator<(const LLPathParams ¶ms) const; - - void copyParams(const LLPathParams ¶ms); - - bool importFile(LLFILE *fp); - bool exportFile(LLFILE *fp) const; - - bool importLegacyStream(std::istream& input_stream); - bool exportLegacyStream(std::ostream& output_stream) const; - - LLSD asLLSD() const; - operator LLSD() const { return asLLSD(); } - bool fromLLSD(LLSD& sd); - - const F32& getBegin() const { return mBegin; } - const F32& getEnd() const { return mEnd; } - const LLVector2 &getScale() const { return mScale; } - const F32& getScaleX() const { return mScale.mV[0]; } - const F32& getScaleY() const { return mScale.mV[1]; } - const LLVector2 getBeginScale() const; - const LLVector2 getEndScale() const; - const LLVector2 &getShear() const { return mShear; } - const F32& getShearX() const { return mShear.mV[0]; } - const F32& getShearY() const { return mShear.mV[1]; } - const U8& getCurveType () const { return mCurveType; } - - const F32& getTwistBegin() const { return mTwistBegin; } - const F32& getTwistEnd() const { return mTwistEnd; } - const F32& getTwist() const { return mTwistEnd; } // deprecated - const F32& getRadiusOffset() const { return mRadiusOffset; } - const LLVector2 &getTaper() const { return mTaper; } - const F32& getTaperX() const { return mTaper.mV[0]; } - const F32& getTaperY() const { return mTaper.mV[1]; } - const F32& getRevolutions() const { return mRevolutions; } - const F32& getSkew() const { return mSkew; } - - void setCurveType(const U8 type) { mCurveType = type; } - void setBegin(const F32 begin) { mBegin = begin; } - void setEnd(const F32 end) { mEnd = end; } - - void setScale(const F32 x, const F32 y) { mScale.setVec(x,y); } - void setScaleX(const F32 v) { mScale.mV[VX] = v; } - void setScaleY(const F32 v) { mScale.mV[VY] = v; } - void setShear(const F32 x, const F32 y) { mShear.setVec(x,y); } - void setShearX(const F32 v) { mShear.mV[VX] = v; } - void setShearY(const F32 v) { mShear.mV[VY] = v; } - - void setTwistBegin(const F32 twist_begin) { mTwistBegin = twist_begin; } - void setTwistEnd(const F32 twist_end) { mTwistEnd = twist_end; } - void setTwist(const F32 twist) { setTwistEnd(twist); } // deprecated - void setRadiusOffset(const F32 radius_offset){ mRadiusOffset = radius_offset; } - void setTaper(const F32 x, const F32 y) { mTaper.setVec(x,y); } - void setTaperX(const F32 v) { mTaper.mV[VX] = v; } - void setTaperY(const F32 v) { mTaper.mV[VY] = v; } - void setRevolutions(const F32 revolutions) { mRevolutions = revolutions; } - void setSkew(const F32 skew) { mSkew = skew; } - - friend std::ostream& operator<<(std::ostream &s, const LLPathParams &path_params); + LLPathParams() + : + mCurveType(LL_PCODE_PATH_LINE), + mBegin(0.f), + mEnd(1.f), + mScale(1.f,1.f), + mShear(0.f,0.f), + mTwistBegin(0.f), + mTwistEnd(0.f), + mRadiusOffset(0.f), + mTaper(0.f,0.f), + mRevolutions(1.f), + mSkew(0.f), + mCRC(0) + { + } + + LLPathParams(U8 curve, F32 begin, F32 end, F32 scx, F32 scy, F32 shx, F32 shy, F32 twistend, F32 twistbegin, F32 radiusoffset, F32 tx, F32 ty, F32 revolutions, F32 skew) + : mCurveType(curve), + mBegin(begin), + mEnd(end), + mScale(scx,scy), + mShear(shx,shy), + mTwistBegin(twistbegin), + mTwistEnd(twistend), + mRadiusOffset(radiusoffset), + mTaper(tx,ty), + mRevolutions(revolutions), + mSkew(skew), + mCRC(0) + { + } + + LLPathParams(U8 curve, U16 begin, U16 end, U8 scx, U8 scy, U8 shx, U8 shy, U8 twistend, U8 twistbegin, U8 radiusoffset, U8 tx, U8 ty, U8 revolutions, U8 skew) + { + mCurveType = curve; + mBegin = (F32)(begin * CUT_QUANTA); + mEnd = (F32)(100.f - end) * CUT_QUANTA; + if (mEnd > 1.f) + mEnd = 1.f; + mScale.setVec((F32) (200 - scx) * SCALE_QUANTA,(F32) (200 - scy) * SCALE_QUANTA); + mShear.setVec(U8_TO_F32(shx) * SHEAR_QUANTA,U8_TO_F32(shy) * SHEAR_QUANTA); + mTwistBegin = U8_TO_F32(twistbegin) * SCALE_QUANTA; + mTwistEnd = U8_TO_F32(twistend) * SCALE_QUANTA; + mRadiusOffset = U8_TO_F32(radiusoffset) * SCALE_QUANTA; + mTaper.setVec(U8_TO_F32(tx) * TAPER_QUANTA,U8_TO_F32(ty) * TAPER_QUANTA); + mRevolutions = ((F32)revolutions) * REV_QUANTA + 1.0f; + mSkew = U8_TO_F32(skew) * SCALE_QUANTA; + + mCRC = 0; + } + + bool operator==(const LLPathParams ¶ms) const; + bool operator!=(const LLPathParams ¶ms) const; + bool operator<(const LLPathParams ¶ms) const; + + void copyParams(const LLPathParams ¶ms); + + bool importFile(LLFILE *fp); + bool exportFile(LLFILE *fp) const; + + bool importLegacyStream(std::istream& input_stream); + bool exportLegacyStream(std::ostream& output_stream) const; + + LLSD asLLSD() const; + operator LLSD() const { return asLLSD(); } + bool fromLLSD(LLSD& sd); + + const F32& getBegin() const { return mBegin; } + const F32& getEnd() const { return mEnd; } + const LLVector2 &getScale() const { return mScale; } + const F32& getScaleX() const { return mScale.mV[0]; } + const F32& getScaleY() const { return mScale.mV[1]; } + const LLVector2 getBeginScale() const; + const LLVector2 getEndScale() const; + const LLVector2 &getShear() const { return mShear; } + const F32& getShearX() const { return mShear.mV[0]; } + const F32& getShearY() const { return mShear.mV[1]; } + const U8& getCurveType () const { return mCurveType; } + + const F32& getTwistBegin() const { return mTwistBegin; } + const F32& getTwistEnd() const { return mTwistEnd; } + const F32& getTwist() const { return mTwistEnd; } // deprecated + const F32& getRadiusOffset() const { return mRadiusOffset; } + const LLVector2 &getTaper() const { return mTaper; } + const F32& getTaperX() const { return mTaper.mV[0]; } + const F32& getTaperY() const { return mTaper.mV[1]; } + const F32& getRevolutions() const { return mRevolutions; } + const F32& getSkew() const { return mSkew; } + + void setCurveType(const U8 type) { mCurveType = type; } + void setBegin(const F32 begin) { mBegin = begin; } + void setEnd(const F32 end) { mEnd = end; } + + void setScale(const F32 x, const F32 y) { mScale.setVec(x,y); } + void setScaleX(const F32 v) { mScale.mV[VX] = v; } + void setScaleY(const F32 v) { mScale.mV[VY] = v; } + void setShear(const F32 x, const F32 y) { mShear.setVec(x,y); } + void setShearX(const F32 v) { mShear.mV[VX] = v; } + void setShearY(const F32 v) { mShear.mV[VY] = v; } + + void setTwistBegin(const F32 twist_begin) { mTwistBegin = twist_begin; } + void setTwistEnd(const F32 twist_end) { mTwistEnd = twist_end; } + void setTwist(const F32 twist) { setTwistEnd(twist); } // deprecated + void setRadiusOffset(const F32 radius_offset){ mRadiusOffset = radius_offset; } + void setTaper(const F32 x, const F32 y) { mTaper.setVec(x,y); } + void setTaperX(const F32 v) { mTaper.mV[VX] = v; } + void setTaperY(const F32 v) { mTaper.mV[VY] = v; } + void setRevolutions(const F32 revolutions) { mRevolutions = revolutions; } + void setSkew(const F32 skew) { mSkew = skew; } + + friend std::ostream& operator<<(std::ostream &s, const LLPathParams &path_params); protected: - // Path params - U8 mCurveType; - F32 mBegin; - F32 mEnd; - LLVector2 mScale; - LLVector2 mShear; - - F32 mTwistBegin; - F32 mTwistEnd; - F32 mRadiusOffset; - LLVector2 mTaper; - F32 mRevolutions; - F32 mSkew; - - U32 mCRC; + // Path params + U8 mCurveType; + F32 mBegin; + F32 mEnd; + LLVector2 mScale; + LLVector2 mShear; + + F32 mTwistBegin; + F32 mTwistEnd; + F32 mRadiusOffset; + LLVector2 mTaper; + F32 mRevolutions; + F32 mSkew; + + U32 mCRC; }; inline bool LLPathParams::operator==(const LLPathParams ¶ms) const { - return - (getCurveType() == params.getCurveType()) && - (getScale() == params.getScale()) && - (getBegin() == params.getBegin()) && - (getEnd() == params.getEnd()) && - (getShear() == params.getShear()) && - (getTwist() == params.getTwist()) && - (getTwistBegin() == params.getTwistBegin()) && - (getRadiusOffset() == params.getRadiusOffset()) && - (getTaper() == params.getTaper()) && - (getRevolutions() == params.getRevolutions()) && - (getSkew() == params.getSkew()); + return + (getCurveType() == params.getCurveType()) && + (getScale() == params.getScale()) && + (getBegin() == params.getBegin()) && + (getEnd() == params.getEnd()) && + (getShear() == params.getShear()) && + (getTwist() == params.getTwist()) && + (getTwistBegin() == params.getTwistBegin()) && + (getRadiusOffset() == params.getRadiusOffset()) && + (getTaper() == params.getTaper()) && + (getRevolutions() == params.getRevolutions()) && + (getSkew() == params.getSkew()); } inline bool LLPathParams::operator!=(const LLPathParams ¶ms) const { - return - (getCurveType() != params.getCurveType()) || - (getScale() != params.getScale()) || - (getBegin() != params.getBegin()) || - (getEnd() != params.getEnd()) || - (getShear() != params.getShear()) || - (getTwist() != params.getTwist()) || - (getTwistBegin() !=params.getTwistBegin()) || - (getRadiusOffset() != params.getRadiusOffset()) || - (getTaper() != params.getTaper()) || - (getRevolutions() != params.getRevolutions()) || - (getSkew() != params.getSkew()); + return + (getCurveType() != params.getCurveType()) || + (getScale() != params.getScale()) || + (getBegin() != params.getBegin()) || + (getEnd() != params.getEnd()) || + (getShear() != params.getShear()) || + (getTwist() != params.getTwist()) || + (getTwistBegin() !=params.getTwistBegin()) || + (getRadiusOffset() != params.getRadiusOffset()) || + (getTaper() != params.getTaper()) || + (getRevolutions() != params.getRevolutions()) || + (getSkew() != params.getSkew()); } inline bool LLPathParams::operator<(const LLPathParams ¶ms) const { - if( getCurveType() != params.getCurveType()) - { - return getCurveType() < params.getCurveType(); - } - else - if( getScale() != params.getScale()) - { - return getScale() < params.getScale(); - } - else - if( getBegin() != params.getBegin()) - { - return getBegin() < params.getBegin(); - } - else - if( getEnd() != params.getEnd()) - { - return getEnd() < params.getEnd(); - } - else - if( getShear() != params.getShear()) - { - return getShear() < params.getShear(); - } - else - if( getTwist() != params.getTwist()) - { - return getTwist() < params.getTwist(); - } - else - if( getTwistBegin() != params.getTwistBegin()) - { - return getTwistBegin() < params.getTwistBegin(); - } - else - if( getRadiusOffset() != params.getRadiusOffset()) - { - return getRadiusOffset() < params.getRadiusOffset(); - } - else - if( getTaper() != params.getTaper()) - { - return getTaper() < params.getTaper(); - } - else - if( getRevolutions() != params.getRevolutions()) - { - return getRevolutions() < params.getRevolutions(); - } - else - { - return getSkew() < params.getSkew(); - } + if( getCurveType() != params.getCurveType()) + { + return getCurveType() < params.getCurveType(); + } + else + if( getScale() != params.getScale()) + { + return getScale() < params.getScale(); + } + else + if( getBegin() != params.getBegin()) + { + return getBegin() < params.getBegin(); + } + else + if( getEnd() != params.getEnd()) + { + return getEnd() < params.getEnd(); + } + else + if( getShear() != params.getShear()) + { + return getShear() < params.getShear(); + } + else + if( getTwist() != params.getTwist()) + { + return getTwist() < params.getTwist(); + } + else + if( getTwistBegin() != params.getTwistBegin()) + { + return getTwistBegin() < params.getTwistBegin(); + } + else + if( getRadiusOffset() != params.getRadiusOffset()) + { + return getRadiusOffset() < params.getRadiusOffset(); + } + else + if( getTaper() != params.getTaper()) + { + return getTaper() < params.getTaper(); + } + else + if( getRevolutions() != params.getRevolutions()) + { + return getRevolutions() < params.getRevolutions(); + } + else + { + return getSkew() < params.getSkew(); + } } typedef LLVolumeParams* LLVolumeParamsPtr; @@ -560,190 +560,190 @@ typedef const LLVolumeParams* const_LLVolumeParamsPtr; class LLVolumeParams { public: - LLVolumeParams() - : mSculptType(LL_SCULPT_TYPE_NONE) - { - } - - LLVolumeParams(LLProfileParams &profile, LLPathParams &path, - LLUUID sculpt_id = LLUUID::null, U8 sculpt_type = LL_SCULPT_TYPE_NONE) - : mProfileParams(profile), mPathParams(path), mSculptID(sculpt_id), mSculptType(sculpt_type) - { - } - - bool operator==(const LLVolumeParams ¶ms) const; - bool operator!=(const LLVolumeParams ¶ms) const; - bool operator<(const LLVolumeParams ¶ms) const; - - - void copyParams(const LLVolumeParams ¶ms); - - const LLProfileParams &getProfileParams() const {return mProfileParams;} - LLProfileParams &getProfileParams() {return mProfileParams;} - const LLPathParams &getPathParams() const {return mPathParams;} - LLPathParams &getPathParams() {return mPathParams;} - - bool importFile(LLFILE *fp); - bool exportFile(LLFILE *fp) const; - - bool importLegacyStream(std::istream& input_stream); - bool exportLegacyStream(std::ostream& output_stream) const; - - LLSD sculptAsLLSD() const; - bool sculptFromLLSD(LLSD& sd); - - LLSD asLLSD() const; - operator LLSD() const { return asLLSD(); } - bool fromLLSD(LLSD& sd); - - bool setType(U8 profile, U8 path); - - //void setBeginS(const F32 beginS) { mProfileParams.setBegin(beginS); } // range 0 to 1 - //void setBeginT(const F32 beginT) { mPathParams.setBegin(beginT); } // range 0 to 1 - //void setEndS(const F32 endS) { mProfileParams.setEnd(endS); } // range 0 to 1, must be greater than begin - //void setEndT(const F32 endT) { mPathParams.setEnd(endT); } // range 0 to 1, must be greater than begin - - bool setBeginAndEndS(const F32 begin, const F32 end); // both range from 0 to 1, begin must be less than end - bool setBeginAndEndT(const F32 begin, const F32 end); // both range from 0 to 1, begin must be less than end - - bool setHollow(const F32 hollow); // range 0 to 1 - bool setRatio(const F32 x) { return setRatio(x,x); } // 0 = point, 1 = same as base - bool setShear(const F32 x) { return setShear(x,x); } // 0 = no movement, - bool setRatio(const F32 x, const F32 y); // 0 = point, 1 = same as base - bool setShear(const F32 x, const F32 y); // 0 = no movement - - bool setTwistBegin(const F32 twist_begin); // range -1 to 1 - bool setTwistEnd(const F32 twist_end); // range -1 to 1 - bool setTwist(const F32 twist) { return setTwistEnd(twist); } // deprecated - bool setTaper(const F32 x, const F32 y) { bool pass_x = setTaperX(x); bool pass_y = setTaperY(y); return pass_x && pass_y; } - bool setTaperX(const F32 v); // -1 to 1 - bool setTaperY(const F32 v); // -1 to 1 - bool setRevolutions(const F32 revolutions); // 1 to 4 - bool setRadiusOffset(const F32 radius_offset); - bool setSkew(const F32 skew); - bool setSculptID(const LLUUID& sculpt_id, U8 sculpt_type); - - static bool validate(U8 prof_curve, F32 prof_begin, F32 prof_end, F32 hollow, - U8 path_curve, F32 path_begin, F32 path_end, - F32 scx, F32 scy, F32 shx, F32 shy, - F32 twistend, F32 twistbegin, F32 radiusoffset, - F32 tx, F32 ty, F32 revolutions, F32 skew); - - const F32& getBeginS() const { return mProfileParams.getBegin(); } - const F32& getBeginT() const { return mPathParams.getBegin(); } - const F32& getEndS() const { return mProfileParams.getEnd(); } - const F32& getEndT() const { return mPathParams.getEnd(); } - - const F32& getHollow() const { return mProfileParams.getHollow(); } - const F32& getTwist() const { return mPathParams.getTwist(); } - const F32& getRatio() const { return mPathParams.getScaleX(); } - const F32& getRatioX() const { return mPathParams.getScaleX(); } - const F32& getRatioY() const { return mPathParams.getScaleY(); } - const F32& getShearX() const { return mPathParams.getShearX(); } - const F32& getShearY() const { return mPathParams.getShearY(); } - - const F32& getTwistBegin()const { return mPathParams.getTwistBegin(); } - const F32& getRadiusOffset() const { return mPathParams.getRadiusOffset(); } - const F32& getTaper() const { return mPathParams.getTaperX(); } - const F32& getTaperX() const { return mPathParams.getTaperX(); } - const F32& getTaperY() const { return mPathParams.getTaperY(); } - const F32& getRevolutions() const { return mPathParams.getRevolutions(); } - const F32& getSkew() const { return mPathParams.getSkew(); } - const LLUUID& getSculptID() const { return mSculptID; } - const U8& getSculptType() const { return mSculptType; } - bool isSculpt() const; - bool isMeshSculpt() const; - bool isConvex() const; - - // 'begin' and 'end' should be in range [0, 1] (they will be clamped) - // (begin, end) = (0, 1) will not change the volume - // (begin, end) = (0, 0.5) will reduce the volume to the first half of its profile/path (S/T) - void reduceS(F32 begin, F32 end); - void reduceT(F32 begin, F32 end); - - struct compare - { - bool operator()( const const_LLVolumeParamsPtr& first, const const_LLVolumeParamsPtr& second) const - { - return (*first < *second); - } - }; - - friend std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params); - - // debug helper functions - void setCube(); + LLVolumeParams() + : mSculptType(LL_SCULPT_TYPE_NONE) + { + } + + LLVolumeParams(LLProfileParams &profile, LLPathParams &path, + LLUUID sculpt_id = LLUUID::null, U8 sculpt_type = LL_SCULPT_TYPE_NONE) + : mProfileParams(profile), mPathParams(path), mSculptID(sculpt_id), mSculptType(sculpt_type) + { + } + + bool operator==(const LLVolumeParams ¶ms) const; + bool operator!=(const LLVolumeParams ¶ms) const; + bool operator<(const LLVolumeParams ¶ms) const; + + + void copyParams(const LLVolumeParams ¶ms); + + const LLProfileParams &getProfileParams() const {return mProfileParams;} + LLProfileParams &getProfileParams() {return mProfileParams;} + const LLPathParams &getPathParams() const {return mPathParams;} + LLPathParams &getPathParams() {return mPathParams;} + + bool importFile(LLFILE *fp); + bool exportFile(LLFILE *fp) const; + + bool importLegacyStream(std::istream& input_stream); + bool exportLegacyStream(std::ostream& output_stream) const; + + LLSD sculptAsLLSD() const; + bool sculptFromLLSD(LLSD& sd); + + LLSD asLLSD() const; + operator LLSD() const { return asLLSD(); } + bool fromLLSD(LLSD& sd); + + bool setType(U8 profile, U8 path); + + //void setBeginS(const F32 beginS) { mProfileParams.setBegin(beginS); } // range 0 to 1 + //void setBeginT(const F32 beginT) { mPathParams.setBegin(beginT); } // range 0 to 1 + //void setEndS(const F32 endS) { mProfileParams.setEnd(endS); } // range 0 to 1, must be greater than begin + //void setEndT(const F32 endT) { mPathParams.setEnd(endT); } // range 0 to 1, must be greater than begin + + bool setBeginAndEndS(const F32 begin, const F32 end); // both range from 0 to 1, begin must be less than end + bool setBeginAndEndT(const F32 begin, const F32 end); // both range from 0 to 1, begin must be less than end + + bool setHollow(const F32 hollow); // range 0 to 1 + bool setRatio(const F32 x) { return setRatio(x,x); } // 0 = point, 1 = same as base + bool setShear(const F32 x) { return setShear(x,x); } // 0 = no movement, + bool setRatio(const F32 x, const F32 y); // 0 = point, 1 = same as base + bool setShear(const F32 x, const F32 y); // 0 = no movement + + bool setTwistBegin(const F32 twist_begin); // range -1 to 1 + bool setTwistEnd(const F32 twist_end); // range -1 to 1 + bool setTwist(const F32 twist) { return setTwistEnd(twist); } // deprecated + bool setTaper(const F32 x, const F32 y) { bool pass_x = setTaperX(x); bool pass_y = setTaperY(y); return pass_x && pass_y; } + bool setTaperX(const F32 v); // -1 to 1 + bool setTaperY(const F32 v); // -1 to 1 + bool setRevolutions(const F32 revolutions); // 1 to 4 + bool setRadiusOffset(const F32 radius_offset); + bool setSkew(const F32 skew); + bool setSculptID(const LLUUID& sculpt_id, U8 sculpt_type); + + static bool validate(U8 prof_curve, F32 prof_begin, F32 prof_end, F32 hollow, + U8 path_curve, F32 path_begin, F32 path_end, + F32 scx, F32 scy, F32 shx, F32 shy, + F32 twistend, F32 twistbegin, F32 radiusoffset, + F32 tx, F32 ty, F32 revolutions, F32 skew); + + const F32& getBeginS() const { return mProfileParams.getBegin(); } + const F32& getBeginT() const { return mPathParams.getBegin(); } + const F32& getEndS() const { return mProfileParams.getEnd(); } + const F32& getEndT() const { return mPathParams.getEnd(); } + + const F32& getHollow() const { return mProfileParams.getHollow(); } + const F32& getTwist() const { return mPathParams.getTwist(); } + const F32& getRatio() const { return mPathParams.getScaleX(); } + const F32& getRatioX() const { return mPathParams.getScaleX(); } + const F32& getRatioY() const { return mPathParams.getScaleY(); } + const F32& getShearX() const { return mPathParams.getShearX(); } + const F32& getShearY() const { return mPathParams.getShearY(); } + + const F32& getTwistBegin()const { return mPathParams.getTwistBegin(); } + const F32& getRadiusOffset() const { return mPathParams.getRadiusOffset(); } + const F32& getTaper() const { return mPathParams.getTaperX(); } + const F32& getTaperX() const { return mPathParams.getTaperX(); } + const F32& getTaperY() const { return mPathParams.getTaperY(); } + const F32& getRevolutions() const { return mPathParams.getRevolutions(); } + const F32& getSkew() const { return mPathParams.getSkew(); } + const LLUUID& getSculptID() const { return mSculptID; } + const U8& getSculptType() const { return mSculptType; } + bool isSculpt() const; + bool isMeshSculpt() const; + bool isConvex() const; + + // 'begin' and 'end' should be in range [0, 1] (they will be clamped) + // (begin, end) = (0, 1) will not change the volume + // (begin, end) = (0, 0.5) will reduce the volume to the first half of its profile/path (S/T) + void reduceS(F32 begin, F32 end); + void reduceT(F32 begin, F32 end); + + struct compare + { + bool operator()( const const_LLVolumeParamsPtr& first, const const_LLVolumeParamsPtr& second) const + { + return (*first < *second); + } + }; + + friend std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params); + + // debug helper functions + void setCube(); protected: - LLProfileParams mProfileParams; - LLPathParams mPathParams; - LLUUID mSculptID; - U8 mSculptType; + LLProfileParams mProfileParams; + LLPathParams mPathParams; + LLUUID mSculptID; + U8 mSculptType; }; class LLProfile { - friend class LLVolume; + friend class LLVolume; public: - LLProfile() - : mOpen(false), - mConcave(false), - mDirty(true), - mTotalOut(0), - mTotal(2) - { - } - - S32 getTotal() const { return mTotal; } - S32 getTotalOut() const { return mTotalOut; } // Total number of outside points - bool isFlat(S32 face) const { return (mFaces[face].mCount == 2); } - bool isOpen() const { return mOpen; } - void setDirty() { mDirty = true; } - - static S32 getNumPoints(const LLProfileParams& params, bool path_open, F32 detail = 1.0f, S32 split = 0, - bool is_sculpted = false, S32 sculpt_size = 0); - bool generate(const LLProfileParams& params, bool path_open, F32 detail = 1.0f, S32 split = 0, - bool is_sculpted = false, S32 sculpt_size = 0); - bool isConcave() const { return mConcave; } + LLProfile() + : mOpen(false), + mConcave(false), + mDirty(true), + mTotalOut(0), + mTotal(2) + { + } + + S32 getTotal() const { return mTotal; } + S32 getTotalOut() const { return mTotalOut; } // Total number of outside points + bool isFlat(S32 face) const { return (mFaces[face].mCount == 2); } + bool isOpen() const { return mOpen; } + void setDirty() { mDirty = true; } + + static S32 getNumPoints(const LLProfileParams& params, bool path_open, F32 detail = 1.0f, S32 split = 0, + bool is_sculpted = false, S32 sculpt_size = 0); + bool generate(const LLProfileParams& params, bool path_open, F32 detail = 1.0f, S32 split = 0, + bool is_sculpted = false, S32 sculpt_size = 0); + bool isConcave() const { return mConcave; } public: - struct Face - { - S32 mIndex; - S32 mCount; - F32 mScaleU; - bool mCap; - bool mFlat; - LLFaceID mFaceID; - }; - - LLAlignedArray<LLVector4a, 64> mProfile; - //LLAlignedArray<LLVector4a, 64> mNormals; - std::vector<Face> mFaces; - - //LLAlignedArray<LLVector4a, 64> mEdgeNormals; - //LLAlignedArray<LLVector4a, 64> mEdgeCenters; - - friend std::ostream& operator<<(std::ostream &s, const LLProfile &profile); + struct Face + { + S32 mIndex; + S32 mCount; + F32 mScaleU; + bool mCap; + bool mFlat; + LLFaceID mFaceID; + }; + + LLAlignedArray<LLVector4a, 64> mProfile; + //LLAlignedArray<LLVector4a, 64> mNormals; + std::vector<Face> mFaces; + + //LLAlignedArray<LLVector4a, 64> mEdgeNormals; + //LLAlignedArray<LLVector4a, 64> mEdgeCenters; + + friend std::ostream& operator<<(std::ostream &s, const LLProfile &profile); protected: - ~LLProfile(); + ~LLProfile(); - static S32 getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0); - void genNGon(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0); + static S32 getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0); + void genNGon(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0); - Face* addHole(const LLProfileParams& params, bool flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split = 0); - Face* addCap (S16 faceID); - Face* addFace(S32 index, S32 count, F32 scaleU, S16 faceID, bool flat); + Face* addHole(const LLProfileParams& params, bool flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split = 0); + Face* addCap (S16 faceID); + Face* addFace(S32 index, S32 count, F32 scaleU, S16 faceID, bool flat); protected: - bool mOpen; - bool mConcave; - bool mDirty; + bool mOpen; + bool mConcave; + bool mDirty; - S32 mTotalOut; - S32 mTotal; + S32 mTotalOut; + S32 mTotal; }; //------------------------------------------------------------------- @@ -753,220 +753,220 @@ protected: class LLPath { public: - class PathPt - { - public: - LLMatrix4a mRot; - LLVector4a mPos; - - LLVector4a mScale; - F32 mTexT; - F32 pad[3]; //for alignment - PathPt() - { - mPos.clear(); - mTexT = 0; - mScale.clear(); - mRot.setRows(LLVector4a(1,0,0,0), - LLVector4a(0,1,0,0), - LLVector4a(0,0,1,0)); - - //distinguished data in the pad for debugging - pad[0] = 3.14159f; - pad[1] = -3.14159f; - pad[2] = 0.585f; - } - }; + class PathPt + { + public: + LLMatrix4a mRot; + LLVector4a mPos; + + LLVector4a mScale; + F32 mTexT; + F32 pad[3]; //for alignment + PathPt() + { + mPos.clear(); + mTexT = 0; + mScale.clear(); + mRot.setRows(LLVector4a(1,0,0,0), + LLVector4a(0,1,0,0), + LLVector4a(0,0,1,0)); + + //distinguished data in the pad for debugging + pad[0] = 3.14159f; + pad[1] = -3.14159f; + pad[2] = 0.585f; + } + }; public: - LLPath() - : mOpen(false), - mTotal(0), - mDirty(true), - mStep(1) - { - } + LLPath() + : mOpen(false), + mTotal(0), + mDirty(true), + mStep(1) + { + } - virtual ~LLPath(); + virtual ~LLPath(); - static S32 getNumPoints(const LLPathParams& params, F32 detail); - static S32 getNumNGonPoints(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f); + static S32 getNumPoints(const LLPathParams& params, F32 detail); + static S32 getNumNGonPoints(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f); - void genNGon(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f); - virtual bool generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0, - bool is_sculpted = false, S32 sculpt_size = 0); + void genNGon(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f); + virtual bool generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0, + bool is_sculpted = false, S32 sculpt_size = 0); - bool isOpen() const { return mOpen; } - F32 getStep() const { return mStep; } - void setDirty() { mDirty = true; } + bool isOpen() const { return mOpen; } + F32 getStep() const { return mStep; } + void setDirty() { mDirty = true; } - S32 getPathLength() const { return (S32)mPath.size(); } + S32 getPathLength() const { return (S32)mPath.size(); } - void resizePath(S32 length) { mPath.resize(length); } + void resizePath(S32 length) { mPath.resize(length); } - friend std::ostream& operator<<(std::ostream &s, const LLPath &path); + friend std::ostream& operator<<(std::ostream &s, const LLPath &path); public: - LLAlignedArray<PathPt, 64> mPath; + LLAlignedArray<PathPt, 64> mPath; protected: - bool mOpen; - S32 mTotal; - bool mDirty; - F32 mStep; + bool mOpen; + S32 mTotal; + bool mDirty; + F32 mStep; }; class LLDynamicPath : public LLPath { public: - LLDynamicPath() : LLPath() { } - /*virtual*/ bool generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0, - bool is_sculpted = false, S32 sculpt_size = 0); + LLDynamicPath() : LLPath() { } + /*virtual*/ bool generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0, + bool is_sculpted = false, S32 sculpt_size = 0); }; // Yet another "face" class - caches volume-specific, but not instance-specific data for faces) class LLVolumeFace { public: - class VertexData - { - enum - { - POSITION = 0, - NORMAL = 1 - }; - - private: - void init(); - public: - VertexData(); - VertexData(const VertexData& rhs); - const VertexData& operator=(const VertexData& rhs); - - ~VertexData(); - LLVector4a& getPosition(); - LLVector4a& getNormal(); - const LLVector4a& getPosition() const; - const LLVector4a& getNormal() const; - void setPosition(const LLVector4a& pos); - void setNormal(const LLVector4a& norm); - - - LLVector2 mTexCoord; - - bool operator<(const VertexData& rhs) const; - bool operator==(const VertexData& rhs) const; - bool compareNormal(const VertexData& rhs, F32 angle_cutoff) const; - - private: - LLVector4a* mData; - }; - - LLVolumeFace(); - LLVolumeFace(const LLVolumeFace& src); - LLVolumeFace& operator=(const LLVolumeFace& rhs); - - ~LLVolumeFace(); + class VertexData + { + enum + { + POSITION = 0, + NORMAL = 1 + }; + + private: + void init(); + public: + VertexData(); + VertexData(const VertexData& rhs); + const VertexData& operator=(const VertexData& rhs); + + ~VertexData(); + LLVector4a& getPosition(); + LLVector4a& getNormal(); + const LLVector4a& getPosition() const; + const LLVector4a& getNormal() const; + void setPosition(const LLVector4a& pos); + void setNormal(const LLVector4a& norm); + + + LLVector2 mTexCoord; + + bool operator<(const VertexData& rhs) const; + bool operator==(const VertexData& rhs) const; + bool compareNormal(const VertexData& rhs, F32 angle_cutoff) const; + + private: + LLVector4a* mData; + }; + + LLVolumeFace(); + LLVolumeFace(const LLVolumeFace& src); + LLVolumeFace& operator=(const LLVolumeFace& rhs); + + ~LLVolumeFace(); private: - void freeData(); + void freeData(); public: - bool create(LLVolume* volume, bool partial_build = false); - void createTangents(); - - void resizeVertices(S32 num_verts); - void allocateTangents(S32 num_verts); - void allocateWeights(S32 num_verts); + bool create(LLVolume* volume, bool partial_build = false); + void createTangents(); + + void resizeVertices(S32 num_verts); + void allocateTangents(S32 num_verts); + void allocateWeights(S32 num_verts); void allocateJointIndices(S32 num_verts); - void resizeIndices(S32 num_indices); - void fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v, std::vector<U16>& idx); + void resizeIndices(S32 num_indices); + void fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v, std::vector<U16>& idx); - void pushVertex(const VertexData& cv); - void pushVertex(const LLVector4a& pos, const LLVector4a& norm, const LLVector2& tc); - void pushIndex(const U16& idx); + void pushVertex(const VertexData& cv); + void pushVertex(const LLVector4a& pos, const LLVector4a& norm, const LLVector2& tc); + void pushIndex(const U16& idx); - void swapData(LLVolumeFace& rhs); + void swapData(LLVolumeFace& rhs); - void getVertexData(U16 indx, LLVolumeFace::VertexData& cv); + void getVertexData(U16 indx, LLVolumeFace::VertexData& cv); - class VertexMapData : public LLVolumeFace::VertexData - { - public: - U16 mIndex; + class VertexMapData : public LLVolumeFace::VertexData + { + public: + U16 mIndex; - bool operator==(const LLVolumeFace::VertexData& rhs) const; + bool operator==(const LLVolumeFace::VertexData& rhs) const; - struct ComparePosition - { - bool operator()(const LLVector3& a, const LLVector3& b) const; - }; + struct ComparePosition + { + bool operator()(const LLVector3& a, const LLVector3& b) const; + }; - typedef std::map<LLVector3, std::vector<VertexMapData>, VertexMapData::ComparePosition > PointMap; - }; + typedef std::map<LLVector3, std::vector<VertexMapData>, VertexMapData::ComparePosition > PointMap; + }; // Eliminates non unique triangles, takes positions, // normals and texture coordinates into account. void remap(); - void optimize(F32 angle_cutoff = 2.f); - bool cacheOptimize(bool gen_tangents = false); + void optimize(F32 angle_cutoff = 2.f); + bool cacheOptimize(bool gen_tangents = false); - void createOctree(F32 scaler = 0.25f, const LLVector4a& center = LLVector4a(0,0,0), const LLVector4a& size = LLVector4a(0.5f,0.5f,0.5f)); + void createOctree(F32 scaler = 0.25f, const LLVector4a& center = LLVector4a(0,0,0), const LLVector4a& size = LLVector4a(0.5f,0.5f,0.5f)); void destroyOctree(); // Get a reference to the octree, which may be null const LLVolumeOctree* getOctree() const; - enum - { - SINGLE_MASK = 0x0001, - CAP_MASK = 0x0002, - END_MASK = 0x0004, - SIDE_MASK = 0x0008, - INNER_MASK = 0x0010, - OUTER_MASK = 0x0020, - HOLLOW_MASK = 0x0040, - OPEN_MASK = 0x0080, - FLAT_MASK = 0x0100, - TOP_MASK = 0x0200, - BOTTOM_MASK = 0x0400 - }; - + enum + { + SINGLE_MASK = 0x0001, + CAP_MASK = 0x0002, + END_MASK = 0x0004, + SIDE_MASK = 0x0008, + INNER_MASK = 0x0010, + OUTER_MASK = 0x0020, + HOLLOW_MASK = 0x0040, + OPEN_MASK = 0x0080, + FLAT_MASK = 0x0100, + TOP_MASK = 0x0200, + BOTTOM_MASK = 0x0400 + }; + public: - S32 mID; - U32 mTypeMask; - - // Only used for INNER/OUTER faces - S32 mBeginS; - S32 mBeginT; - S32 mNumS; - S32 mNumT; - - LLVector4a* mExtents; //minimum and maximum point of face - LLVector4a* mCenter; - LLVector2 mTexCoordExtents[2]; //minimum and maximum of texture coordinates of the face. - - S32 mNumVertices; // num vertices == num normals == num texcoords - S32 mNumAllocatedVertices; - S32 mNumIndices; - - LLVector4a* mPositions; // Contains vertices, nortmals and texcoords - LLVector4a* mNormals; // pointer into mPositions - LLVector4a* mTangents; - LLVector2* mTexCoords; // pointer into mPositions - - // mIndices contains mNumIndices amount of elements. - // It contains triangles, each 3 indices describe one triangle. + S32 mID; + U32 mTypeMask; + + // Only used for INNER/OUTER faces + S32 mBeginS; + S32 mBeginT; + S32 mNumS; + S32 mNumT; + + LLVector4a* mExtents; //minimum and maximum point of face + LLVector4a* mCenter; + LLVector2 mTexCoordExtents[2]; //minimum and maximum of texture coordinates of the face. + + S32 mNumVertices; // num vertices == num normals == num texcoords + S32 mNumAllocatedVertices; + S32 mNumIndices; + + LLVector4a* mPositions; // Contains vertices, nortmals and texcoords + LLVector4a* mNormals; // pointer into mPositions + LLVector4a* mTangents; + LLVector2* mTexCoords; // pointer into mPositions + + // mIndices contains mNumIndices amount of elements. + // It contains triangles, each 3 indices describe one triangle. // If mIndices contains {0, 2, 3, 1, 2, 4}, it means there // are two triangles {0, 2, 3} and {1, 2, 4} with values being // indexes for mPositions/mNormals/mTexCoords - U16* mIndices; + U16* mIndices; - std::vector<S32> mEdge; + std::vector<S32> mEdge; - //list of skin weights for rigged volumes - // format is mWeights[vertex_index].mV[influence] = <joint_index>.<weight> - // mWeights.size() should be empty or match mVertices.size() - LLVector4a* mWeights; + //list of skin weights for rigged volumes + // format is mWeights[vertex_index].mV[influence] = <joint_index>.<weight> + // mWeights.size() should be empty or match mVertices.size() + LLVector4a* mWeights; #if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS LLVector4a* mJustWeights; @@ -979,8 +979,8 @@ public: // vertices per joint. LLJointRiggingInfoTab mJointRiggingInfoTab; - //whether or not face has been cache optimized - bool mOptimized; + //whether or not face has been cache optimized + bool mOptimized; // if this is a mesh asset, scale and translation that were applied // when encoding the source mesh into a unit cube @@ -991,152 +991,152 @@ private: LLVolumeOctree* mOctree; LLVolumeTriangle* mOctreeTriangles; - bool createUnCutCubeCap(LLVolume* volume, bool partial_build = false); - bool createCap(LLVolume* volume, bool partial_build = false); - bool createSide(LLVolume* volume, bool partial_build = false); + bool createUnCutCubeCap(LLVolume* volume, bool partial_build = false); + bool createCap(LLVolume* volume, bool partial_build = false); + bool createSide(LLVolume* volume, bool partial_build = false); }; class LLVolume : public LLRefCount { - friend class LLVolumeLODGroup; + friend class LLVolumeLODGroup; protected: - virtual ~LLVolume(); // use unref + virtual ~LLVolume(); // use unref public: - typedef std::vector<LLVolumeFace> face_list_t; - - struct FaceParams - { - LLFaceID mFaceID; - S32 mBeginS; - S32 mCountS; - S32 mBeginT; - S32 mCountT; - }; - - LLVolume(const LLVolumeParams ¶ms, const F32 detail, const bool generate_single_face = false, const bool is_unique = false); - - U8 getProfileType() const { return mParams.getProfileParams().getCurveType(); } - U8 getPathType() const { return mParams.getPathParams().getCurveType(); } - S32 getNumFaces() const; - S32 getNumVolumeFaces() const { return mVolumeFaces.size(); } - F32 getDetail() const { return mDetail; } - F32 getSurfaceArea() const { return mSurfaceArea; } - const LLVolumeParams& getParams() const { return mParams; } - LLVolumeParams getCopyOfParams() const { return mParams; } - const LLProfile& getProfile() const { return *mProfilep; } - LLPath& getPath() const { return *mPathp; } - void resizePath(S32 length); - const LLAlignedArray<LLVector4a,64>& getMesh() const { return mMesh; } - const LLVector4a& getMeshPt(const U32 i) const { return mMesh[i]; } - - - void setDirty() { mPathp->setDirty(); mProfilep->setDirty(); } - - void regen(); + typedef std::vector<LLVolumeFace> face_list_t; + + struct FaceParams + { + LLFaceID mFaceID; + S32 mBeginS; + S32 mCountS; + S32 mBeginT; + S32 mCountT; + }; + + LLVolume(const LLVolumeParams ¶ms, const F32 detail, const bool generate_single_face = false, const bool is_unique = false); + + U8 getProfileType() const { return mParams.getProfileParams().getCurveType(); } + U8 getPathType() const { return mParams.getPathParams().getCurveType(); } + S32 getNumFaces() const; + S32 getNumVolumeFaces() const { return mVolumeFaces.size(); } + F32 getDetail() const { return mDetail; } + F32 getSurfaceArea() const { return mSurfaceArea; } + const LLVolumeParams& getParams() const { return mParams; } + LLVolumeParams getCopyOfParams() const { return mParams; } + const LLProfile& getProfile() const { return *mProfilep; } + LLPath& getPath() const { return *mPathp; } + void resizePath(S32 length); + const LLAlignedArray<LLVector4a,64>& getMesh() const { return mMesh; } + const LLVector4a& getMeshPt(const U32 i) const { return mMesh[i]; } + + + void setDirty() { mPathp->setDirty(); mProfilep->setDirty(); } + + void regen(); void genTangents(S32 face); - bool isConvex() const; - bool isCap(S32 face); - bool isFlat(S32 face); - bool isUnique() const { return mUnique; } - - S32 getSculptLevel() const { return mSculptLevel; } - void setSculptLevel(S32 level) { mSculptLevel = level; } - - - static void getLoDTriangleCounts(const LLVolumeParams& params, S32* counts); - - S32 getNumTriangles(S32* vcount = nullptr) const; - - void generateSilhouetteVertices(std::vector<LLVector3> &vertices, - std::vector<LLVector3> &normals, - const LLVector3& view_vec, - const LLMatrix4& mat, - const LLMatrix3& norm_mat, - S32 face_index); - - //get the face index of the face that intersects with the given line segment at the point - //closest to start. Moves end to the point of intersection. Returns -1 if no intersection. - //Line segment must be in volume space. - S32 lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, - S32 face = -1, // which face to check, -1 = ALL_SIDES - LLVector4a* intersection = nullptr, // return the intersection point - LLVector2* tex_coord = nullptr, // return the texture coordinates of the intersection point - LLVector4a* normal = nullptr, // return the surface normal at the intersection point - LLVector4a* tangent = nullptr // return the surface tangent at the intersection point - ); - - LLFaceID generateFaceMask(); - - bool isFaceMaskValid(LLFaceID face_mask); - static S32 sNumMeshPoints; - - friend std::ostream& operator<<(std::ostream &s, const LLVolume &volume); - friend std::ostream& operator<<(std::ostream &s, const LLVolume *volumep); // HACK to bypass Windoze confusion over - // conversion if *(LLVolume*) to LLVolume& - const LLVolumeFace &getVolumeFace(const S32 f) const {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE - - LLVolumeFace &getVolumeFace(const S32 f) {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE - - face_list_t& getVolumeFaces() { return mVolumeFaces; } - - U32 mFaceMask; // bit array of which faces exist in this volume - LLVector3 mLODScaleBias; // vector for biasing LOD based on scale - - void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level, bool visible_placeholder); - void copyVolumeFaces(const LLVolume* volume); - void copyFacesTo(std::vector<LLVolumeFace> &faces) const; - void copyFacesFrom(const std::vector<LLVolumeFace> &faces); + bool isConvex() const; + bool isCap(S32 face); + bool isFlat(S32 face); + bool isUnique() const { return mUnique; } + + S32 getSculptLevel() const { return mSculptLevel; } + void setSculptLevel(S32 level) { mSculptLevel = level; } + + + static void getLoDTriangleCounts(const LLVolumeParams& params, S32* counts); + + S32 getNumTriangles(S32* vcount = nullptr) const; + + void generateSilhouetteVertices(std::vector<LLVector3> &vertices, + std::vector<LLVector3> &normals, + const LLVector3& view_vec, + const LLMatrix4& mat, + const LLMatrix3& norm_mat, + S32 face_index); + + //get the face index of the face that intersects with the given line segment at the point + //closest to start. Moves end to the point of intersection. Returns -1 if no intersection. + //Line segment must be in volume space. + S32 lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, + S32 face = -1, // which face to check, -1 = ALL_SIDES + LLVector4a* intersection = nullptr, // return the intersection point + LLVector2* tex_coord = nullptr, // return the texture coordinates of the intersection point + LLVector4a* normal = nullptr, // return the surface normal at the intersection point + LLVector4a* tangent = nullptr // return the surface tangent at the intersection point + ); + + LLFaceID generateFaceMask(); + + bool isFaceMaskValid(LLFaceID face_mask); + static S32 sNumMeshPoints; + + friend std::ostream& operator<<(std::ostream &s, const LLVolume &volume); + friend std::ostream& operator<<(std::ostream &s, const LLVolume *volumep); // HACK to bypass Windoze confusion over + // conversion if *(LLVolume*) to LLVolume& + const LLVolumeFace &getVolumeFace(const S32 f) const {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE + + LLVolumeFace &getVolumeFace(const S32 f) {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE + + face_list_t& getVolumeFaces() { return mVolumeFaces; } + + U32 mFaceMask; // bit array of which faces exist in this volume + LLVector3 mLODScaleBias; // vector for biasing LOD based on scale + + void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level, bool visible_placeholder); + void copyVolumeFaces(const LLVolume* volume); + void copyFacesTo(std::vector<LLVolumeFace> &faces) const; + void copyFacesFrom(const std::vector<LLVolumeFace> &faces); // use meshoptimizer to optimize index buffer for vertex shader cache // gen_tangents - if true, generate MikkTSpace tangents if needed before optimizing index buffer - bool cacheOptimize(bool gen_tangents = false); + bool cacheOptimize(bool gen_tangents = false); private: - void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type); - F32 sculptGetSurfaceArea(); - void sculptGenerateEmptyPlaceholder(); - void sculptGenerateSpherePlaceholder(); + void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type); + F32 sculptGetSurfaceArea(); + void sculptGenerateEmptyPlaceholder(); + void sculptGenerateSpherePlaceholder(); protected: - bool generate(); - void createVolumeFaces(); + bool generate(); + void createVolumeFaces(); public: - bool unpackVolumeFaces(std::istream& is, S32 size); - bool unpackVolumeFaces(U8* in_data, S32 size); + bool unpackVolumeFaces(std::istream& is, S32 size); + bool unpackVolumeFaces(U8* in_data, S32 size); private: - bool unpackVolumeFacesInternal(const LLSD& mdl); + bool unpackVolumeFacesInternal(const LLSD& mdl); public: - virtual void setMeshAssetLoaded(bool loaded); - virtual bool isMeshAssetLoaded(); + virtual void setMeshAssetLoaded(bool loaded); + virtual bool isMeshAssetLoaded(); virtual void setMeshAssetUnavaliable(bool unavaliable); virtual bool isMeshAssetUnavaliable(); protected: - bool mUnique; - F32 mDetail; - S32 mSculptLevel; - F32 mSurfaceArea; //unscaled surface area - bool mIsMeshAssetLoaded; + bool mUnique; + F32 mDetail; + S32 mSculptLevel; + F32 mSurfaceArea; //unscaled surface area + bool mIsMeshAssetLoaded; bool mIsMeshAssetUnavaliable; - - const LLVolumeParams mParams; - LLPath *mPathp; - LLProfile *mProfilep; - LLAlignedArray<LLVector4a,64> mMesh; - - - bool mGenerateSingleFace; - face_list_t mVolumeFaces; + + const LLVolumeParams mParams; + LLPath *mPathp; + LLProfile *mProfilep; + LLAlignedArray<LLVector4a,64> mMesh; + + + bool mGenerateSingleFace; + face_list_t mVolumeFaces; public: - LLVector4a* mHullPoints; - U16* mHullIndices; - S32 mNumHullPoints; - S32 mNumHullIndices; + LLVector4a* mHullPoints; + U16* mHullIndices; + S32 mNumHullPoints; + S32 mNumHullIndices; }; std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params); @@ -1148,8 +1148,8 @@ bool LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, con bool LLLineSegmentBoxIntersect(const LLVector4a& start, const LLVector4a& end, const LLVector4a& center, const LLVector4a& size); bool LLTriangleRayIntersect(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir, - F32& intersection_a, F32& intersection_b, F32& intersection_t); + F32& intersection_a, F32& intersection_b, F32& intersection_t); bool LLTriangleRayIntersectTwoSided(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir, - F32& intersection_a, F32& intersection_b, F32& intersection_t); + F32& intersection_a, F32& intersection_b, F32& intersection_t); #endif diff --git a/indra/llmath/llvolumemgr.cpp b/indra/llmath/llvolumemgr.cpp index 06794fd23f..bb0c94d513 100644 --- a/indra/llmath/llvolumemgr.cpp +++ b/indra/llmath/llvolumemgr.cpp @@ -1,24 +1,24 @@ -/** +/** * @file llvolumemgr.cpp * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -33,9 +33,9 @@ const F32 BASE_THRESHOLD = 0.03f; //static F32 LLVolumeLODGroup::mDetailThresholds[NUM_LODS] = {BASE_THRESHOLD, - 2*BASE_THRESHOLD, - 8*BASE_THRESHOLD, - 100*BASE_THRESHOLD}; + 2*BASE_THRESHOLD, + 8*BASE_THRESHOLD, + 100*BASE_THRESHOLD}; //static F32 LLVolumeLODGroup::mDetailScales[NUM_LODS] = {1.f, 1.5f, 2.5f, 4.f}; @@ -44,45 +44,45 @@ F32 LLVolumeLODGroup::mDetailScales[NUM_LODS] = {1.f, 1.5f, 2.5f, 4.f}; //============================================================================ LLVolumeMgr::LLVolumeMgr() -: mDataMutex(NULL) +: mDataMutex(NULL) { - // the LLMutex magic interferes with easy unit testing, - // so you now must manually call useMutex() to use it - //mDataMutex = new LLMutex(); + // the LLMutex magic interferes with easy unit testing, + // so you now must manually call useMutex() to use it + //mDataMutex = new LLMutex(); } LLVolumeMgr::~LLVolumeMgr() { - cleanup(); + cleanup(); - delete mDataMutex; - mDataMutex = NULL; + delete mDataMutex; + mDataMutex = NULL; } bool LLVolumeMgr::cleanup() { - bool no_refs = true; - if (mDataMutex) - { - mDataMutex->lock(); - } - for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(), - end = mVolumeLODGroups.end(); - iter != end; iter++) - { - LLVolumeLODGroup *volgroupp = iter->second; - if (!volgroupp->cleanupRefs()) - { - no_refs = false; - } - delete volgroupp; - } - mVolumeLODGroups.clear(); - if (mDataMutex) - { - mDataMutex->unlock(); - } - return no_refs; + bool no_refs = true; + if (mDataMutex) + { + mDataMutex->lock(); + } + for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(), + end = mVolumeLODGroups.end(); + iter != end; iter++) + { + LLVolumeLODGroup *volgroupp = iter->second; + if (!volgroupp->cleanupRefs()) + { + no_refs = false; + } + delete volgroupp; + } + mVolumeLODGroups.clear(); + if (mDataMutex) + { + mDataMutex->unlock(); + } + return no_refs; } // Always only ever store the results of refVolume in a LLPointer @@ -91,318 +91,318 @@ bool LLVolumeMgr::cleanup() // anything holding the volume and the LODGroup are destroyed LLVolume* LLVolumeMgr::refVolume(const LLVolumeParams &volume_params, const S32 lod) { - LLVolumeLODGroup* volgroupp; - if (mDataMutex) - { - mDataMutex->lock(); - } - volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(&volume_params); - if( iter == mVolumeLODGroups.end() ) - { - volgroupp = createNewGroup(volume_params); - } - else - { - volgroupp = iter->second; - } - if (mDataMutex) - { - mDataMutex->unlock(); - } - return volgroupp->refLOD(lod); + LLVolumeLODGroup* volgroupp; + if (mDataMutex) + { + mDataMutex->lock(); + } + volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(&volume_params); + if( iter == mVolumeLODGroups.end() ) + { + volgroupp = createNewGroup(volume_params); + } + else + { + volgroupp = iter->second; + } + if (mDataMutex) + { + mDataMutex->unlock(); + } + return volgroupp->refLOD(lod); } // virtual LLVolumeLODGroup* LLVolumeMgr::getGroup( const LLVolumeParams& volume_params ) const { - LLVolumeLODGroup* volgroupp = NULL; - if (mDataMutex) - { - mDataMutex->lock(); - } - volume_lod_group_map_t::const_iterator iter = mVolumeLODGroups.find(&volume_params); - if( iter != mVolumeLODGroups.end() ) - { - volgroupp = iter->second; - } - if (mDataMutex) - { - mDataMutex->unlock(); - } - return volgroupp; + LLVolumeLODGroup* volgroupp = NULL; + if (mDataMutex) + { + mDataMutex->lock(); + } + volume_lod_group_map_t::const_iterator iter = mVolumeLODGroups.find(&volume_params); + if( iter != mVolumeLODGroups.end() ) + { + volgroupp = iter->second; + } + if (mDataMutex) + { + mDataMutex->unlock(); + } + return volgroupp; } void LLVolumeMgr::unrefVolume(LLVolume *volumep) { - if (volumep->isUnique()) - { - // TomY: Don't need to manage this volume. It is a unique instance. - return; - } - const LLVolumeParams* params = &(volumep->getParams()); - if (mDataMutex) - { - mDataMutex->lock(); - } - volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(params); - if( iter == mVolumeLODGroups.end() ) - { - LL_ERRS() << "Warning! Tried to cleanup unknown volume type! " << *params << LL_ENDL; - if (mDataMutex) - { - mDataMutex->unlock(); - } - return; - } - else - { - LLVolumeLODGroup* volgroupp = iter->second; - - volgroupp->derefLOD(volumep); - if (volgroupp->getNumRefs() == 0) - { - mVolumeLODGroups.erase(params); - delete volgroupp; - } - } - if (mDataMutex) - { - mDataMutex->unlock(); - } + if (volumep->isUnique()) + { + // TomY: Don't need to manage this volume. It is a unique instance. + return; + } + const LLVolumeParams* params = &(volumep->getParams()); + if (mDataMutex) + { + mDataMutex->lock(); + } + volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(params); + if( iter == mVolumeLODGroups.end() ) + { + LL_ERRS() << "Warning! Tried to cleanup unknown volume type! " << *params << LL_ENDL; + if (mDataMutex) + { + mDataMutex->unlock(); + } + return; + } + else + { + LLVolumeLODGroup* volgroupp = iter->second; + + volgroupp->derefLOD(volumep); + if (volgroupp->getNumRefs() == 0) + { + mVolumeLODGroups.erase(params); + delete volgroupp; + } + } + if (mDataMutex) + { + mDataMutex->unlock(); + } } // protected void LLVolumeMgr::insertGroup(LLVolumeLODGroup* volgroup) { - mVolumeLODGroups[volgroup->getVolumeParams()] = volgroup; + mVolumeLODGroups[volgroup->getVolumeParams()] = volgroup; } // protected LLVolumeLODGroup* LLVolumeMgr::createNewGroup(const LLVolumeParams& volume_params) { - LLVolumeLODGroup* volgroup = new LLVolumeLODGroup(volume_params); - insertGroup(volgroup); - return volgroup; + LLVolumeLODGroup* volgroup = new LLVolumeLODGroup(volume_params); + insertGroup(volgroup); + return volgroup; } // virtual void LLVolumeMgr::dump() { - F32 avg = 0.f; - if (mDataMutex) - { - mDataMutex->lock(); - } - for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(), - end = mVolumeLODGroups.end(); - iter != end; iter++) - { - LLVolumeLODGroup *volgroupp = iter->second; - avg += volgroupp->dump(); - } - int count = (int)mVolumeLODGroups.size(); - avg = count ? avg / (F32)count : 0.0f; - if (mDataMutex) - { - mDataMutex->unlock(); - } - LL_INFOS() << "Average usage of LODs " << avg << LL_ENDL; + F32 avg = 0.f; + if (mDataMutex) + { + mDataMutex->lock(); + } + for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(), + end = mVolumeLODGroups.end(); + iter != end; iter++) + { + LLVolumeLODGroup *volgroupp = iter->second; + avg += volgroupp->dump(); + } + int count = (int)mVolumeLODGroups.size(); + avg = count ? avg / (F32)count : 0.0f; + if (mDataMutex) + { + mDataMutex->unlock(); + } + LL_INFOS() << "Average usage of LODs " << avg << LL_ENDL; } void LLVolumeMgr::useMutex() -{ - if (!mDataMutex) - { - mDataMutex = new LLMutex(); - } +{ + if (!mDataMutex) + { + mDataMutex = new LLMutex(); + } } std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr) { - s << "{ numLODgroups=" << volume_mgr.mVolumeLODGroups.size() << ", "; - - S32 total_refs = 0; - if (volume_mgr.mDataMutex) - { - volume_mgr.mDataMutex->lock(); - } - - for (LLVolumeMgr::volume_lod_group_map_t::const_iterator iter = volume_mgr.mVolumeLODGroups.begin(); - iter != volume_mgr.mVolumeLODGroups.end(); ++iter) - { - LLVolumeLODGroup *volgroupp = iter->second; - total_refs += volgroupp->getNumRefs(); - s << ", " << (*volgroupp); - } - - if (volume_mgr.mDataMutex) - { - volume_mgr.mDataMutex->unlock(); - } - - s << ", total_refs=" << total_refs << " }"; - return s; + s << "{ numLODgroups=" << volume_mgr.mVolumeLODGroups.size() << ", "; + + S32 total_refs = 0; + if (volume_mgr.mDataMutex) + { + volume_mgr.mDataMutex->lock(); + } + + for (LLVolumeMgr::volume_lod_group_map_t::const_iterator iter = volume_mgr.mVolumeLODGroups.begin(); + iter != volume_mgr.mVolumeLODGroups.end(); ++iter) + { + LLVolumeLODGroup *volgroupp = iter->second; + total_refs += volgroupp->getNumRefs(); + s << ", " << (*volgroupp); + } + + if (volume_mgr.mDataMutex) + { + volume_mgr.mDataMutex->unlock(); + } + + s << ", total_refs=" << total_refs << " }"; + return s; } LLVolumeLODGroup::LLVolumeLODGroup(const LLVolumeParams ¶ms) - : mVolumeParams(params), - mRefs(0) + : mVolumeParams(params), + mRefs(0) { - for (S32 i = 0; i < NUM_LODS; i++) - { - mLODRefs[i] = 0; - mAccessCount[i] = 0; - } + for (S32 i = 0; i < NUM_LODS; i++) + { + mLODRefs[i] = 0; + mAccessCount[i] = 0; + } } LLVolumeLODGroup::~LLVolumeLODGroup() { - for (S32 i = 0; i < NUM_LODS; i++) - { - llassert_always(mLODRefs[i] == 0); - } + for (S32 i = 0; i < NUM_LODS; i++) + { + llassert_always(mLODRefs[i] == 0); + } } // Called from LLVolumeMgr::cleanup bool LLVolumeLODGroup::cleanupRefs() { - bool res = true; - if (mRefs != 0) - { - LL_WARNS() << "Volume group has remaining refs:" << getNumRefs() << LL_ENDL; - mRefs = 0; - for (S32 i = 0; i < NUM_LODS; i++) - { - if (mLODRefs[i] > 0) - { - LL_WARNS() << " LOD " << i << " refs = " << mLODRefs[i] << LL_ENDL; - mLODRefs[i] = 0; - mVolumeLODs[i] = NULL; - } - } - LL_WARNS() << *getVolumeParams() << LL_ENDL; - res = false; - } - return res; + bool res = true; + if (mRefs != 0) + { + LL_WARNS() << "Volume group has remaining refs:" << getNumRefs() << LL_ENDL; + mRefs = 0; + for (S32 i = 0; i < NUM_LODS; i++) + { + if (mLODRefs[i] > 0) + { + LL_WARNS() << " LOD " << i << " refs = " << mLODRefs[i] << LL_ENDL; + mLODRefs[i] = 0; + mVolumeLODs[i] = NULL; + } + } + LL_WARNS() << *getVolumeParams() << LL_ENDL; + res = false; + } + return res; } LLVolume* LLVolumeLODGroup::refLOD(const S32 lod) { - llassert(lod >=0 && lod < NUM_LODS); - mAccessCount[lod]++; - - mRefs++; - if (mVolumeLODs[lod].isNull()) - { - mVolumeLODs[lod] = new LLVolume(mVolumeParams, mDetailScales[lod]); - } - mLODRefs[lod]++; - return mVolumeLODs[lod]; + llassert(lod >=0 && lod < NUM_LODS); + mAccessCount[lod]++; + + mRefs++; + if (mVolumeLODs[lod].isNull()) + { + mVolumeLODs[lod] = new LLVolume(mVolumeParams, mDetailScales[lod]); + } + mLODRefs[lod]++; + return mVolumeLODs[lod]; } bool LLVolumeLODGroup::derefLOD(LLVolume *volumep) { - llassert_always(mRefs > 0); - mRefs--; - for (S32 i = 0; i < NUM_LODS; i++) - { - if (mVolumeLODs[i] == volumep) - { - llassert_always(mLODRefs[i] > 0); - mLODRefs[i]--; + llassert_always(mRefs > 0); + mRefs--; + for (S32 i = 0; i < NUM_LODS; i++) + { + if (mVolumeLODs[i] == volumep) + { + llassert_always(mLODRefs[i] > 0); + mLODRefs[i]--; #if 0 // SJB: Possible opt: keep other lods around - if (!mLODRefs[i]) - { - mVolumeLODs[i] = NULL; - } + if (!mLODRefs[i]) + { + mVolumeLODs[i] = NULL; + } #endif - return true; - } - } - LL_ERRS() << "Deref of non-matching LOD in volume LOD group" << LL_ENDL; - return false; + return true; + } + } + LL_ERRS() << "Deref of non-matching LOD in volume LOD group" << LL_ENDL; + return false; } S32 LLVolumeLODGroup::getDetailFromTan(const F32 tan_angle) { - S32 i = 0; - while (i < (NUM_LODS - 1)) - { - if (tan_angle <= mDetailThresholds[i]) - { - return i; - } - i++; - } - return NUM_LODS - 1; + S32 i = 0; + while (i < (NUM_LODS - 1)) + { + if (tan_angle <= mDetailThresholds[i]) + { + return i; + } + i++; + } + return NUM_LODS - 1; } void LLVolumeLODGroup::getDetailProximity(const F32 tan_angle, F32 &to_lower, F32& to_higher) { - S32 detail = getDetailFromTan(tan_angle); - - if (detail > 0) - { - to_lower = tan_angle - mDetailThresholds[detail]; - } - else - { - to_lower = 1024.f*1024.f; - } - - if (detail < NUM_LODS-1) - { - to_higher = mDetailThresholds[detail+1] - tan_angle; - } - else - { - to_higher = 1024.f*1024.f; - } + S32 detail = getDetailFromTan(tan_angle); + + if (detail > 0) + { + to_lower = tan_angle - mDetailThresholds[detail]; + } + else + { + to_lower = 1024.f*1024.f; + } + + if (detail < NUM_LODS-1) + { + to_higher = mDetailThresholds[detail+1] - tan_angle; + } + else + { + to_higher = 1024.f*1024.f; + } } F32 LLVolumeLODGroup::getVolumeScaleFromDetail(const S32 detail) { - return mDetailScales[detail]; + return mDetailScales[detail]; } S32 LLVolumeLODGroup::getVolumeDetailFromScale(const F32 detail) { - for (S32 i = 1; i < 4; i++) - { - if (mDetailScales[i] > detail) - { - return i-1; - } - } - - return 3; + for (S32 i = 1; i < 4; i++) + { + if (mDetailScales[i] > detail) + { + return i-1; + } + } + + return 3; } F32 LLVolumeLODGroup::dump() { - F32 usage = 0.f; - for (S32 i = 0; i < NUM_LODS; i++) - { - if (mAccessCount[i] > 0) - { - usage += 1.f; - } - } - usage = usage / (F32)NUM_LODS; - - std::string dump_str = llformat("%.3f %d %d %d %d", usage, mAccessCount[0], mAccessCount[1], mAccessCount[2], mAccessCount[3]); - - LL_INFOS() << dump_str << LL_ENDL; - return usage; + F32 usage = 0.f; + for (S32 i = 0; i < NUM_LODS; i++) + { + if (mAccessCount[i] > 0) + { + usage += 1.f; + } + } + usage = usage / (F32)NUM_LODS; + + std::string dump_str = llformat("%.3f %d %d %d %d", usage, mAccessCount[0], mAccessCount[1], mAccessCount[2], mAccessCount[3]); + + LL_INFOS() << dump_str << LL_ENDL; + return usage; } std::ostream& operator<<(std::ostream& s, const LLVolumeLODGroup& volgroup) { - s << "{ numRefs=" << volgroup.getNumRefs(); - s << ", mParams=" << volgroup.getVolumeParams(); - s << " }"; - - return s; + s << "{ numRefs=" << volgroup.getNumRefs(); + s << ", mParams=" << volgroup.getVolumeParams(); + s << " }"; + + return s; } diff --git a/indra/llmath/llvolumemgr.h b/indra/llmath/llvolumemgr.h index b0baf7054d..2e0ce3e88a 100644 --- a/indra/llmath/llvolumemgr.h +++ b/indra/llmath/llvolumemgr.h @@ -1,25 +1,25 @@ -/** +/** * @file llvolumemgr.h * @brief LLVolumeMgr class. * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,75 +38,75 @@ class LLVolumeLODGroup; class LLVolumeLODGroup { - LOG_CLASS(LLVolumeLODGroup); - + LOG_CLASS(LLVolumeLODGroup); + public: - enum - { - NUM_LODS = 4 - }; + enum + { + NUM_LODS = 4 + }; + + LLVolumeLODGroup(const LLVolumeParams ¶ms); + ~LLVolumeLODGroup(); + bool cleanupRefs(); - LLVolumeLODGroup(const LLVolumeParams ¶ms); - ~LLVolumeLODGroup(); - bool cleanupRefs(); + static S32 getDetailFromTan(const F32 tan_angle); + static void getDetailProximity(const F32 tan_angle, F32 &to_lower, F32& to_higher); + static F32 getVolumeScaleFromDetail(const S32 detail); + static S32 getVolumeDetailFromScale(F32 scale); - static S32 getDetailFromTan(const F32 tan_angle); - static void getDetailProximity(const F32 tan_angle, F32 &to_lower, F32& to_higher); - static F32 getVolumeScaleFromDetail(const S32 detail); - static S32 getVolumeDetailFromScale(F32 scale); + LLVolume* refLOD(const S32 detail); + bool derefLOD(LLVolume *volumep); + S32 getNumRefs() const { return mRefs; } - LLVolume* refLOD(const S32 detail); - bool derefLOD(LLVolume *volumep); - S32 getNumRefs() const { return mRefs; } - - const LLVolumeParams* getVolumeParams() const { return &mVolumeParams; }; + const LLVolumeParams* getVolumeParams() const { return &mVolumeParams; }; - F32 dump(); - friend std::ostream& operator<<(std::ostream& s, const LLVolumeLODGroup& volgroup); + F32 dump(); + friend std::ostream& operator<<(std::ostream& s, const LLVolumeLODGroup& volgroup); protected: - LLVolumeParams mVolumeParams; - - S32 mRefs; - S32 mLODRefs[NUM_LODS]; - LLPointer<LLVolume> mVolumeLODs[NUM_LODS]; - static F32 mDetailThresholds[NUM_LODS]; - static F32 mDetailScales[NUM_LODS]; - S32 mAccessCount[NUM_LODS]; + LLVolumeParams mVolumeParams; + + S32 mRefs; + S32 mLODRefs[NUM_LODS]; + LLPointer<LLVolume> mVolumeLODs[NUM_LODS]; + static F32 mDetailThresholds[NUM_LODS]; + static F32 mDetailScales[NUM_LODS]; + S32 mAccessCount[NUM_LODS]; }; class LLVolumeMgr { public: - LLVolumeMgr(); - virtual ~LLVolumeMgr(); - bool cleanup(); // Cleanup all volumes being managed, returns true if no dangling references + LLVolumeMgr(); + virtual ~LLVolumeMgr(); + bool cleanup(); // Cleanup all volumes being managed, returns true if no dangling references - virtual LLVolumeLODGroup* getGroup( const LLVolumeParams& volume_params ) const; + virtual LLVolumeLODGroup* getGroup( const LLVolumeParams& volume_params ) const; - // whatever calls getVolume() never owns the LLVolume* and - // cannot keep references for long since it may be deleted - // later. For best results hold it in an LLPointer<LLVolume>. - virtual LLVolume *refVolume(const LLVolumeParams &volume_params, const S32 detail); - virtual void unrefVolume(LLVolume *volumep); + // whatever calls getVolume() never owns the LLVolume* and + // cannot keep references for long since it may be deleted + // later. For best results hold it in an LLPointer<LLVolume>. + virtual LLVolume *refVolume(const LLVolumeParams &volume_params, const S32 detail); + virtual void unrefVolume(LLVolume *volumep); - void dump(); + void dump(); - // manually call this for mutex magic - void useMutex(); + // manually call this for mutex magic + void useMutex(); - friend std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr); + friend std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr); protected: - void insertGroup(LLVolumeLODGroup* volgroup); - // Overridden in llphysics/abstract/utils/llphysicsvolumemanager.h - virtual LLVolumeLODGroup* createNewGroup(const LLVolumeParams& volume_params); + void insertGroup(LLVolumeLODGroup* volgroup); + // Overridden in llphysics/abstract/utils/llphysicsvolumemanager.h + virtual LLVolumeLODGroup* createNewGroup(const LLVolumeParams& volume_params); protected: - typedef std::map<const LLVolumeParams*, LLVolumeLODGroup*, LLVolumeParams::compare> volume_lod_group_map_t; - volume_lod_group_map_t mVolumeLODGroups; + typedef std::map<const LLVolumeParams*, LLVolumeLODGroup*, LLVolumeParams::compare> volume_lod_group_map_t; + volume_lod_group_map_t mVolumeLODGroups; - LLMutex* mDataMutex; + LLMutex* mDataMutex; }; #endif // LL_LLVOLUMEMGR_H diff --git a/indra/llmath/llvolumeoctree.cpp b/indra/llmath/llvolumeoctree.cpp index aa35b4cdd2..7a4d313fb1 100644 --- a/indra/llmath/llvolumeoctree.cpp +++ b/indra/llmath/llvolumeoctree.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llvolumeoctree.cpp * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -29,54 +29,54 @@ bool LLLineSegmentBoxIntersect(const LLVector4a& start, const LLVector4a& end, const LLVector4a& center, const LLVector4a& size) { - LLVector4a fAWdU; - LLVector4a dir; - LLVector4a diff; + LLVector4a fAWdU; + LLVector4a dir; + LLVector4a diff; + + dir.setSub(end, start); + dir.mul(0.5f); + + diff.setAdd(end,start); + diff.mul(0.5f); + diff.sub(center); + fAWdU.setAbs(dir); - dir.setSub(end, start); - dir.mul(0.5f); + LLVector4a rhs; + rhs.setAdd(size, fAWdU); - diff.setAdd(end,start); - diff.mul(0.5f); - diff.sub(center); - fAWdU.setAbs(dir); + LLVector4a lhs; + lhs.setAbs(diff); - LLVector4a rhs; - rhs.setAdd(size, fAWdU); + U32 grt = lhs.greaterThan(rhs).getGatheredBits(); - LLVector4a lhs; - lhs.setAbs(diff); + if (grt & 0x7) + { + return false; + } - U32 grt = lhs.greaterThan(rhs).getGatheredBits(); + LLVector4a f; + f.setCross3(dir, diff); + f.setAbs(f); - if (grt & 0x7) - { - return false; - } - - LLVector4a f; - f.setCross3(dir, diff); - f.setAbs(f); + LLVector4a v0, v1; - LLVector4a v0, v1; + v0 = _mm_shuffle_ps(size, size,_MM_SHUFFLE(3,0,0,1)); + v1 = _mm_shuffle_ps(fAWdU, fAWdU, _MM_SHUFFLE(3,1,2,2)); + lhs.setMul(v0, v1); - v0 = _mm_shuffle_ps(size, size,_MM_SHUFFLE(3,0,0,1)); - v1 = _mm_shuffle_ps(fAWdU, fAWdU, _MM_SHUFFLE(3,1,2,2)); - lhs.setMul(v0, v1); + v0 = _mm_shuffle_ps(size, size, _MM_SHUFFLE(3,1,2,2)); + v1 = _mm_shuffle_ps(fAWdU, fAWdU, _MM_SHUFFLE(3,0,0,1)); + rhs.setMul(v0, v1); + rhs.add(lhs); - v0 = _mm_shuffle_ps(size, size, _MM_SHUFFLE(3,1,2,2)); - v1 = _mm_shuffle_ps(fAWdU, fAWdU, _MM_SHUFFLE(3,0,0,1)); - rhs.setMul(v0, v1); - rhs.add(lhs); - - grt = f.greaterThan(rhs).getGatheredBits(); + grt = f.greaterThan(rhs).getGatheredBits(); - return (grt & 0x7) == 0; + return (grt & 0x7) == 0; } LLVolumeOctreeListener::LLVolumeOctreeListener(LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* node) { - node->addListener(this); + node->addListener(this); } LLVolumeOctreeListener::~LLVolumeOctreeListener() @@ -84,134 +84,134 @@ LLVolumeOctreeListener::~LLVolumeOctreeListener() } -void LLVolumeOctreeListener::handleChildAddition(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* parent, +void LLVolumeOctreeListener::handleChildAddition(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* parent, LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* child) { - new LLVolumeOctreeListener(child); + new LLVolumeOctreeListener(child); } -LLOctreeTriangleRayIntersect::LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir, +LLOctreeTriangleRayIntersect::LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir, LLVolumeFace* face, F32* closest_t, - LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) + LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) : mStart(start), - mDir(dir), - mIntersection(intersection), - mTexCoord(tex_coord), - mNormal(normal), - mTangent(tangent), + mDir(dir), + mIntersection(intersection), + mTexCoord(tex_coord), + mNormal(normal), + mTangent(tangent), mFace(face), - mClosestT(closest_t), - mHitFace(false) + mClosestT(closest_t), + mHitFace(false) { - mEnd.setAdd(mStart, mDir); + mEnd.setAdd(mStart, mDir); } void LLOctreeTriangleRayIntersect::traverse(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* node) { - LLVolumeOctreeListener* vl = (LLVolumeOctreeListener*) node->getListener(0); - - if (LLLineSegmentBoxIntersect(mStart, mEnd, vl->mBounds[0], vl->mBounds[1])) - { - node->accept(this); - for (S32 i = 0; i < node->getChildCount(); ++i) - { - traverse(node->getChild(i)); - } - } + LLVolumeOctreeListener* vl = (LLVolumeOctreeListener*) node->getListener(0); + + if (LLLineSegmentBoxIntersect(mStart, mEnd, vl->mBounds[0], vl->mBounds[1])) + { + node->accept(this); + for (S32 i = 0; i < node->getChildCount(); ++i) + { + traverse(node->getChild(i)); + } + } } void LLOctreeTriangleRayIntersect::visit(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* node) { for (typename LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>::const_element_iter iter = - node->getDataBegin(); iter != node->getDataEnd(); ++iter) - { - const LLVolumeTriangle* tri = *iter; - - F32 a, b, t; - - if (LLTriangleRayIntersect(*tri->mV[0], *tri->mV[1], *tri->mV[2], - mStart, mDir, a, b, t)) - { - if ((t >= 0.f) && // if hit is after start - (t <= 1.f) && // and before end - (t < *mClosestT)) // and this hit is closer - { - *mClosestT = t; - mHitFace = true; + node->getDataBegin(); iter != node->getDataEnd(); ++iter) + { + const LLVolumeTriangle* tri = *iter; + + F32 a, b, t; + + if (LLTriangleRayIntersect(*tri->mV[0], *tri->mV[1], *tri->mV[2], + mStart, mDir, a, b, t)) + { + if ((t >= 0.f) && // if hit is after start + (t <= 1.f) && // and before end + (t < *mClosestT)) // and this hit is closer + { + *mClosestT = t; + mHitFace = true; mHitTriangle = tri; - if (mIntersection != NULL) - { - LLVector4a intersect = mDir; - intersect.mul(*mClosestT); - intersect.add(mStart); - *mIntersection = intersect; - } - - U32 idx0 = tri->mIndex[0]; - U32 idx1 = tri->mIndex[1]; - U32 idx2 = tri->mIndex[2]; - - if (mTexCoord != NULL) - { - LLVector2* tc = (LLVector2*) mFace->mTexCoords; - *mTexCoord = ((1.f - a - b) * tc[idx0] + - a * tc[idx1] + - b * tc[idx2]); - - } - - if (mNormal != NULL) - { - LLVector4a* norm = mFace->mNormals; - - LLVector4a n1,n2,n3; - n1 = norm[idx0]; - n1.mul(1.f-a-b); - - n2 = norm[idx1]; - n2.mul(a); - - n3 = norm[idx2]; - n3.mul(b); - - n1.add(n2); - n1.add(n3); - - *mNormal = n1; - } - - if (mTangent != NULL) - { - LLVector4a* tangents = mFace->mTangents; - - LLVector4a t1,t2,t3; - t1 = tangents[idx0]; - t1.mul(1.f-a-b); - - t2 = tangents[idx1]; - t2.mul(a); - - t3 = tangents[idx2]; - t3.mul(b); - - t1.add(t2); - t1.add(t3); - - *mTangent = t1; - } - } - } - } + if (mIntersection != NULL) + { + LLVector4a intersect = mDir; + intersect.mul(*mClosestT); + intersect.add(mStart); + *mIntersection = intersect; + } + + U32 idx0 = tri->mIndex[0]; + U32 idx1 = tri->mIndex[1]; + U32 idx2 = tri->mIndex[2]; + + if (mTexCoord != NULL) + { + LLVector2* tc = (LLVector2*) mFace->mTexCoords; + *mTexCoord = ((1.f - a - b) * tc[idx0] + + a * tc[idx1] + + b * tc[idx2]); + + } + + if (mNormal != NULL) + { + LLVector4a* norm = mFace->mNormals; + + LLVector4a n1,n2,n3; + n1 = norm[idx0]; + n1.mul(1.f-a-b); + + n2 = norm[idx1]; + n2.mul(a); + + n3 = norm[idx2]; + n3.mul(b); + + n1.add(n2); + n1.add(n3); + + *mNormal = n1; + } + + if (mTangent != NULL) + { + LLVector4a* tangents = mFace->mTangents; + + LLVector4a t1,t2,t3; + t1 = tangents[idx0]; + t1.mul(1.f-a-b); + + t2 = tangents[idx1]; + t2.mul(a); + + t3 = tangents[idx2]; + t3.mul(b); + + t1.add(t2); + t1.add(t3); + + *mTangent = t1; + } + } + } + } } const LLVector4a& LLVolumeTriangle::getPositionGroup() const { - return mPositionGroup; + return mPositionGroup; } const F32& LLVolumeTriangle::getBinRadius() const { - return mRadius; + return mRadius; } @@ -219,55 +219,55 @@ const F32& LLVolumeTriangle::getBinRadius() const void LLVolumeOctreeValidate::visit(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* branch) { - LLVolumeOctreeListener* node = (LLVolumeOctreeListener*) branch->getListener(0); + LLVolumeOctreeListener* node = (LLVolumeOctreeListener*) branch->getListener(0); - //make sure bounds matches extents - LLVector4a& min = node->mExtents[0]; - LLVector4a& max = node->mExtents[1]; + //make sure bounds matches extents + LLVector4a& min = node->mExtents[0]; + LLVector4a& max = node->mExtents[1]; - LLVector4a& center = node->mBounds[0]; - LLVector4a& size = node->mBounds[1]; + LLVector4a& center = node->mBounds[0]; + LLVector4a& size = node->mBounds[1]; - LLVector4a test_min, test_max; - test_min.setSub(center, size); - test_max.setAdd(center, size); + LLVector4a test_min, test_max; + test_min.setSub(center, size); + test_max.setAdd(center, size); - if (!test_min.equals3(min, 0.001f) || - !test_max.equals3(max, 0.001f)) - { - LL_ERRS() << "Bad bounding box data found." << LL_ENDL; - } + if (!test_min.equals3(min, 0.001f) || + !test_max.equals3(max, 0.001f)) + { + LL_ERRS() << "Bad bounding box data found." << LL_ENDL; + } - test_min.sub(LLVector4a(0.001f)); - test_max.add(LLVector4a(0.001f)); + test_min.sub(LLVector4a(0.001f)); + test_max.add(LLVector4a(0.001f)); - for (U32 i = 0; i < branch->getChildCount(); ++i) - { - LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(i)->getListener(0); + for (U32 i = 0; i < branch->getChildCount(); ++i) + { + LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(i)->getListener(0); - //make sure all children fit inside this node - if (child->mExtents[0].lessThan(test_min).areAnySet(LLVector4Logical::MASK_XYZ) || - child->mExtents[1].greaterThan(test_max).areAnySet(LLVector4Logical::MASK_XYZ)) - { - LL_ERRS() << "Child protrudes from bounding box." << LL_ENDL; - } - } + //make sure all children fit inside this node + if (child->mExtents[0].lessThan(test_min).areAnySet(LLVector4Logical::MASK_XYZ) || + child->mExtents[1].greaterThan(test_max).areAnySet(LLVector4Logical::MASK_XYZ)) + { + LL_ERRS() << "Child protrudes from bounding box." << LL_ENDL; + } + } - //children fit, check data + //children fit, check data for (typename LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>::const_element_iter iter = branch->getDataBegin(); - iter != branch->getDataEnd(); ++iter) - { - const LLVolumeTriangle* tri = *iter; - - //validate triangle - for (U32 i = 0; i < 3; i++) - { - if (tri->mV[i]->greaterThan(test_max).areAnySet(LLVector4Logical::MASK_XYZ) || - tri->mV[i]->lessThan(test_min).areAnySet(LLVector4Logical::MASK_XYZ)) - { - LL_ERRS() << "Triangle protrudes from node." << LL_ENDL; - } - } - } + iter != branch->getDataEnd(); ++iter) + { + const LLVolumeTriangle* tri = *iter; + + //validate triangle + for (U32 i = 0; i < 3; i++) + { + if (tri->mV[i]->greaterThan(test_max).areAnySet(LLVector4Logical::MASK_XYZ) || + tri->mV[i]->lessThan(test_min).areAnySet(LLVector4Logical::MASK_XYZ)) + { + LL_ERRS() << "Triangle protrudes from node." << LL_ENDL; + } + } + } } diff --git a/indra/llmath/llvolumeoctree.h b/indra/llmath/llvolumeoctree.h index 1df2bf5390..838e1d3db0 100644 --- a/indra/llmath/llvolumeoctree.h +++ b/indra/llmath/llvolumeoctree.h @@ -1,25 +1,25 @@ -/** +/** * @file llvolumeoctree.h * @brief LLVolume octree classes. * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,35 +38,35 @@ class alignas(16) LLVolumeTriangle : public LLRefCount { LL_ALIGN_NEW public: - LLVolumeTriangle() - { - mBinIndex = -1; - } + LLVolumeTriangle() + { + mBinIndex = -1; + } - LLVolumeTriangle(const LLVolumeTriangle& rhs) - { - *this = rhs; - } + LLVolumeTriangle(const LLVolumeTriangle& rhs) + { + *this = rhs; + } - ~LLVolumeTriangle() - { - - } + ~LLVolumeTriangle() + { + + } - LL_ALIGN_16(LLVector4a mPositionGroup); + LL_ALIGN_16(LLVector4a mPositionGroup); - const LLVector4a* mV[3]; - U32 mIndex[3]; + const LLVector4a* mV[3]; + U32 mIndex[3]; - F32 mRadius; - mutable S32 mBinIndex; + F32 mRadius; + mutable S32 mBinIndex; - virtual const LLVector4a& getPositionGroup() const; - virtual const F32& getBinRadius() const; - - S32 getBinIndex() const { return mBinIndex; } - void setBinIndex(S32 idx) const { mBinIndex = idx; } + virtual const LLVector4a& getPositionGroup() const; + virtual const F32& getBinRadius() const; + + S32 getBinIndex() const { return mBinIndex; } + void setBinIndex(S32 idx) const { mBinIndex = idx; } }; @@ -76,52 +76,52 @@ class alignas(16) LLVolumeOctreeListener : public LLOctreeListener<LLVolumeTrian LL_ALIGN_NEW public: LLVolumeOctreeListener(LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* node); - ~LLVolumeOctreeListener(); - - LLVolumeOctreeListener(const LLVolumeOctreeListener& rhs) - { - *this = rhs; - } - - const LLVolumeOctreeListener& operator=(const LLVolumeOctreeListener& rhs) - { - LL_ERRS() << "Illegal operation!" << LL_ENDL; - return *this; - } - - //LISTENER FUNCTIONS + ~LLVolumeOctreeListener(); + + LLVolumeOctreeListener(const LLVolumeOctreeListener& rhs) + { + *this = rhs; + } + + const LLVolumeOctreeListener& operator=(const LLVolumeOctreeListener& rhs) + { + LL_ERRS() << "Illegal operation!" << LL_ENDL; + return *this; + } + + //LISTENER FUNCTIONS virtual void handleChildAddition(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* parent, LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* child); - virtual void handleStateChange(const LLTreeNode<LLVolumeTriangle>* node) { } + virtual void handleStateChange(const LLTreeNode<LLVolumeTriangle>* node) { } virtual void handleChildRemoval(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* parent, const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* child) { } - virtual void handleInsertion(const LLTreeNode<LLVolumeTriangle>* node, LLVolumeTriangle* tri) { } - virtual void handleRemoval(const LLTreeNode<LLVolumeTriangle>* node, LLVolumeTriangle* tri) { } - virtual void handleDestruction(const LLTreeNode<LLVolumeTriangle>* node) { } - + virtual void handleInsertion(const LLTreeNode<LLVolumeTriangle>* node, LLVolumeTriangle* tri) { } + virtual void handleRemoval(const LLTreeNode<LLVolumeTriangle>* node, LLVolumeTriangle* tri) { } + virtual void handleDestruction(const LLTreeNode<LLVolumeTriangle>* node) { } + public: - LL_ALIGN_16(LLVector4a mBounds[2]); // bounding box (center, size) of this node and all its children (tight fit to objects) - LL_ALIGN_16(LLVector4a mExtents[2]); // extents (min, max) of this node and all its children + LL_ALIGN_16(LLVector4a mBounds[2]); // bounding box (center, size) of this node and all its children (tight fit to objects) + LL_ALIGN_16(LLVector4a mExtents[2]); // extents (min, max) of this node and all its children }; class LLOctreeTriangleRayIntersect : public LLOctreeTraveler<LLVolumeTriangle, LLVolumeTriangle*> { public: - LLVector4a mStart; - LLVector4a mDir; - LLVector4a mEnd; - LLVector4a* mIntersection; - LLVector2* mTexCoord; - LLVector4a* mNormal; - LLVector4a* mTangent; - F32* mClosestT; + LLVector4a mStart; + LLVector4a mDir; + LLVector4a mEnd; + LLVector4a* mIntersection; + LLVector2* mTexCoord; + LLVector4a* mNormal; + LLVector4a* mTangent; + F32* mClosestT; LLVolumeFace* mFace; - bool mHitFace; + bool mHitFace; const LLVolumeTriangle* mHitTriangle = nullptr; - LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir, + LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir, LLVolumeFace* face, - F32* closest_t, - LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent); + F32* closest_t, + LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent); void traverse(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* node); @@ -211,7 +211,7 @@ public: { new LLVolumeOctreeListener(this); } - + LLVolumeOctree() : LLOctreeRoot<LLVolumeTriangle, LLVolumeTriangle*>(LLVector4a::getZero(), LLVector4a(1.f,1.f,1.f), nullptr), LLRefCount() diff --git a/indra/llmath/m3math.cpp b/indra/llmath/m3math.cpp index c7777164c0..472d340af5 100644 --- a/indra/llmath/m3math.cpp +++ b/indra/llmath/m3math.cpp @@ -1,25 +1,25 @@ -/** +/** * @file m3math.cpp * @brief LLMatrix3 class implementation. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -36,7 +36,7 @@ // LLMatrix3 -// ji +// ji // LLMatrix3 = |00 01 02 | // |10 11 12 | // |20 21 22 | @@ -51,266 +51,266 @@ LLMatrix3::LLMatrix3(const LLQuaternion &q) { - setRot(q); + setRot(q); } LLMatrix3::LLMatrix3(const F32 angle, const LLVector3 &vec) { - LLQuaternion quat(angle, vec); - setRot(quat); + LLQuaternion quat(angle, vec); + setRot(quat); } LLMatrix3::LLMatrix3(const F32 angle, const LLVector3d &vec) { - LLVector3 vec_f; - vec_f.setVec(vec); - LLQuaternion quat(angle, vec_f); - setRot(quat); + LLVector3 vec_f; + vec_f.setVec(vec); + LLQuaternion quat(angle, vec_f); + setRot(quat); } LLMatrix3::LLMatrix3(const F32 angle, const LLVector4 &vec) { - LLQuaternion quat(angle, vec); - setRot(quat); + LLQuaternion quat(angle, vec); + setRot(quat); } LLMatrix3::LLMatrix3(const F32 roll, const F32 pitch, const F32 yaw) { - setRot(roll,pitch,yaw); + setRot(roll,pitch,yaw); } // From Matrix and Quaternion FAQ void LLMatrix3::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const { - F64 angle_x, angle_y, angle_z; - F64 cx, cy, cz; // cosine of angle_x, angle_y, angle_z - F64 sx, sz; // sine of angle_x, angle_y, angle_z + F64 angle_x, angle_y, angle_z; + F64 cx, cy, cz; // cosine of angle_x, angle_y, angle_z + F64 sx, sz; // sine of angle_x, angle_y, angle_z - angle_y = asin(llclamp(mMatrix[2][0], -1.f, 1.f)); - cy = cos(angle_y); + angle_y = asin(llclamp(mMatrix[2][0], -1.f, 1.f)); + cy = cos(angle_y); - if (fabs(cy) > 0.005) // non-zero - { - // no gimbal lock - cx = mMatrix[2][2] / cy; - sx = - mMatrix[2][1] / cy; + if (fabs(cy) > 0.005) // non-zero + { + // no gimbal lock + cx = mMatrix[2][2] / cy; + sx = - mMatrix[2][1] / cy; - angle_x = (F32) atan2(sx, cx); + angle_x = (F32) atan2(sx, cx); - cz = mMatrix[0][0] / cy; - sz = - mMatrix[1][0] / cy; + cz = mMatrix[0][0] / cy; + sz = - mMatrix[1][0] / cy; - angle_z = (F32) atan2(sz, cz); - } - else - { - // yup, gimbal lock - angle_x = 0; + angle_z = (F32) atan2(sz, cz); + } + else + { + // yup, gimbal lock + angle_x = 0; - // some tricky math thereby avoided, see article + // some tricky math thereby avoided, see article - cz = mMatrix[1][1]; - sz = mMatrix[0][1]; + cz = mMatrix[1][1]; + sz = mMatrix[0][1]; - angle_z = atan2(sz, cz); - } + angle_z = atan2(sz, cz); + } - *roll = (F32)angle_x; - *pitch = (F32)angle_y; - *yaw = (F32)angle_z; + *roll = (F32)angle_x; + *pitch = (F32)angle_y; + *yaw = (F32)angle_z; } - + // Clear and Assignment Functions -const LLMatrix3& LLMatrix3::setIdentity() +const LLMatrix3& LLMatrix3::setIdentity() { - mMatrix[0][0] = 1.f; - mMatrix[0][1] = 0.f; - mMatrix[0][2] = 0.f; + mMatrix[0][0] = 1.f; + mMatrix[0][1] = 0.f; + mMatrix[0][2] = 0.f; - mMatrix[1][0] = 0.f; - mMatrix[1][1] = 1.f; - mMatrix[1][2] = 0.f; + mMatrix[1][0] = 0.f; + mMatrix[1][1] = 1.f; + mMatrix[1][2] = 0.f; - mMatrix[2][0] = 0.f; - mMatrix[2][1] = 0.f; - mMatrix[2][2] = 1.f; - return (*this); + mMatrix[2][0] = 0.f; + mMatrix[2][1] = 0.f; + mMatrix[2][2] = 1.f; + return (*this); } -const LLMatrix3& LLMatrix3::clear() +const LLMatrix3& LLMatrix3::clear() { - mMatrix[0][0] = 0.f; - mMatrix[0][1] = 0.f; - mMatrix[0][2] = 0.f; + mMatrix[0][0] = 0.f; + mMatrix[0][1] = 0.f; + mMatrix[0][2] = 0.f; - mMatrix[1][0] = 0.f; - mMatrix[1][1] = 0.f; - mMatrix[1][2] = 0.f; + mMatrix[1][0] = 0.f; + mMatrix[1][1] = 0.f; + mMatrix[1][2] = 0.f; - mMatrix[2][0] = 0.f; - mMatrix[2][1] = 0.f; - mMatrix[2][2] = 0.f; - return (*this); + mMatrix[2][0] = 0.f; + mMatrix[2][1] = 0.f; + mMatrix[2][2] = 0.f; + return (*this); } -const LLMatrix3& LLMatrix3::setZero() +const LLMatrix3& LLMatrix3::setZero() { - mMatrix[0][0] = 0.f; - mMatrix[0][1] = 0.f; - mMatrix[0][2] = 0.f; + mMatrix[0][0] = 0.f; + mMatrix[0][1] = 0.f; + mMatrix[0][2] = 0.f; - mMatrix[1][0] = 0.f; - mMatrix[1][1] = 0.f; - mMatrix[1][2] = 0.f; + mMatrix[1][0] = 0.f; + mMatrix[1][1] = 0.f; + mMatrix[1][2] = 0.f; - mMatrix[2][0] = 0.f; - mMatrix[2][1] = 0.f; - mMatrix[2][2] = 0.f; - return (*this); + mMatrix[2][0] = 0.f; + mMatrix[2][1] = 0.f; + mMatrix[2][2] = 0.f; + return (*this); } // various useful mMatrix functions -const LLMatrix3& LLMatrix3::transpose() +const LLMatrix3& LLMatrix3::transpose() { - // transpose the matrix - F32 temp; - temp = mMatrix[VX][VY]; mMatrix[VX][VY] = mMatrix[VY][VX]; mMatrix[VY][VX] = temp; - temp = mMatrix[VX][VZ]; mMatrix[VX][VZ] = mMatrix[VZ][VX]; mMatrix[VZ][VX] = temp; - temp = mMatrix[VY][VZ]; mMatrix[VY][VZ] = mMatrix[VZ][VY]; mMatrix[VZ][VY] = temp; - return *this; + // transpose the matrix + F32 temp; + temp = mMatrix[VX][VY]; mMatrix[VX][VY] = mMatrix[VY][VX]; mMatrix[VY][VX] = temp; + temp = mMatrix[VX][VZ]; mMatrix[VX][VZ] = mMatrix[VZ][VX]; mMatrix[VZ][VX] = temp; + temp = mMatrix[VY][VZ]; mMatrix[VY][VZ] = mMatrix[VZ][VY]; mMatrix[VZ][VY] = temp; + return *this; } -F32 LLMatrix3::determinant() const +F32 LLMatrix3::determinant() const { - // Is this a useful method when we assume the matrices are valid rotation - // matrices throughout this implementation? - return mMatrix[0][0] * (mMatrix[1][1] * mMatrix[2][2] - mMatrix[1][2] * mMatrix[2][1]) + - mMatrix[0][1] * (mMatrix[1][2] * mMatrix[2][0] - mMatrix[1][0] * mMatrix[2][2]) + - mMatrix[0][2] * (mMatrix[1][0] * mMatrix[2][1] - mMatrix[1][1] * mMatrix[2][0]); + // Is this a useful method when we assume the matrices are valid rotation + // matrices throughout this implementation? + return mMatrix[0][0] * (mMatrix[1][1] * mMatrix[2][2] - mMatrix[1][2] * mMatrix[2][1]) + + mMatrix[0][1] * (mMatrix[1][2] * mMatrix[2][0] - mMatrix[1][0] * mMatrix[2][2]) + + mMatrix[0][2] * (mMatrix[1][0] * mMatrix[2][1] - mMatrix[1][1] * mMatrix[2][0]); } // inverts this matrix void LLMatrix3::invert() { - // fails silently if determinant is zero too small - F32 det = determinant(); - const F32 VERY_SMALL_DETERMINANT = 0.000001f; - if (fabs(det) > VERY_SMALL_DETERMINANT) - { - // invertiable - LLMatrix3 t(*this); - mMatrix[VX][VX] = ( t.mMatrix[VY][VY] * t.mMatrix[VZ][VZ] - t.mMatrix[VY][VZ] * t.mMatrix[VZ][VY] ) / det; - mMatrix[VY][VX] = ( t.mMatrix[VY][VZ] * t.mMatrix[VZ][VX] - t.mMatrix[VY][VX] * t.mMatrix[VZ][VZ] ) / det; - mMatrix[VZ][VX] = ( t.mMatrix[VY][VX] * t.mMatrix[VZ][VY] - t.mMatrix[VY][VY] * t.mMatrix[VZ][VX] ) / det; - mMatrix[VX][VY] = ( t.mMatrix[VZ][VY] * t.mMatrix[VX][VZ] - t.mMatrix[VZ][VZ] * t.mMatrix[VX][VY] ) / det; - mMatrix[VY][VY] = ( t.mMatrix[VZ][VZ] * t.mMatrix[VX][VX] - t.mMatrix[VZ][VX] * t.mMatrix[VX][VZ] ) / det; - mMatrix[VZ][VY] = ( t.mMatrix[VZ][VX] * t.mMatrix[VX][VY] - t.mMatrix[VZ][VY] * t.mMatrix[VX][VX] ) / det; - mMatrix[VX][VZ] = ( t.mMatrix[VX][VY] * t.mMatrix[VY][VZ] - t.mMatrix[VX][VZ] * t.mMatrix[VY][VY] ) / det; - mMatrix[VY][VZ] = ( t.mMatrix[VX][VZ] * t.mMatrix[VY][VX] - t.mMatrix[VX][VX] * t.mMatrix[VY][VZ] ) / det; - mMatrix[VZ][VZ] = ( t.mMatrix[VX][VX] * t.mMatrix[VY][VY] - t.mMatrix[VX][VY] * t.mMatrix[VY][VX] ) / det; - } + // fails silently if determinant is zero too small + F32 det = determinant(); + const F32 VERY_SMALL_DETERMINANT = 0.000001f; + if (fabs(det) > VERY_SMALL_DETERMINANT) + { + // invertiable + LLMatrix3 t(*this); + mMatrix[VX][VX] = ( t.mMatrix[VY][VY] * t.mMatrix[VZ][VZ] - t.mMatrix[VY][VZ] * t.mMatrix[VZ][VY] ) / det; + mMatrix[VY][VX] = ( t.mMatrix[VY][VZ] * t.mMatrix[VZ][VX] - t.mMatrix[VY][VX] * t.mMatrix[VZ][VZ] ) / det; + mMatrix[VZ][VX] = ( t.mMatrix[VY][VX] * t.mMatrix[VZ][VY] - t.mMatrix[VY][VY] * t.mMatrix[VZ][VX] ) / det; + mMatrix[VX][VY] = ( t.mMatrix[VZ][VY] * t.mMatrix[VX][VZ] - t.mMatrix[VZ][VZ] * t.mMatrix[VX][VY] ) / det; + mMatrix[VY][VY] = ( t.mMatrix[VZ][VZ] * t.mMatrix[VX][VX] - t.mMatrix[VZ][VX] * t.mMatrix[VX][VZ] ) / det; + mMatrix[VZ][VY] = ( t.mMatrix[VZ][VX] * t.mMatrix[VX][VY] - t.mMatrix[VZ][VY] * t.mMatrix[VX][VX] ) / det; + mMatrix[VX][VZ] = ( t.mMatrix[VX][VY] * t.mMatrix[VY][VZ] - t.mMatrix[VX][VZ] * t.mMatrix[VY][VY] ) / det; + mMatrix[VY][VZ] = ( t.mMatrix[VX][VZ] * t.mMatrix[VY][VX] - t.mMatrix[VX][VX] * t.mMatrix[VY][VZ] ) / det; + mMatrix[VZ][VZ] = ( t.mMatrix[VX][VX] * t.mMatrix[VY][VY] - t.mMatrix[VX][VY] * t.mMatrix[VY][VX] ) / det; + } } // does not assume a rotation matrix, and does not divide by determinant, assuming results will be renormalized -const LLMatrix3& LLMatrix3::adjointTranspose() +const LLMatrix3& LLMatrix3::adjointTranspose() { - LLMatrix3 adjoint_transpose; - adjoint_transpose.mMatrix[VX][VX] = mMatrix[VY][VY] * mMatrix[VZ][VZ] - mMatrix[VY][VZ] * mMatrix[VZ][VY] ; - adjoint_transpose.mMatrix[VY][VX] = mMatrix[VY][VZ] * mMatrix[VZ][VX] - mMatrix[VY][VX] * mMatrix[VZ][VZ] ; - adjoint_transpose.mMatrix[VZ][VX] = mMatrix[VY][VX] * mMatrix[VZ][VY] - mMatrix[VY][VY] * mMatrix[VZ][VX] ; - adjoint_transpose.mMatrix[VX][VY] = mMatrix[VZ][VY] * mMatrix[VX][VZ] - mMatrix[VZ][VZ] * mMatrix[VX][VY] ; - adjoint_transpose.mMatrix[VY][VY] = mMatrix[VZ][VZ] * mMatrix[VX][VX] - mMatrix[VZ][VX] * mMatrix[VX][VZ] ; - adjoint_transpose.mMatrix[VZ][VY] = mMatrix[VZ][VX] * mMatrix[VX][VY] - mMatrix[VZ][VY] * mMatrix[VX][VX] ; - adjoint_transpose.mMatrix[VX][VZ] = mMatrix[VX][VY] * mMatrix[VY][VZ] - mMatrix[VX][VZ] * mMatrix[VY][VY] ; - adjoint_transpose.mMatrix[VY][VZ] = mMatrix[VX][VZ] * mMatrix[VY][VX] - mMatrix[VX][VX] * mMatrix[VY][VZ] ; - adjoint_transpose.mMatrix[VZ][VZ] = mMatrix[VX][VX] * mMatrix[VY][VY] - mMatrix[VX][VY] * mMatrix[VY][VX] ; + LLMatrix3 adjoint_transpose; + adjoint_transpose.mMatrix[VX][VX] = mMatrix[VY][VY] * mMatrix[VZ][VZ] - mMatrix[VY][VZ] * mMatrix[VZ][VY] ; + adjoint_transpose.mMatrix[VY][VX] = mMatrix[VY][VZ] * mMatrix[VZ][VX] - mMatrix[VY][VX] * mMatrix[VZ][VZ] ; + adjoint_transpose.mMatrix[VZ][VX] = mMatrix[VY][VX] * mMatrix[VZ][VY] - mMatrix[VY][VY] * mMatrix[VZ][VX] ; + adjoint_transpose.mMatrix[VX][VY] = mMatrix[VZ][VY] * mMatrix[VX][VZ] - mMatrix[VZ][VZ] * mMatrix[VX][VY] ; + adjoint_transpose.mMatrix[VY][VY] = mMatrix[VZ][VZ] * mMatrix[VX][VX] - mMatrix[VZ][VX] * mMatrix[VX][VZ] ; + adjoint_transpose.mMatrix[VZ][VY] = mMatrix[VZ][VX] * mMatrix[VX][VY] - mMatrix[VZ][VY] * mMatrix[VX][VX] ; + adjoint_transpose.mMatrix[VX][VZ] = mMatrix[VX][VY] * mMatrix[VY][VZ] - mMatrix[VX][VZ] * mMatrix[VY][VY] ; + adjoint_transpose.mMatrix[VY][VZ] = mMatrix[VX][VZ] * mMatrix[VY][VX] - mMatrix[VX][VX] * mMatrix[VY][VZ] ; + adjoint_transpose.mMatrix[VZ][VZ] = mMatrix[VX][VX] * mMatrix[VY][VY] - mMatrix[VX][VY] * mMatrix[VY][VX] ; - *this = adjoint_transpose; - return *this; + *this = adjoint_transpose; + return *this; } // SJB: This code is correct for a logicly stored (non-transposed) matrix; -// Our matrices are stored transposed, OpenGL style, so this generates the -// INVERSE quaternion (-x, -y, -z, w)! -// Because we use similar logic in LLQuaternion::getMatrix3, -// we are internally consistant so everything works OK :) -LLQuaternion LLMatrix3::quaternion() const -{ - LLQuaternion quat; - F32 tr, s, q[4]; - U32 i, j, k; - U32 nxt[3] = {1, 2, 0}; - - tr = mMatrix[0][0] + mMatrix[1][1] + mMatrix[2][2]; - - // check the diagonal - if (tr > 0.f) - { - s = (F32)sqrt (tr + 1.f); - quat.mQ[VS] = s / 2.f; - s = 0.5f / s; - quat.mQ[VX] = (mMatrix[1][2] - mMatrix[2][1]) * s; - quat.mQ[VY] = (mMatrix[2][0] - mMatrix[0][2]) * s; - quat.mQ[VZ] = (mMatrix[0][1] - mMatrix[1][0]) * s; - } - else - { - // diagonal is negative - i = 0; - if (mMatrix[1][1] > mMatrix[0][0]) - i = 1; - if (mMatrix[2][2] > mMatrix[i][i]) - i = 2; - - j = nxt[i]; - k = nxt[j]; - - - s = (F32)sqrt ((mMatrix[i][i] - (mMatrix[j][j] + mMatrix[k][k])) + 1.f); - - q[i] = s * 0.5f; - - if (s != 0.f) - s = 0.5f / s; - - q[3] = (mMatrix[j][k] - mMatrix[k][j]) * s; - q[j] = (mMatrix[i][j] + mMatrix[j][i]) * s; - q[k] = (mMatrix[i][k] + mMatrix[k][i]) * s; - - quat.setQuat(q); - } - return quat; -} - -const LLMatrix3& LLMatrix3::setRot(const F32 angle, const LLVector3 &vec) -{ - setRot(LLQuaternion(angle, vec)); - return *this; -} - -const LLMatrix3& LLMatrix3::setRot(const F32 roll, const F32 pitch, const F32 yaw) -{ - // Rotates RH about x-axis by 'roll' then - // rotates RH about the old y-axis by 'pitch' then - // rotates RH about the original z-axis by 'yaw'. - // . - // /|\ yaw axis - // | __. - // ._ ___| /| pitch axis - // _||\ \\ |-. / - // \|| \_______\_|__\_/_______ - // | _ _ o o o_o_o_o o /_\_ ________\ roll axis - // // /_______/ /__________> / - // /_,-' // / - // /__,-' - - F32 cx, sx, cy, sy, cz, sz; - F32 cxsy, sxsy; +// Our matrices are stored transposed, OpenGL style, so this generates the +// INVERSE quaternion (-x, -y, -z, w)! +// Because we use similar logic in LLQuaternion::getMatrix3, +// we are internally consistant so everything works OK :) +LLQuaternion LLMatrix3::quaternion() const +{ + LLQuaternion quat; + F32 tr, s, q[4]; + U32 i, j, k; + U32 nxt[3] = {1, 2, 0}; + + tr = mMatrix[0][0] + mMatrix[1][1] + mMatrix[2][2]; + + // check the diagonal + if (tr > 0.f) + { + s = (F32)sqrt (tr + 1.f); + quat.mQ[VS] = s / 2.f; + s = 0.5f / s; + quat.mQ[VX] = (mMatrix[1][2] - mMatrix[2][1]) * s; + quat.mQ[VY] = (mMatrix[2][0] - mMatrix[0][2]) * s; + quat.mQ[VZ] = (mMatrix[0][1] - mMatrix[1][0]) * s; + } + else + { + // diagonal is negative + i = 0; + if (mMatrix[1][1] > mMatrix[0][0]) + i = 1; + if (mMatrix[2][2] > mMatrix[i][i]) + i = 2; + + j = nxt[i]; + k = nxt[j]; + + + s = (F32)sqrt ((mMatrix[i][i] - (mMatrix[j][j] + mMatrix[k][k])) + 1.f); + + q[i] = s * 0.5f; + + if (s != 0.f) + s = 0.5f / s; + + q[3] = (mMatrix[j][k] - mMatrix[k][j]) * s; + q[j] = (mMatrix[i][j] + mMatrix[j][i]) * s; + q[k] = (mMatrix[i][k] + mMatrix[k][i]) * s; + + quat.setQuat(q); + } + return quat; +} + +const LLMatrix3& LLMatrix3::setRot(const F32 angle, const LLVector3 &vec) +{ + setRot(LLQuaternion(angle, vec)); + return *this; +} + +const LLMatrix3& LLMatrix3::setRot(const F32 roll, const F32 pitch, const F32 yaw) +{ + // Rotates RH about x-axis by 'roll' then + // rotates RH about the old y-axis by 'pitch' then + // rotates RH about the original z-axis by 'yaw'. + // . + // /|\ yaw axis + // | __. + // ._ ___| /| pitch axis + // _||\ \\ |-. / + // \|| \_______\_|__\_/_______ + // | _ _ o o o_o_o_o o /_\_ ________\ roll axis + // // /_______/ /__________> / + // /_,-' // / + // /__,-' + + F32 cx, sx, cy, sy, cz, sz; + F32 cxsy, sxsy; cx = (F32)cos(roll); //A sx = (F32)sin(roll); //B @@ -320,7 +320,7 @@ const LLMatrix3& LLMatrix3::setRot(const F32 roll, const F32 pitch, const F32 ya sz = (F32)sin(yaw); //F cxsy = cx * sy; //AD - sxsy = sx * sy; //BD + sxsy = sx * sy; //BD mMatrix[0][0] = cy * cz; mMatrix[1][0] = -cy * sz; @@ -331,118 +331,118 @@ const LLMatrix3& LLMatrix3::setRot(const F32 roll, const F32 pitch, const F32 ya mMatrix[0][2] = -cxsy * cz + sx * sz; mMatrix[1][2] = cxsy * sz + sx * cz; mMatrix[2][2] = cx * cy; - return *this; + return *this; } -const LLMatrix3& LLMatrix3::setRot(const LLQuaternion &q) +const LLMatrix3& LLMatrix3::setRot(const LLQuaternion &q) { - *this = q.getMatrix3(); - return *this; + *this = q.getMatrix3(); + return *this; } -const LLMatrix3& LLMatrix3::setRows(const LLVector3 &fwd, const LLVector3 &left, const LLVector3 &up) +const LLMatrix3& LLMatrix3::setRows(const LLVector3 &fwd, const LLVector3 &left, const LLVector3 &up) { - mMatrix[0][0] = fwd.mV[0]; - mMatrix[0][1] = fwd.mV[1]; - mMatrix[0][2] = fwd.mV[2]; + mMatrix[0][0] = fwd.mV[0]; + mMatrix[0][1] = fwd.mV[1]; + mMatrix[0][2] = fwd.mV[2]; - mMatrix[1][0] = left.mV[0]; - mMatrix[1][1] = left.mV[1]; - mMatrix[1][2] = left.mV[2]; + mMatrix[1][0] = left.mV[0]; + mMatrix[1][1] = left.mV[1]; + mMatrix[1][2] = left.mV[2]; - mMatrix[2][0] = up.mV[0]; - mMatrix[2][1] = up.mV[1]; - mMatrix[2][2] = up.mV[2]; + mMatrix[2][0] = up.mV[0]; + mMatrix[2][1] = up.mV[1]; + mMatrix[2][2] = up.mV[2]; - return *this; + return *this; } const LLMatrix3& LLMatrix3::setRow( U32 rowIndex, const LLVector3& row ) { - llassert( rowIndex >= 0 && rowIndex < NUM_VALUES_IN_MAT3 ); + llassert( rowIndex >= 0 && rowIndex < NUM_VALUES_IN_MAT3 ); - mMatrix[rowIndex][0] = row[0]; - mMatrix[rowIndex][1] = row[1]; - mMatrix[rowIndex][2] = row[2]; + mMatrix[rowIndex][0] = row[0]; + mMatrix[rowIndex][1] = row[1]; + mMatrix[rowIndex][2] = row[2]; - return *this; + return *this; } const LLMatrix3& LLMatrix3::setCol( U32 colIndex, const LLVector3& col ) { - llassert( colIndex >= 0 && colIndex < NUM_VALUES_IN_MAT3 ); + llassert( colIndex >= 0 && colIndex < NUM_VALUES_IN_MAT3 ); - mMatrix[0][colIndex] = col[0]; - mMatrix[1][colIndex] = col[1]; - mMatrix[2][colIndex] = col[2]; + mMatrix[0][colIndex] = col[0]; + mMatrix[1][colIndex] = col[1]; + mMatrix[2][colIndex] = col[2]; - return *this; + return *this; } -const LLMatrix3& LLMatrix3::rotate(const F32 angle, const LLVector3 &vec) +const LLMatrix3& LLMatrix3::rotate(const F32 angle, const LLVector3 &vec) { - LLMatrix3 mat(angle, vec); - *this *= mat; - return *this; + LLMatrix3 mat(angle, vec); + *this *= mat; + return *this; } -const LLMatrix3& LLMatrix3::rotate(const F32 roll, const F32 pitch, const F32 yaw) +const LLMatrix3& LLMatrix3::rotate(const F32 roll, const F32 pitch, const F32 yaw) { - LLMatrix3 mat(roll, pitch, yaw); - *this *= mat; - return *this; + LLMatrix3 mat(roll, pitch, yaw); + *this *= mat; + return *this; } -const LLMatrix3& LLMatrix3::rotate(const LLQuaternion &q) +const LLMatrix3& LLMatrix3::rotate(const LLQuaternion &q) { - LLMatrix3 mat(q); - *this *= mat; - return *this; + LLMatrix3 mat(q); + *this *= mat; + return *this; } void LLMatrix3::add(const LLMatrix3& other_matrix) { - for (S32 i = 0; i < 3; ++i) - { - for (S32 j = 0; j < 3; ++j) - { - mMatrix[i][j] += other_matrix.mMatrix[i][j]; - } - } + for (S32 i = 0; i < 3; ++i) + { + for (S32 j = 0; j < 3; ++j) + { + mMatrix[i][j] += other_matrix.mMatrix[i][j]; + } + } } -LLVector3 LLMatrix3::getFwdRow() const +LLVector3 LLMatrix3::getFwdRow() const { - return LLVector3(mMatrix[VX]); + return LLVector3(mMatrix[VX]); } -LLVector3 LLMatrix3::getLeftRow() const +LLVector3 LLMatrix3::getLeftRow() const { - return LLVector3(mMatrix[VY]); + return LLVector3(mMatrix[VY]); } -LLVector3 LLMatrix3::getUpRow() const +LLVector3 LLMatrix3::getUpRow() const { - return LLVector3(mMatrix[VZ]); + return LLVector3(mMatrix[VZ]); } -const LLMatrix3& LLMatrix3::orthogonalize() +const LLMatrix3& LLMatrix3::orthogonalize() { - LLVector3 x_axis(mMatrix[VX]); - LLVector3 y_axis(mMatrix[VY]); - LLVector3 z_axis(mMatrix[VZ]); + LLVector3 x_axis(mMatrix[VX]); + LLVector3 y_axis(mMatrix[VY]); + LLVector3 z_axis(mMatrix[VZ]); - x_axis.normVec(); - y_axis -= x_axis * (x_axis * y_axis); - y_axis.normVec(); - z_axis = x_axis % y_axis; - setRows(x_axis, y_axis, z_axis); - return (*this); + x_axis.normVec(); + y_axis -= x_axis * (x_axis * y_axis); + y_axis.normVec(); + z_axis = x_axis % y_axis; + setRows(x_axis, y_axis, z_axis); + return (*this); } @@ -450,141 +450,141 @@ const LLMatrix3& LLMatrix3::orthogonalize() LLMatrix3 operator*(const LLMatrix3 &a, const LLMatrix3 &b) { - U32 i, j; - LLMatrix3 mat; - for (i = 0; i < NUM_VALUES_IN_MAT3; i++) - { - for (j = 0; j < NUM_VALUES_IN_MAT3; j++) - { - mat.mMatrix[j][i] = a.mMatrix[j][0] * b.mMatrix[0][i] + - a.mMatrix[j][1] * b.mMatrix[1][i] + - a.mMatrix[j][2] * b.mMatrix[2][i]; - } - } - return mat; -} - -/* Not implemented to help enforce code consistency with the syntax of + U32 i, j; + LLMatrix3 mat; + for (i = 0; i < NUM_VALUES_IN_MAT3; i++) + { + for (j = 0; j < NUM_VALUES_IN_MAT3; j++) + { + mat.mMatrix[j][i] = a.mMatrix[j][0] * b.mMatrix[0][i] + + a.mMatrix[j][1] * b.mMatrix[1][i] + + a.mMatrix[j][2] * b.mMatrix[2][i]; + } + } + return mat; +} + +/* Not implemented to help enforce code consistency with the syntax of row-major notation. This is a Good Thing. LLVector3 operator*(const LLMatrix3 &a, const LLVector3 &b) { - LLVector3 vec; - // matrix operates "from the left" on column vector - vec.mV[VX] = a.mMatrix[VX][VX] * b.mV[VX] + - a.mMatrix[VX][VY] * b.mV[VY] + - a.mMatrix[VX][VZ] * b.mV[VZ]; - - vec.mV[VY] = a.mMatrix[VY][VX] * b.mV[VX] + - a.mMatrix[VY][VY] * b.mV[VY] + - a.mMatrix[VY][VZ] * b.mV[VZ]; - - vec.mV[VZ] = a.mMatrix[VZ][VX] * b.mV[VX] + - a.mMatrix[VZ][VY] * b.mV[VY] + - a.mMatrix[VZ][VZ] * b.mV[VZ]; - return vec; + LLVector3 vec; + // matrix operates "from the left" on column vector + vec.mV[VX] = a.mMatrix[VX][VX] * b.mV[VX] + + a.mMatrix[VX][VY] * b.mV[VY] + + a.mMatrix[VX][VZ] * b.mV[VZ]; + + vec.mV[VY] = a.mMatrix[VY][VX] * b.mV[VX] + + a.mMatrix[VY][VY] * b.mV[VY] + + a.mMatrix[VY][VZ] * b.mV[VZ]; + + vec.mV[VZ] = a.mMatrix[VZ][VX] * b.mV[VX] + + a.mMatrix[VZ][VY] * b.mV[VY] + + a.mMatrix[VZ][VZ] * b.mV[VZ]; + return vec; } */ LLVector3 operator*(const LLVector3 &a, const LLMatrix3 &b) { - // matrix operates "from the right" on row vector - return LLVector3( - a.mV[VX] * b.mMatrix[VX][VX] + - a.mV[VY] * b.mMatrix[VY][VX] + - a.mV[VZ] * b.mMatrix[VZ][VX], - - a.mV[VX] * b.mMatrix[VX][VY] + - a.mV[VY] * b.mMatrix[VY][VY] + - a.mV[VZ] * b.mMatrix[VZ][VY], - - a.mV[VX] * b.mMatrix[VX][VZ] + - a.mV[VY] * b.mMatrix[VY][VZ] + - a.mV[VZ] * b.mMatrix[VZ][VZ] ); + // matrix operates "from the right" on row vector + return LLVector3( + a.mV[VX] * b.mMatrix[VX][VX] + + a.mV[VY] * b.mMatrix[VY][VX] + + a.mV[VZ] * b.mMatrix[VZ][VX], + + a.mV[VX] * b.mMatrix[VX][VY] + + a.mV[VY] * b.mMatrix[VY][VY] + + a.mV[VZ] * b.mMatrix[VZ][VY], + + a.mV[VX] * b.mMatrix[VX][VZ] + + a.mV[VY] * b.mMatrix[VY][VZ] + + a.mV[VZ] * b.mMatrix[VZ][VZ] ); } LLVector3d operator*(const LLVector3d &a, const LLMatrix3 &b) { - // matrix operates "from the right" on row vector - return LLVector3d( - a.mdV[VX] * b.mMatrix[VX][VX] + - a.mdV[VY] * b.mMatrix[VY][VX] + - a.mdV[VZ] * b.mMatrix[VZ][VX], - - a.mdV[VX] * b.mMatrix[VX][VY] + - a.mdV[VY] * b.mMatrix[VY][VY] + - a.mdV[VZ] * b.mMatrix[VZ][VY], - - a.mdV[VX] * b.mMatrix[VX][VZ] + - a.mdV[VY] * b.mMatrix[VY][VZ] + - a.mdV[VZ] * b.mMatrix[VZ][VZ] ); + // matrix operates "from the right" on row vector + return LLVector3d( + a.mdV[VX] * b.mMatrix[VX][VX] + + a.mdV[VY] * b.mMatrix[VY][VX] + + a.mdV[VZ] * b.mMatrix[VZ][VX], + + a.mdV[VX] * b.mMatrix[VX][VY] + + a.mdV[VY] * b.mMatrix[VY][VY] + + a.mdV[VZ] * b.mMatrix[VZ][VY], + + a.mdV[VX] * b.mMatrix[VX][VZ] + + a.mdV[VY] * b.mMatrix[VY][VZ] + + a.mdV[VZ] * b.mMatrix[VZ][VZ] ); } bool operator==(const LLMatrix3 &a, const LLMatrix3 &b) { - U32 i, j; - for (i = 0; i < NUM_VALUES_IN_MAT3; i++) - { - for (j = 0; j < NUM_VALUES_IN_MAT3; j++) - { - if (a.mMatrix[j][i] != b.mMatrix[j][i]) - return false; - } - } - return true; + U32 i, j; + for (i = 0; i < NUM_VALUES_IN_MAT3; i++) + { + for (j = 0; j < NUM_VALUES_IN_MAT3; j++) + { + if (a.mMatrix[j][i] != b.mMatrix[j][i]) + return false; + } + } + return true; } bool operator!=(const LLMatrix3 &a, const LLMatrix3 &b) { - U32 i, j; - for (i = 0; i < NUM_VALUES_IN_MAT3; i++) - { - for (j = 0; j < NUM_VALUES_IN_MAT3; j++) - { - if (a.mMatrix[j][i] != b.mMatrix[j][i]) - return true; - } - } - return false; + U32 i, j; + for (i = 0; i < NUM_VALUES_IN_MAT3; i++) + { + for (j = 0; j < NUM_VALUES_IN_MAT3; j++) + { + if (a.mMatrix[j][i] != b.mMatrix[j][i]) + return true; + } + } + return false; } const LLMatrix3& operator*=(LLMatrix3 &a, const LLMatrix3 &b) { - U32 i, j; - LLMatrix3 mat; - for (i = 0; i < NUM_VALUES_IN_MAT3; i++) - { - for (j = 0; j < NUM_VALUES_IN_MAT3; j++) - { - mat.mMatrix[j][i] = a.mMatrix[j][0] * b.mMatrix[0][i] + - a.mMatrix[j][1] * b.mMatrix[1][i] + - a.mMatrix[j][2] * b.mMatrix[2][i]; - } - } - a = mat; - return a; + U32 i, j; + LLMatrix3 mat; + for (i = 0; i < NUM_VALUES_IN_MAT3; i++) + { + for (j = 0; j < NUM_VALUES_IN_MAT3; j++) + { + mat.mMatrix[j][i] = a.mMatrix[j][0] * b.mMatrix[0][i] + + a.mMatrix[j][1] * b.mMatrix[1][i] + + a.mMatrix[j][2] * b.mMatrix[2][i]; + } + } + a = mat; + return a; } const LLMatrix3& operator*=(LLMatrix3 &a, F32 scalar ) { - for( U32 i = 0; i < NUM_VALUES_IN_MAT3; ++i ) - { - for( U32 j = 0; j < NUM_VALUES_IN_MAT3; ++j ) - { - a.mMatrix[i][j] *= scalar; - } - } + for( U32 i = 0; i < NUM_VALUES_IN_MAT3; ++i ) + { + for( U32 j = 0; j < NUM_VALUES_IN_MAT3; ++j ) + { + a.mMatrix[i][j] *= scalar; + } + } - return a; + return a; } -std::ostream& operator<<(std::ostream& s, const LLMatrix3 &a) +std::ostream& operator<<(std::ostream& s, const LLMatrix3 &a) { - s << "{ " - << a.mMatrix[VX][VX] << ", " << a.mMatrix[VX][VY] << ", " << a.mMatrix[VX][VZ] << "; " - << a.mMatrix[VY][VX] << ", " << a.mMatrix[VY][VY] << ", " << a.mMatrix[VY][VZ] << "; " - << a.mMatrix[VZ][VX] << ", " << a.mMatrix[VZ][VY] << ", " << a.mMatrix[VZ][VZ] - << " }"; - return s; + s << "{ " + << a.mMatrix[VX][VX] << ", " << a.mMatrix[VX][VY] << ", " << a.mMatrix[VX][VZ] << "; " + << a.mMatrix[VY][VX] << ", " << a.mMatrix[VY][VY] << ", " << a.mMatrix[VY][VZ] << "; " + << a.mMatrix[VZ][VX] << ", " << a.mMatrix[VZ][VY] << ", " << a.mMatrix[VZ][VZ] + << " }"; + return s; } diff --git a/indra/llmath/m3math.h b/indra/llmath/m3math.h index bf38895855..cd14290246 100644 --- a/indra/llmath/m3math.h +++ b/indra/llmath/m3math.h @@ -1,25 +1,25 @@ -/** +/** * @file m3math.h * @brief LLMatrix3 class header file. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -37,139 +37,139 @@ class LLQuaternion; // NOTA BENE: Currently assuming a right-handed, z-up universe -// ji +// ji // LLMatrix3 = | 00 01 02 | -// | 10 11 12 | -// | 20 21 22 | +// | 10 11 12 | +// | 20 21 22 | -// LLMatrix3 = | fx fy fz | forward-axis -// | lx ly lz | left-axis -// | ux uy uz | up-axis +// LLMatrix3 = | fx fy fz | forward-axis +// | lx ly lz | left-axis +// | ux uy uz | up-axis -// NOTE: The world of computer graphics uses column-vectors and matricies that -// "operate to the left". +// NOTE: The world of computer graphics uses column-vectors and matricies that +// "operate to the left". -static const U32 NUM_VALUES_IN_MAT3 = 3; +static const U32 NUM_VALUES_IN_MAT3 = 3; class LLMatrix3 { - public: - F32 mMatrix[NUM_VALUES_IN_MAT3][NUM_VALUES_IN_MAT3]; - - LLMatrix3(void); // Initializes Matrix to identity matrix - explicit LLMatrix3(const F32 *mat); // Initializes Matrix to values in mat - explicit LLMatrix3(const LLQuaternion &q); // Initializes Matrix with rotation q - - LLMatrix3(const F32 angle, const LLVector3 &vec); // Initializes Matrix with axis angle - LLMatrix3(const F32 angle, const LLVector3d &vec); // Initializes Matrix with axis angle - LLMatrix3(const F32 angle, const LLVector4 &vec); // Initializes Matrix with axis angle - LLMatrix3(const F32 roll, const F32 pitch, const F32 yaw); // Initializes Matrix with Euler angles - - ////////////////////////////// - // - // Matrix initializers - these replace any existing values in the matrix - // - - // various useful matrix functions - const LLMatrix3& setIdentity(); // Load identity matrix - const LLMatrix3& clear(); // Clears Matrix to zero - const LLMatrix3& setZero(); // Clears Matrix to zero - - /////////////////////////// - // - // Matrix setters - set some properties without modifying others - // - - // These functions take Rotation arguments - const LLMatrix3& setRot(const F32 angle, const LLVector3 &vec); // Calculate rotation matrix for rotating angle radians about vec - const LLMatrix3& setRot(const F32 roll, const F32 pitch, const F32 yaw); // Calculate rotation matrix from Euler angles - const LLMatrix3& setRot(const LLQuaternion &q); // Transform matrix by Euler angles and translating by pos - - const LLMatrix3& setRows(const LLVector3 &x_axis, const LLVector3 &y_axis, const LLVector3 &z_axis); - const LLMatrix3& setRow( U32 rowIndex, const LLVector3& row ); - const LLMatrix3& setCol( U32 colIndex, const LLVector3& col ); - - - /////////////////////////// - // - // Get properties of a matrix - // - LLQuaternion quaternion() const; // Returns quaternion from mat - void getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const; // Returns Euler angles, in radians - - // Axis extraction routines - LLVector3 getFwdRow() const; - LLVector3 getLeftRow() const; - LLVector3 getUpRow() const; - F32 determinant() const; // Return determinant - - - /////////////////////////// - // - // Operations on an existing matrix - // - const LLMatrix3& transpose(); // Transpose MAT4 - const LLMatrix3& orthogonalize(); // Orthogonalizes X, then Y, then Z - void invert(); // Invert MAT4 - const LLMatrix3& adjointTranspose();// returns transpose of matrix adjoint, for multiplying normals - - - // Rotate existing matrix - // Note: the two lines below are equivalent: - // foo.rotate(bar) - // foo = foo * bar - // That is, foo.rotate(bar) multiplies foo by bar FROM THE RIGHT - const LLMatrix3& rotate(const F32 angle, const F32 x, const F32 y, const F32 z); // Rotate matrix by rotating angle radians about (x, y, z) - const LLMatrix3& rotate(const F32 angle, const LLVector3 &vec); // Rotate matrix by rotating angle radians about vec - const LLMatrix3& rotate(const F32 roll, const F32 pitch, const F32 yaw); // Rotate matrix by roll (about x), pitch (about y), and yaw (about z) - const LLMatrix3& rotate(const LLQuaternion &q); // Transform matrix by Euler angles and translating by pos - - void add(const LLMatrix3& other_matrix); // add other_matrix to this one + public: + F32 mMatrix[NUM_VALUES_IN_MAT3][NUM_VALUES_IN_MAT3]; + + LLMatrix3(void); // Initializes Matrix to identity matrix + explicit LLMatrix3(const F32 *mat); // Initializes Matrix to values in mat + explicit LLMatrix3(const LLQuaternion &q); // Initializes Matrix with rotation q + + LLMatrix3(const F32 angle, const LLVector3 &vec); // Initializes Matrix with axis angle + LLMatrix3(const F32 angle, const LLVector3d &vec); // Initializes Matrix with axis angle + LLMatrix3(const F32 angle, const LLVector4 &vec); // Initializes Matrix with axis angle + LLMatrix3(const F32 roll, const F32 pitch, const F32 yaw); // Initializes Matrix with Euler angles + + ////////////////////////////// + // + // Matrix initializers - these replace any existing values in the matrix + // + + // various useful matrix functions + const LLMatrix3& setIdentity(); // Load identity matrix + const LLMatrix3& clear(); // Clears Matrix to zero + const LLMatrix3& setZero(); // Clears Matrix to zero + + /////////////////////////// + // + // Matrix setters - set some properties without modifying others + // + + // These functions take Rotation arguments + const LLMatrix3& setRot(const F32 angle, const LLVector3 &vec); // Calculate rotation matrix for rotating angle radians about vec + const LLMatrix3& setRot(const F32 roll, const F32 pitch, const F32 yaw); // Calculate rotation matrix from Euler angles + const LLMatrix3& setRot(const LLQuaternion &q); // Transform matrix by Euler angles and translating by pos + + const LLMatrix3& setRows(const LLVector3 &x_axis, const LLVector3 &y_axis, const LLVector3 &z_axis); + const LLMatrix3& setRow( U32 rowIndex, const LLVector3& row ); + const LLMatrix3& setCol( U32 colIndex, const LLVector3& col ); + + + /////////////////////////// + // + // Get properties of a matrix + // + LLQuaternion quaternion() const; // Returns quaternion from mat + void getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const; // Returns Euler angles, in radians + + // Axis extraction routines + LLVector3 getFwdRow() const; + LLVector3 getLeftRow() const; + LLVector3 getUpRow() const; + F32 determinant() const; // Return determinant + + + /////////////////////////// + // + // Operations on an existing matrix + // + const LLMatrix3& transpose(); // Transpose MAT4 + const LLMatrix3& orthogonalize(); // Orthogonalizes X, then Y, then Z + void invert(); // Invert MAT4 + const LLMatrix3& adjointTranspose();// returns transpose of matrix adjoint, for multiplying normals + + + // Rotate existing matrix + // Note: the two lines below are equivalent: + // foo.rotate(bar) + // foo = foo * bar + // That is, foo.rotate(bar) multiplies foo by bar FROM THE RIGHT + const LLMatrix3& rotate(const F32 angle, const F32 x, const F32 y, const F32 z); // Rotate matrix by rotating angle radians about (x, y, z) + const LLMatrix3& rotate(const F32 angle, const LLVector3 &vec); // Rotate matrix by rotating angle radians about vec + const LLMatrix3& rotate(const F32 roll, const F32 pitch, const F32 yaw); // Rotate matrix by roll (about x), pitch (about y), and yaw (about z) + const LLMatrix3& rotate(const LLQuaternion &q); // Transform matrix by Euler angles and translating by pos + + void add(const LLMatrix3& other_matrix); // add other_matrix to this one // This operator is misleading as to operation direction -// friend LLVector3 operator*(const LLMatrix3 &a, const LLVector3 &b); // Apply rotation a to vector b +// friend LLVector3 operator*(const LLMatrix3 &a, const LLVector3 &b); // Apply rotation a to vector b - friend LLVector3 operator*(const LLVector3 &a, const LLMatrix3 &b); // Apply rotation b to vector a - friend LLVector3d operator*(const LLVector3d &a, const LLMatrix3 &b); // Apply rotation b to vector a - friend LLMatrix3 operator*(const LLMatrix3 &a, const LLMatrix3 &b); // Return a * b + friend LLVector3 operator*(const LLVector3 &a, const LLMatrix3 &b); // Apply rotation b to vector a + friend LLVector3d operator*(const LLVector3d &a, const LLMatrix3 &b); // Apply rotation b to vector a + friend LLMatrix3 operator*(const LLMatrix3 &a, const LLMatrix3 &b); // Return a * b - friend bool operator==(const LLMatrix3 &a, const LLMatrix3 &b); // Return a == b - friend bool operator!=(const LLMatrix3 &a, const LLMatrix3 &b); // Return a != b + friend bool operator==(const LLMatrix3 &a, const LLMatrix3 &b); // Return a == b + friend bool operator!=(const LLMatrix3 &a, const LLMatrix3 &b); // Return a != b - friend const LLMatrix3& operator*=(LLMatrix3 &a, const LLMatrix3 &b); // Return a * b - friend const LLMatrix3& operator*=(LLMatrix3 &a, F32 scalar ); // Return a * scalar + friend const LLMatrix3& operator*=(LLMatrix3 &a, const LLMatrix3 &b); // Return a * b + friend const LLMatrix3& operator*=(LLMatrix3 &a, F32 scalar ); // Return a * scalar - friend std::ostream& operator<<(std::ostream& s, const LLMatrix3 &a); // Stream a + friend std::ostream& operator<<(std::ostream& s, const LLMatrix3 &a); // Stream a }; inline LLMatrix3::LLMatrix3(void) { - mMatrix[0][0] = 1.f; - mMatrix[0][1] = 0.f; - mMatrix[0][2] = 0.f; + mMatrix[0][0] = 1.f; + mMatrix[0][1] = 0.f; + mMatrix[0][2] = 0.f; - mMatrix[1][0] = 0.f; - mMatrix[1][1] = 1.f; - mMatrix[1][2] = 0.f; + mMatrix[1][0] = 0.f; + mMatrix[1][1] = 1.f; + mMatrix[1][2] = 0.f; - mMatrix[2][0] = 0.f; - mMatrix[2][1] = 0.f; - mMatrix[2][2] = 1.f; + mMatrix[2][0] = 0.f; + mMatrix[2][1] = 0.f; + mMatrix[2][2] = 1.f; } inline LLMatrix3::LLMatrix3(const F32 *mat) { - mMatrix[0][0] = mat[0]; - mMatrix[0][1] = mat[1]; - mMatrix[0][2] = mat[2]; + mMatrix[0][0] = mat[0]; + mMatrix[0][1] = mat[1]; + mMatrix[0][2] = mat[2]; - mMatrix[1][0] = mat[3]; - mMatrix[1][1] = mat[4]; - mMatrix[1][2] = mat[5]; + mMatrix[1][0] = mat[3]; + mMatrix[1][1] = mat[4]; + mMatrix[1][2] = mat[5]; - mMatrix[2][0] = mat[6]; - mMatrix[2][1] = mat[7]; - mMatrix[2][2] = mat[8]; + mMatrix[2][0] = mat[6]; + mMatrix[2][1] = mat[7]; + mMatrix[2][2] = mat[8]; } @@ -187,7 +187,7 @@ inline LLMatrix3::LLMatrix3(const F32 *mat) // Creating Rotation Matricies From Object Axes // -------------------------------------------- // Suppose you know the three axes of some object in some "absolute-frame". -// If you take those three vectors and throw them into the rows of +// If you take those three vectors and throw them into the rows of // a rotation matrix what do you get? // // R = | X0 X1 X2 | @@ -198,11 +198,11 @@ inline LLMatrix3::LLMatrix3(const F32 *mat) // // Transpose the matrix and have it operate on a vector... // -// V * R_transpose = [ V0 V1 V2 ] * | X0 Y0 Z0 | -// | X1 Y1 Z1 | +// V * R_transpose = [ V0 V1 V2 ] * | X0 Y0 Z0 | +// | X1 Y1 Z1 | // | X2 Y2 Z2 | -// -// = [ V*X V*Y V*Z ] +// +// = [ V*X V*Y V*Z ] // // = components of V that are parallel to the three object axes // diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp index ee4f607442..c46ee587cb 100644 --- a/indra/llmath/m4math.cpp +++ b/indra/llmath/m4math.cpp @@ -1,25 +1,25 @@ -/** +/** * @file m4math.cpp * @brief LLMatrix4 class implementation. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -42,119 +42,119 @@ LLMatrix4::LLMatrix4(const F32 *mat) { - mMatrix[0][0] = mat[0]; - mMatrix[0][1] = mat[1]; - mMatrix[0][2] = mat[2]; - mMatrix[0][3] = mat[3]; + mMatrix[0][0] = mat[0]; + mMatrix[0][1] = mat[1]; + mMatrix[0][2] = mat[2]; + mMatrix[0][3] = mat[3]; - mMatrix[1][0] = mat[4]; - mMatrix[1][1] = mat[5]; - mMatrix[1][2] = mat[6]; - mMatrix[1][3] = mat[7]; + mMatrix[1][0] = mat[4]; + mMatrix[1][1] = mat[5]; + mMatrix[1][2] = mat[6]; + mMatrix[1][3] = mat[7]; - mMatrix[2][0] = mat[8]; - mMatrix[2][1] = mat[9]; - mMatrix[2][2] = mat[10]; - mMatrix[2][3] = mat[11]; + mMatrix[2][0] = mat[8]; + mMatrix[2][1] = mat[9]; + mMatrix[2][2] = mat[10]; + mMatrix[2][3] = mat[11]; - mMatrix[3][0] = mat[12]; - mMatrix[3][1] = mat[13]; - mMatrix[3][2] = mat[14]; - mMatrix[3][3] = mat[15]; + mMatrix[3][0] = mat[12]; + mMatrix[3][1] = mat[13]; + mMatrix[3][2] = mat[14]; + mMatrix[3][3] = mat[15]; } LLMatrix4::LLMatrix4(const LLMatrix3 &mat, const LLVector4 &vec) { - mMatrix[0][0] = mat.mMatrix[0][0]; - mMatrix[0][1] = mat.mMatrix[0][1]; - mMatrix[0][2] = mat.mMatrix[0][2]; - mMatrix[0][3] = 0.f; + mMatrix[0][0] = mat.mMatrix[0][0]; + mMatrix[0][1] = mat.mMatrix[0][1]; + mMatrix[0][2] = mat.mMatrix[0][2]; + mMatrix[0][3] = 0.f; - mMatrix[1][0] = mat.mMatrix[1][0]; - mMatrix[1][1] = mat.mMatrix[1][1]; - mMatrix[1][2] = mat.mMatrix[1][2]; - mMatrix[1][3] = 0.f; + mMatrix[1][0] = mat.mMatrix[1][0]; + mMatrix[1][1] = mat.mMatrix[1][1]; + mMatrix[1][2] = mat.mMatrix[1][2]; + mMatrix[1][3] = 0.f; - mMatrix[2][0] = mat.mMatrix[2][0]; - mMatrix[2][1] = mat.mMatrix[2][1]; - mMatrix[2][2] = mat.mMatrix[2][2]; - mMatrix[2][3] = 0.f; + mMatrix[2][0] = mat.mMatrix[2][0]; + mMatrix[2][1] = mat.mMatrix[2][1]; + mMatrix[2][2] = mat.mMatrix[2][2]; + mMatrix[2][3] = 0.f; - mMatrix[3][0] = vec.mV[0]; - mMatrix[3][1] = vec.mV[1]; - mMatrix[3][2] = vec.mV[2]; - mMatrix[3][3] = 1.f; + mMatrix[3][0] = vec.mV[0]; + mMatrix[3][1] = vec.mV[1]; + mMatrix[3][2] = vec.mV[2]; + mMatrix[3][3] = 1.f; } LLMatrix4::LLMatrix4(const LLMatrix3 &mat) { - mMatrix[0][0] = mat.mMatrix[0][0]; - mMatrix[0][1] = mat.mMatrix[0][1]; - mMatrix[0][2] = mat.mMatrix[0][2]; - mMatrix[0][3] = 0.f; + mMatrix[0][0] = mat.mMatrix[0][0]; + mMatrix[0][1] = mat.mMatrix[0][1]; + mMatrix[0][2] = mat.mMatrix[0][2]; + mMatrix[0][3] = 0.f; - mMatrix[1][0] = mat.mMatrix[1][0]; - mMatrix[1][1] = mat.mMatrix[1][1]; - mMatrix[1][2] = mat.mMatrix[1][2]; - mMatrix[1][3] = 0.f; + mMatrix[1][0] = mat.mMatrix[1][0]; + mMatrix[1][1] = mat.mMatrix[1][1]; + mMatrix[1][2] = mat.mMatrix[1][2]; + mMatrix[1][3] = 0.f; - mMatrix[2][0] = mat.mMatrix[2][0]; - mMatrix[2][1] = mat.mMatrix[2][1]; - mMatrix[2][2] = mat.mMatrix[2][2]; - mMatrix[2][3] = 0.f; + mMatrix[2][0] = mat.mMatrix[2][0]; + mMatrix[2][1] = mat.mMatrix[2][1]; + mMatrix[2][2] = mat.mMatrix[2][2]; + mMatrix[2][3] = 0.f; - mMatrix[3][0] = 0.f; - mMatrix[3][1] = 0.f; - mMatrix[3][2] = 0.f; - mMatrix[3][3] = 1.f; + mMatrix[3][0] = 0.f; + mMatrix[3][1] = 0.f; + mMatrix[3][2] = 0.f; + mMatrix[3][3] = 1.f; } LLMatrix4::LLMatrix4(const LLQuaternion &q) { - *this = initRotation(q); + *this = initRotation(q); } LLMatrix4::LLMatrix4(const LLMatrix4a& mat) : LLMatrix4(mat.getF32ptr()) { - + } LLMatrix4::LLMatrix4(const LLQuaternion &q, const LLVector4 &pos) { - *this = initRotTrans(q, pos); + *this = initRotTrans(q, pos); } LLMatrix4::LLMatrix4(const F32 angle, const LLVector4 &vec, const LLVector4 &pos) { - initRotTrans(LLQuaternion(angle, vec), pos); + initRotTrans(LLQuaternion(angle, vec), pos); } LLMatrix4::LLMatrix4(const F32 angle, const LLVector4 &vec) { - initRotation(LLQuaternion(angle, vec)); + initRotation(LLQuaternion(angle, vec)); - mMatrix[3][0] = 0.f; - mMatrix[3][1] = 0.f; - mMatrix[3][2] = 0.f; - mMatrix[3][3] = 1.f; + mMatrix[3][0] = 0.f; + mMatrix[3][1] = 0.f; + mMatrix[3][2] = 0.f; + mMatrix[3][3] = 1.f; } LLMatrix4::LLMatrix4(const F32 roll, const F32 pitch, const F32 yaw, const LLVector4 &pos) { - LLMatrix3 mat(roll, pitch, yaw); - initRotTrans(LLQuaternion(mat), pos); + LLMatrix3 mat(roll, pitch, yaw); + initRotTrans(LLQuaternion(mat), pos); } LLMatrix4::LLMatrix4(const F32 roll, const F32 pitch, const F32 yaw) { - LLMatrix3 mat(roll, pitch, yaw); - initRotation(LLQuaternion(mat)); + LLMatrix3 mat(roll, pitch, yaw); + initRotation(LLQuaternion(mat)); - mMatrix[3][0] = 0.f; - mMatrix[3][1] = 0.f; - mMatrix[3][2] = 0.f; - mMatrix[3][3] = 1.f; + mMatrix[3][0] = 0.f; + mMatrix[3][1] = 0.f; + mMatrix[3][2] = 0.f; + mMatrix[3][3] = 1.f; } LLMatrix4::~LLMatrix4(void) @@ -165,118 +165,118 @@ LLMatrix4::~LLMatrix4(void) const LLMatrix4& LLMatrix4::setZero() { - mMatrix[0][0] = 0.f; - mMatrix[0][1] = 0.f; - mMatrix[0][2] = 0.f; - mMatrix[0][3] = 0.f; + mMatrix[0][0] = 0.f; + mMatrix[0][1] = 0.f; + mMatrix[0][2] = 0.f; + mMatrix[0][3] = 0.f; - mMatrix[1][0] = 0.f; - mMatrix[1][1] = 0.f; - mMatrix[1][2] = 0.f; - mMatrix[1][3] = 0.f; + mMatrix[1][0] = 0.f; + mMatrix[1][1] = 0.f; + mMatrix[1][2] = 0.f; + mMatrix[1][3] = 0.f; - mMatrix[2][0] = 0.f; - mMatrix[2][1] = 0.f; - mMatrix[2][2] = 0.f; - mMatrix[2][3] = 0.f; + mMatrix[2][0] = 0.f; + mMatrix[2][1] = 0.f; + mMatrix[2][2] = 0.f; + mMatrix[2][3] = 0.f; - mMatrix[3][0] = 0.f; - mMatrix[3][1] = 0.f; - mMatrix[3][2] = 0.f; - mMatrix[3][3] = 0.f; - return *this; + mMatrix[3][0] = 0.f; + mMatrix[3][1] = 0.f; + mMatrix[3][2] = 0.f; + mMatrix[3][3] = 0.f; + return *this; } // various useful mMatrix functions -const LLMatrix4& LLMatrix4::transpose() +const LLMatrix4& LLMatrix4::transpose() { - LLMatrix4 mat; - mat.mMatrix[0][0] = mMatrix[0][0]; - mat.mMatrix[1][0] = mMatrix[0][1]; - mat.mMatrix[2][0] = mMatrix[0][2]; - mat.mMatrix[3][0] = mMatrix[0][3]; + LLMatrix4 mat; + mat.mMatrix[0][0] = mMatrix[0][0]; + mat.mMatrix[1][0] = mMatrix[0][1]; + mat.mMatrix[2][0] = mMatrix[0][2]; + mat.mMatrix[3][0] = mMatrix[0][3]; - mat.mMatrix[0][1] = mMatrix[1][0]; - mat.mMatrix[1][1] = mMatrix[1][1]; - mat.mMatrix[2][1] = mMatrix[1][2]; - mat.mMatrix[3][1] = mMatrix[1][3]; + mat.mMatrix[0][1] = mMatrix[1][0]; + mat.mMatrix[1][1] = mMatrix[1][1]; + mat.mMatrix[2][1] = mMatrix[1][2]; + mat.mMatrix[3][1] = mMatrix[1][3]; - mat.mMatrix[0][2] = mMatrix[2][0]; - mat.mMatrix[1][2] = mMatrix[2][1]; - mat.mMatrix[2][2] = mMatrix[2][2]; - mat.mMatrix[3][2] = mMatrix[2][3]; + mat.mMatrix[0][2] = mMatrix[2][0]; + mat.mMatrix[1][2] = mMatrix[2][1]; + mat.mMatrix[2][2] = mMatrix[2][2]; + mat.mMatrix[3][2] = mMatrix[2][3]; - mat.mMatrix[0][3] = mMatrix[3][0]; - mat.mMatrix[1][3] = mMatrix[3][1]; - mat.mMatrix[2][3] = mMatrix[3][2]; - mat.mMatrix[3][3] = mMatrix[3][3]; + mat.mMatrix[0][3] = mMatrix[3][0]; + mat.mMatrix[1][3] = mMatrix[3][1]; + mat.mMatrix[2][3] = mMatrix[3][2]; + mat.mMatrix[3][3] = mMatrix[3][3]; - *this = mat; - return *this; + *this = mat; + return *this; } F32 LLMatrix4::determinant() const { - F32 value = - mMatrix[0][3] * mMatrix[1][2] * mMatrix[2][1] * mMatrix[3][0] - - mMatrix[0][2] * mMatrix[1][3] * mMatrix[2][1] * mMatrix[3][0] - - mMatrix[0][3] * mMatrix[1][1] * mMatrix[2][2] * mMatrix[3][0] + - mMatrix[0][1] * mMatrix[1][3] * mMatrix[2][2] * mMatrix[3][0] + - mMatrix[0][2] * mMatrix[1][1] * mMatrix[2][3] * mMatrix[3][0] - - mMatrix[0][1] * mMatrix[1][2] * mMatrix[2][3] * mMatrix[3][0] - - mMatrix[0][3] * mMatrix[1][2] * mMatrix[2][0] * mMatrix[3][1] + - mMatrix[0][2] * mMatrix[1][3] * mMatrix[2][0] * mMatrix[3][1] + - mMatrix[0][3] * mMatrix[1][0] * mMatrix[2][2] * mMatrix[3][1] - - mMatrix[0][0] * mMatrix[1][3] * mMatrix[2][2] * mMatrix[3][1] - - mMatrix[0][2] * mMatrix[1][0] * mMatrix[2][3] * mMatrix[3][1] + - mMatrix[0][0] * mMatrix[1][2] * mMatrix[2][3] * mMatrix[3][1] + - mMatrix[0][3] * mMatrix[1][1] * mMatrix[2][0] * mMatrix[3][2] - - mMatrix[0][1] * mMatrix[1][3] * mMatrix[2][0] * mMatrix[3][2] - - mMatrix[0][3] * mMatrix[1][0] * mMatrix[2][1] * mMatrix[3][2] + - mMatrix[0][0] * mMatrix[1][3] * mMatrix[2][1] * mMatrix[3][2] + - mMatrix[0][1] * mMatrix[1][0] * mMatrix[2][3] * mMatrix[3][2] - - mMatrix[0][0] * mMatrix[1][1] * mMatrix[2][3] * mMatrix[3][2] - - mMatrix[0][2] * mMatrix[1][1] * mMatrix[2][0] * mMatrix[3][3] + - mMatrix[0][1] * mMatrix[1][2] * mMatrix[2][0] * mMatrix[3][3] + - mMatrix[0][2] * mMatrix[1][0] * mMatrix[2][1] * mMatrix[3][3] - - mMatrix[0][0] * mMatrix[1][2] * mMatrix[2][1] * mMatrix[3][3] - - mMatrix[0][1] * mMatrix[1][0] * mMatrix[2][2] * mMatrix[3][3] + - mMatrix[0][0] * mMatrix[1][1] * mMatrix[2][2] * mMatrix[3][3]; - - return value; + F32 value = + mMatrix[0][3] * mMatrix[1][2] * mMatrix[2][1] * mMatrix[3][0] - + mMatrix[0][2] * mMatrix[1][3] * mMatrix[2][1] * mMatrix[3][0] - + mMatrix[0][3] * mMatrix[1][1] * mMatrix[2][2] * mMatrix[3][0] + + mMatrix[0][1] * mMatrix[1][3] * mMatrix[2][2] * mMatrix[3][0] + + mMatrix[0][2] * mMatrix[1][1] * mMatrix[2][3] * mMatrix[3][0] - + mMatrix[0][1] * mMatrix[1][2] * mMatrix[2][3] * mMatrix[3][0] - + mMatrix[0][3] * mMatrix[1][2] * mMatrix[2][0] * mMatrix[3][1] + + mMatrix[0][2] * mMatrix[1][3] * mMatrix[2][0] * mMatrix[3][1] + + mMatrix[0][3] * mMatrix[1][0] * mMatrix[2][2] * mMatrix[3][1] - + mMatrix[0][0] * mMatrix[1][3] * mMatrix[2][2] * mMatrix[3][1] - + mMatrix[0][2] * mMatrix[1][0] * mMatrix[2][3] * mMatrix[3][1] + + mMatrix[0][0] * mMatrix[1][2] * mMatrix[2][3] * mMatrix[3][1] + + mMatrix[0][3] * mMatrix[1][1] * mMatrix[2][0] * mMatrix[3][2] - + mMatrix[0][1] * mMatrix[1][3] * mMatrix[2][0] * mMatrix[3][2] - + mMatrix[0][3] * mMatrix[1][0] * mMatrix[2][1] * mMatrix[3][2] + + mMatrix[0][0] * mMatrix[1][3] * mMatrix[2][1] * mMatrix[3][2] + + mMatrix[0][1] * mMatrix[1][0] * mMatrix[2][3] * mMatrix[3][2] - + mMatrix[0][0] * mMatrix[1][1] * mMatrix[2][3] * mMatrix[3][2] - + mMatrix[0][2] * mMatrix[1][1] * mMatrix[2][0] * mMatrix[3][3] + + mMatrix[0][1] * mMatrix[1][2] * mMatrix[2][0] * mMatrix[3][3] + + mMatrix[0][2] * mMatrix[1][0] * mMatrix[2][1] * mMatrix[3][3] - + mMatrix[0][0] * mMatrix[1][2] * mMatrix[2][1] * mMatrix[3][3] - + mMatrix[0][1] * mMatrix[1][0] * mMatrix[2][2] * mMatrix[3][3] + + mMatrix[0][0] * mMatrix[1][1] * mMatrix[2][2] * mMatrix[3][3]; + + return value; } // Only works for pure orthonormal, homogeneous transform matrices. -const LLMatrix4& LLMatrix4::invert(void) -{ - // transpose the rotation part - F32 temp; - temp = mMatrix[VX][VY]; mMatrix[VX][VY] = mMatrix[VY][VX]; mMatrix[VY][VX] = temp; - temp = mMatrix[VX][VZ]; mMatrix[VX][VZ] = mMatrix[VZ][VX]; mMatrix[VZ][VX] = temp; - temp = mMatrix[VY][VZ]; mMatrix[VY][VZ] = mMatrix[VZ][VY]; mMatrix[VZ][VY] = temp; - - // rotate the translation part by the new rotation - // (temporarily store in empty column of matrix) - U32 j; - for (j=0; j<3; j++) - { - mMatrix[j][VW] = mMatrix[VW][VX] * mMatrix[VX][j] + - mMatrix[VW][VY] * mMatrix[VY][j] + - mMatrix[VW][VZ] * mMatrix[VZ][j]; - } - - // negate and copy the temporary vector back to the tranlation row - mMatrix[VW][VX] = -mMatrix[VX][VW]; - mMatrix[VW][VY] = -mMatrix[VY][VW]; - mMatrix[VW][VZ] = -mMatrix[VZ][VW]; - - // zero the empty column again - mMatrix[VX][VW] = mMatrix[VY][VW] = mMatrix[VZ][VW] = 0.0f; - - return *this; +const LLMatrix4& LLMatrix4::invert(void) +{ + // transpose the rotation part + F32 temp; + temp = mMatrix[VX][VY]; mMatrix[VX][VY] = mMatrix[VY][VX]; mMatrix[VY][VX] = temp; + temp = mMatrix[VX][VZ]; mMatrix[VX][VZ] = mMatrix[VZ][VX]; mMatrix[VZ][VX] = temp; + temp = mMatrix[VY][VZ]; mMatrix[VY][VZ] = mMatrix[VZ][VY]; mMatrix[VZ][VY] = temp; + + // rotate the translation part by the new rotation + // (temporarily store in empty column of matrix) + U32 j; + for (j=0; j<3; j++) + { + mMatrix[j][VW] = mMatrix[VW][VX] * mMatrix[VX][j] + + mMatrix[VW][VY] * mMatrix[VY][j] + + mMatrix[VW][VZ] * mMatrix[VZ][j]; + } + + // negate and copy the temporary vector back to the tranlation row + mMatrix[VW][VX] = -mMatrix[VX][VW]; + mMatrix[VW][VY] = -mMatrix[VY][VW]; + mMatrix[VW][VZ] = -mMatrix[VZ][VW]; + + // zero the empty column again + mMatrix[VX][VW] = mMatrix[VY][VW] = mMatrix[VZ][VW] = 0.0f; + + return *this; } // Convenience func for simplifying comparison-heavy code by @@ -284,188 +284,188 @@ const LLMatrix4& LLMatrix4::invert(void) // void LLMatrix4::condition(void) { - U32 i; - U32 j; - for (i = 0; i < 3;i++) - for (j = 0; j < 3;j++) - mMatrix[i][j] = ((mMatrix[i][j] > -FLT_EPSILON) - && (mMatrix[i][j] < FLT_EPSILON)) ? 0.0f : mMatrix[i][j]; + U32 i; + U32 j; + for (i = 0; i < 3;i++) + for (j = 0; j < 3;j++) + mMatrix[i][j] = ((mMatrix[i][j] > -FLT_EPSILON) + && (mMatrix[i][j] < FLT_EPSILON)) ? 0.0f : mMatrix[i][j]; } LLVector4 LLMatrix4::getFwdRow4() const { - return LLVector4(mMatrix[VX][VX], mMatrix[VX][VY], mMatrix[VX][VZ], mMatrix[VX][VW]); + return LLVector4(mMatrix[VX][VX], mMatrix[VX][VY], mMatrix[VX][VZ], mMatrix[VX][VW]); } LLVector4 LLMatrix4::getLeftRow4() const { - return LLVector4(mMatrix[VY][VX], mMatrix[VY][VY], mMatrix[VY][VZ], mMatrix[VY][VW]); + return LLVector4(mMatrix[VY][VX], mMatrix[VY][VY], mMatrix[VY][VZ], mMatrix[VY][VW]); } LLVector4 LLMatrix4::getUpRow4() const { - return LLVector4(mMatrix[VZ][VX], mMatrix[VZ][VY], mMatrix[VZ][VZ], mMatrix[VZ][VW]); + return LLVector4(mMatrix[VZ][VX], mMatrix[VZ][VY], mMatrix[VZ][VZ], mMatrix[VZ][VW]); } // SJB: This code is correct for a logicly stored (non-transposed) matrix; -// Our matrices are stored transposed, OpenGL style, so this generates the -// INVERSE quaternion (-x, -y, -z, w)! -// Because we use similar logic in LLQuaternion::getMatrix3, -// we are internally consistant so everything works OK :) -LLQuaternion LLMatrix4::quaternion() const +// Our matrices are stored transposed, OpenGL style, so this generates the +// INVERSE quaternion (-x, -y, -z, w)! +// Because we use similar logic in LLQuaternion::getMatrix3, +// we are internally consistant so everything works OK :) +LLQuaternion LLMatrix4::quaternion() const { - LLQuaternion quat; - F32 tr, s, q[4]; - U32 i, j, k; - U32 nxt[3] = {1, 2, 0}; + LLQuaternion quat; + F32 tr, s, q[4]; + U32 i, j, k; + U32 nxt[3] = {1, 2, 0}; - tr = mMatrix[0][0] + mMatrix[1][1] + mMatrix[2][2]; + tr = mMatrix[0][0] + mMatrix[1][1] + mMatrix[2][2]; - // check the diagonal - if (tr > 0.f) - { - s = (F32)sqrt (tr + 1.f); - quat.mQ[VS] = s / 2.f; - s = 0.5f / s; - quat.mQ[VX] = (mMatrix[1][2] - mMatrix[2][1]) * s; - quat.mQ[VY] = (mMatrix[2][0] - mMatrix[0][2]) * s; - quat.mQ[VZ] = (mMatrix[0][1] - mMatrix[1][0]) * s; - } - else - { - // diagonal is negative - i = 0; - if (mMatrix[1][1] > mMatrix[0][0]) - i = 1; - if (mMatrix[2][2] > mMatrix[i][i]) - i = 2; + // check the diagonal + if (tr > 0.f) + { + s = (F32)sqrt (tr + 1.f); + quat.mQ[VS] = s / 2.f; + s = 0.5f / s; + quat.mQ[VX] = (mMatrix[1][2] - mMatrix[2][1]) * s; + quat.mQ[VY] = (mMatrix[2][0] - mMatrix[0][2]) * s; + quat.mQ[VZ] = (mMatrix[0][1] - mMatrix[1][0]) * s; + } + else + { + // diagonal is negative + i = 0; + if (mMatrix[1][1] > mMatrix[0][0]) + i = 1; + if (mMatrix[2][2] > mMatrix[i][i]) + i = 2; - j = nxt[i]; - k = nxt[j]; + j = nxt[i]; + k = nxt[j]; - s = (F32)sqrt ((mMatrix[i][i] - (mMatrix[j][j] + mMatrix[k][k])) + 1.f); + s = (F32)sqrt ((mMatrix[i][i] - (mMatrix[j][j] + mMatrix[k][k])) + 1.f); - q[i] = s * 0.5f; + q[i] = s * 0.5f; - if (s != 0.f) - s = 0.5f / s; + if (s != 0.f) + s = 0.5f / s; - q[3] = (mMatrix[j][k] - mMatrix[k][j]) * s; - q[j] = (mMatrix[i][j] + mMatrix[j][i]) * s; - q[k] = (mMatrix[i][k] + mMatrix[k][i]) * s; + q[3] = (mMatrix[j][k] - mMatrix[k][j]) * s; + q[j] = (mMatrix[i][j] + mMatrix[j][i]) * s; + q[k] = (mMatrix[i][k] + mMatrix[k][i]) * s; - quat.setQuat(q); - } - return quat; + quat.setQuat(q); + } + return quat; } void LLMatrix4::initRows(const LLVector4 &row0, - const LLVector4 &row1, - const LLVector4 &row2, - const LLVector4 &row3) + const LLVector4 &row1, + const LLVector4 &row2, + const LLVector4 &row3) { - mMatrix[0][0] = row0.mV[0]; - mMatrix[0][1] = row0.mV[1]; - mMatrix[0][2] = row0.mV[2]; - mMatrix[0][3] = row0.mV[3]; + mMatrix[0][0] = row0.mV[0]; + mMatrix[0][1] = row0.mV[1]; + mMatrix[0][2] = row0.mV[2]; + mMatrix[0][3] = row0.mV[3]; - mMatrix[1][0] = row1.mV[0]; - mMatrix[1][1] = row1.mV[1]; - mMatrix[1][2] = row1.mV[2]; - mMatrix[1][3] = row1.mV[3]; + mMatrix[1][0] = row1.mV[0]; + mMatrix[1][1] = row1.mV[1]; + mMatrix[1][2] = row1.mV[2]; + mMatrix[1][3] = row1.mV[3]; - mMatrix[2][0] = row2.mV[0]; - mMatrix[2][1] = row2.mV[1]; - mMatrix[2][2] = row2.mV[2]; - mMatrix[2][3] = row2.mV[3]; + mMatrix[2][0] = row2.mV[0]; + mMatrix[2][1] = row2.mV[1]; + mMatrix[2][2] = row2.mV[2]; + mMatrix[2][3] = row2.mV[3]; - mMatrix[3][0] = row3.mV[0]; - mMatrix[3][1] = row3.mV[1]; - mMatrix[3][2] = row3.mV[2]; - mMatrix[3][3] = row3.mV[3]; + mMatrix[3][0] = row3.mV[0]; + mMatrix[3][1] = row3.mV[1]; + mMatrix[3][2] = row3.mV[2]; + mMatrix[3][3] = row3.mV[3]; } -const LLMatrix4& LLMatrix4::initRotation(F32 angle, const LLVector4 &vec) +const LLMatrix4& LLMatrix4::initRotation(F32 angle, const LLVector4 &vec) { - LLMatrix3 mat(angle, vec); - return initMatrix(mat); + LLMatrix3 mat(angle, vec); + return initMatrix(mat); } -const LLMatrix4& LLMatrix4::initRotation(const F32 roll, const F32 pitch, const F32 yaw) +const LLMatrix4& LLMatrix4::initRotation(const F32 roll, const F32 pitch, const F32 yaw) { - LLMatrix3 mat(roll, pitch, yaw); - return initMatrix(mat); + LLMatrix3 mat(roll, pitch, yaw); + return initMatrix(mat); } -const LLMatrix4& LLMatrix4::initRotation(const LLQuaternion &q) +const LLMatrix4& LLMatrix4::initRotation(const LLQuaternion &q) { - LLMatrix3 mat(q); - return initMatrix(mat); + LLMatrix3 mat(q); + return initMatrix(mat); } -const LLMatrix4& LLMatrix4::initRotTrans(const F32 angle, const LLVector3 &axis, const LLVector3&translation) +const LLMatrix4& LLMatrix4::initRotTrans(const F32 angle, const LLVector3 &axis, const LLVector3&translation) { - LLMatrix3 mat(angle, axis); - initMatrix(mat); - setTranslation(translation); - return (*this); + LLMatrix3 mat(angle, axis); + initMatrix(mat); + setTranslation(translation); + return (*this); } -const LLMatrix4& LLMatrix4::initRotTrans(const F32 roll, const F32 pitch, const F32 yaw, const LLVector4 &translation) +const LLMatrix4& LLMatrix4::initRotTrans(const F32 roll, const F32 pitch, const F32 yaw, const LLVector4 &translation) { - LLMatrix3 mat(roll, pitch, yaw); - initMatrix(mat); - setTranslation(translation); - return (*this); + LLMatrix3 mat(roll, pitch, yaw); + initMatrix(mat); + setTranslation(translation); + return (*this); } /* -const LLMatrix4& LLMatrix4::initRotTrans(const LLVector4 &fwd, - const LLVector4 &left, - const LLVector4 &up, - const LLVector4 &translation) +const LLMatrix4& LLMatrix4::initRotTrans(const LLVector4 &fwd, + const LLVector4 &left, + const LLVector4 &up, + const LLVector4 &translation) { - LLMatrix3 mat(fwd, left, up); - initMatrix(mat); - setTranslation(translation); - return (*this); + LLMatrix3 mat(fwd, left, up); + initMatrix(mat); + setTranslation(translation); + return (*this); } */ -const LLMatrix4& LLMatrix4::initRotTrans(const LLQuaternion &q, const LLVector4 &translation) +const LLMatrix4& LLMatrix4::initRotTrans(const LLQuaternion &q, const LLVector4 &translation) { - LLMatrix3 mat(q); - initMatrix(mat); - setTranslation(translation); - return (*this); + LLMatrix3 mat(q); + initMatrix(mat); + setTranslation(translation); + return (*this); } const LLMatrix4& LLMatrix4::initScale(const LLVector3 &scale) { - setIdentity(); + setIdentity(); + + mMatrix[VX][VX] = scale.mV[VX]; + mMatrix[VY][VY] = scale.mV[VY]; + mMatrix[VZ][VZ] = scale.mV[VZ]; - mMatrix[VX][VX] = scale.mV[VX]; - mMatrix[VY][VY] = scale.mV[VY]; - mMatrix[VZ][VZ] = scale.mV[VZ]; - - return (*this); + return (*this); } const LLMatrix4& LLMatrix4::initAll(const LLVector3 &scale, const LLQuaternion &q, const LLVector3 &pos) { - F32 sx, sy, sz; - F32 xx, xy, xz, xw, yy, yz, yw, zz, zw; + F32 sx, sy, sz; + F32 xx, xy, xz, xw, yy, yz, yw, zz, zw; - sx = scale.mV[0]; - sy = scale.mV[1]; - sz = scale.mV[2]; + sx = scale.mV[0]; + sy = scale.mV[1]; + sz = scale.mV[2]; xx = q.mQ[VX] * q.mQ[VX]; xy = q.mQ[VX] * q.mQ[VY]; @@ -480,394 +480,394 @@ const LLMatrix4& LLMatrix4::initAll(const LLVector3 &scale, const LLQuaternion & zw = q.mQ[VZ] * q.mQ[VW]; mMatrix[0][0] = (1.f - 2.f * ( yy + zz )) *sx; - mMatrix[0][1] = ( 2.f * ( xy + zw )) *sx; - mMatrix[0][2] = ( 2.f * ( xz - yw )) *sx; + mMatrix[0][1] = ( 2.f * ( xy + zw )) *sx; + mMatrix[0][2] = ( 2.f * ( xz - yw )) *sx; - mMatrix[1][0] = ( 2.f * ( xy - zw )) *sy; + mMatrix[1][0] = ( 2.f * ( xy - zw )) *sy; mMatrix[1][1] = (1.f - 2.f * ( xx + zz )) *sy; mMatrix[1][2] = ( 2.f * ( yz + xw )) *sy; - mMatrix[2][0] = ( 2.f * ( xz + yw )) *sz; - mMatrix[2][1] = ( 2.f * ( yz - xw )) *sz; + mMatrix[2][0] = ( 2.f * ( xz + yw )) *sz; + mMatrix[2][1] = ( 2.f * ( yz - xw )) *sz; mMatrix[2][2] = (1.f - 2.f * ( xx + yy )) *sz; - mMatrix[3][0] = pos.mV[0]; - mMatrix[3][1] = pos.mV[1]; - mMatrix[3][2] = pos.mV[2]; - mMatrix[3][3] = 1.0; + mMatrix[3][0] = pos.mV[0]; + mMatrix[3][1] = pos.mV[1]; + mMatrix[3][2] = pos.mV[2]; + mMatrix[3][3] = 1.0; - // TODO -- should we set the translation portion to zero? - return (*this); + // TODO -- should we set the translation portion to zero? + return (*this); } -const LLMatrix4& LLMatrix4::rotate(const F32 angle, const LLVector4 &vec) +const LLMatrix4& LLMatrix4::rotate(const F32 angle, const LLVector4 &vec) { - LLMatrix4 mat(angle, vec); - *this *= mat; - return *this; + LLMatrix4 mat(angle, vec); + *this *= mat; + return *this; } -const LLMatrix4& LLMatrix4::rotate(const F32 roll, const F32 pitch, const F32 yaw) +const LLMatrix4& LLMatrix4::rotate(const F32 roll, const F32 pitch, const F32 yaw) { - LLMatrix4 mat(roll, pitch, yaw); - *this *= mat; - return *this; + LLMatrix4 mat(roll, pitch, yaw); + *this *= mat; + return *this; } -const LLMatrix4& LLMatrix4::rotate(const LLQuaternion &q) +const LLMatrix4& LLMatrix4::rotate(const LLQuaternion &q) { - LLMatrix4 mat(q); - *this *= mat; - return *this; + LLMatrix4 mat(q); + *this *= mat; + return *this; } -const LLMatrix4& LLMatrix4::translate(const LLVector3 &vec) +const LLMatrix4& LLMatrix4::translate(const LLVector3 &vec) { - mMatrix[3][0] += vec.mV[0]; - mMatrix[3][1] += vec.mV[1]; - mMatrix[3][2] += vec.mV[2]; - return (*this); + mMatrix[3][0] += vec.mV[0]; + mMatrix[3][1] += vec.mV[1]; + mMatrix[3][2] += vec.mV[2]; + return (*this); } void LLMatrix4::setFwdRow(const LLVector3 &row) { - mMatrix[VX][VX] = row.mV[VX]; - mMatrix[VX][VY] = row.mV[VY]; - mMatrix[VX][VZ] = row.mV[VZ]; + mMatrix[VX][VX] = row.mV[VX]; + mMatrix[VX][VY] = row.mV[VY]; + mMatrix[VX][VZ] = row.mV[VZ]; } void LLMatrix4::setLeftRow(const LLVector3 &row) { - mMatrix[VY][VX] = row.mV[VX]; - mMatrix[VY][VY] = row.mV[VY]; - mMatrix[VY][VZ] = row.mV[VZ]; + mMatrix[VY][VX] = row.mV[VX]; + mMatrix[VY][VY] = row.mV[VY]; + mMatrix[VY][VZ] = row.mV[VZ]; } void LLMatrix4::setUpRow(const LLVector3 &row) { - mMatrix[VZ][VX] = row.mV[VX]; - mMatrix[VZ][VY] = row.mV[VY]; - mMatrix[VZ][VZ] = row.mV[VZ]; + mMatrix[VZ][VX] = row.mV[VX]; + mMatrix[VZ][VY] = row.mV[VY]; + mMatrix[VZ][VZ] = row.mV[VZ]; } void LLMatrix4::setFwdCol(const LLVector3 &col) { - mMatrix[VX][VX] = col.mV[VX]; - mMatrix[VY][VX] = col.mV[VY]; - mMatrix[VZ][VX] = col.mV[VZ]; + mMatrix[VX][VX] = col.mV[VX]; + mMatrix[VY][VX] = col.mV[VY]; + mMatrix[VZ][VX] = col.mV[VZ]; } void LLMatrix4::setLeftCol(const LLVector3 &col) { - mMatrix[VX][VY] = col.mV[VX]; - mMatrix[VY][VY] = col.mV[VY]; - mMatrix[VZ][VY] = col.mV[VZ]; + mMatrix[VX][VY] = col.mV[VX]; + mMatrix[VY][VY] = col.mV[VY]; + mMatrix[VZ][VY] = col.mV[VZ]; } void LLMatrix4::setUpCol(const LLVector3 &col) { - mMatrix[VX][VZ] = col.mV[VX]; - mMatrix[VY][VZ] = col.mV[VY]; - mMatrix[VZ][VZ] = col.mV[VZ]; + mMatrix[VX][VZ] = col.mV[VX]; + mMatrix[VY][VZ] = col.mV[VY]; + mMatrix[VZ][VZ] = col.mV[VZ]; } -const LLMatrix4& LLMatrix4::setTranslation(const F32 tx, const F32 ty, const F32 tz) +const LLMatrix4& LLMatrix4::setTranslation(const F32 tx, const F32 ty, const F32 tz) { - mMatrix[VW][VX] = tx; - mMatrix[VW][VY] = ty; - mMatrix[VW][VZ] = tz; - return (*this); + mMatrix[VW][VX] = tx; + mMatrix[VW][VY] = ty; + mMatrix[VW][VZ] = tz; + return (*this); } -const LLMatrix4& LLMatrix4::setTranslation(const LLVector3 &translation) +const LLMatrix4& LLMatrix4::setTranslation(const LLVector3 &translation) { - mMatrix[VW][VX] = translation.mV[VX]; - mMatrix[VW][VY] = translation.mV[VY]; - mMatrix[VW][VZ] = translation.mV[VZ]; - return (*this); + mMatrix[VW][VX] = translation.mV[VX]; + mMatrix[VW][VY] = translation.mV[VY]; + mMatrix[VW][VZ] = translation.mV[VZ]; + return (*this); } -const LLMatrix4& LLMatrix4::setTranslation(const LLVector4 &translation) +const LLMatrix4& LLMatrix4::setTranslation(const LLVector4 &translation) { - mMatrix[VW][VX] = translation.mV[VX]; - mMatrix[VW][VY] = translation.mV[VY]; - mMatrix[VW][VZ] = translation.mV[VZ]; - return (*this); + mMatrix[VW][VX] = translation.mV[VX]; + mMatrix[VW][VY] = translation.mV[VY]; + mMatrix[VW][VZ] = translation.mV[VZ]; + return (*this); } // LLMatrix3 Extraction and Setting -LLMatrix3 LLMatrix4::getMat3() const +LLMatrix3 LLMatrix4::getMat3() const { - LLMatrix3 retmat; + LLMatrix3 retmat; - retmat.mMatrix[0][0] = mMatrix[0][0]; - retmat.mMatrix[0][1] = mMatrix[0][1]; - retmat.mMatrix[0][2] = mMatrix[0][2]; + retmat.mMatrix[0][0] = mMatrix[0][0]; + retmat.mMatrix[0][1] = mMatrix[0][1]; + retmat.mMatrix[0][2] = mMatrix[0][2]; - retmat.mMatrix[1][0] = mMatrix[1][0]; - retmat.mMatrix[1][1] = mMatrix[1][1]; - retmat.mMatrix[1][2] = mMatrix[1][2]; + retmat.mMatrix[1][0] = mMatrix[1][0]; + retmat.mMatrix[1][1] = mMatrix[1][1]; + retmat.mMatrix[1][2] = mMatrix[1][2]; - retmat.mMatrix[2][0] = mMatrix[2][0]; - retmat.mMatrix[2][1] = mMatrix[2][1]; - retmat.mMatrix[2][2] = mMatrix[2][2]; + retmat.mMatrix[2][0] = mMatrix[2][0]; + retmat.mMatrix[2][1] = mMatrix[2][1]; + retmat.mMatrix[2][2] = mMatrix[2][2]; - return retmat; + return retmat; } -const LLMatrix4& LLMatrix4::initMatrix(const LLMatrix3 &mat) +const LLMatrix4& LLMatrix4::initMatrix(const LLMatrix3 &mat) { - mMatrix[0][0] = mat.mMatrix[0][0]; - mMatrix[0][1] = mat.mMatrix[0][1]; - mMatrix[0][2] = mat.mMatrix[0][2]; - mMatrix[0][3] = 0.f; + mMatrix[0][0] = mat.mMatrix[0][0]; + mMatrix[0][1] = mat.mMatrix[0][1]; + mMatrix[0][2] = mat.mMatrix[0][2]; + mMatrix[0][3] = 0.f; - mMatrix[1][0] = mat.mMatrix[1][0]; - mMatrix[1][1] = mat.mMatrix[1][1]; - mMatrix[1][2] = mat.mMatrix[1][2]; - mMatrix[1][3] = 0.f; + mMatrix[1][0] = mat.mMatrix[1][0]; + mMatrix[1][1] = mat.mMatrix[1][1]; + mMatrix[1][2] = mat.mMatrix[1][2]; + mMatrix[1][3] = 0.f; - mMatrix[2][0] = mat.mMatrix[2][0]; - mMatrix[2][1] = mat.mMatrix[2][1]; - mMatrix[2][2] = mat.mMatrix[2][2]; - mMatrix[2][3] = 0.f; + mMatrix[2][0] = mat.mMatrix[2][0]; + mMatrix[2][1] = mat.mMatrix[2][1]; + mMatrix[2][2] = mat.mMatrix[2][2]; + mMatrix[2][3] = 0.f; - mMatrix[3][0] = 0.f; - mMatrix[3][1] = 0.f; - mMatrix[3][2] = 0.f; - mMatrix[3][3] = 1.f; - return (*this); + mMatrix[3][0] = 0.f; + mMatrix[3][1] = 0.f; + mMatrix[3][2] = 0.f; + mMatrix[3][3] = 1.f; + return (*this); } -const LLMatrix4& LLMatrix4::initMatrix(const LLMatrix3 &mat, const LLVector4 &translation) +const LLMatrix4& LLMatrix4::initMatrix(const LLMatrix3 &mat, const LLVector4 &translation) { - mMatrix[0][0] = mat.mMatrix[0][0]; - mMatrix[0][1] = mat.mMatrix[0][1]; - mMatrix[0][2] = mat.mMatrix[0][2]; - mMatrix[0][3] = 0.f; + mMatrix[0][0] = mat.mMatrix[0][0]; + mMatrix[0][1] = mat.mMatrix[0][1]; + mMatrix[0][2] = mat.mMatrix[0][2]; + mMatrix[0][3] = 0.f; - mMatrix[1][0] = mat.mMatrix[1][0]; - mMatrix[1][1] = mat.mMatrix[1][1]; - mMatrix[1][2] = mat.mMatrix[1][2]; - mMatrix[1][3] = 0.f; + mMatrix[1][0] = mat.mMatrix[1][0]; + mMatrix[1][1] = mat.mMatrix[1][1]; + mMatrix[1][2] = mat.mMatrix[1][2]; + mMatrix[1][3] = 0.f; - mMatrix[2][0] = mat.mMatrix[2][0]; - mMatrix[2][1] = mat.mMatrix[2][1]; - mMatrix[2][2] = mat.mMatrix[2][2]; - mMatrix[2][3] = 0.f; + mMatrix[2][0] = mat.mMatrix[2][0]; + mMatrix[2][1] = mat.mMatrix[2][1]; + mMatrix[2][2] = mat.mMatrix[2][2]; + mMatrix[2][3] = 0.f; - mMatrix[3][0] = translation.mV[0]; - mMatrix[3][1] = translation.mV[1]; - mMatrix[3][2] = translation.mV[2]; - mMatrix[3][3] = 1.f; - return (*this); + mMatrix[3][0] = translation.mV[0]; + mMatrix[3][1] = translation.mV[1]; + mMatrix[3][2] = translation.mV[2]; + mMatrix[3][3] = 1.f; + return (*this); } // LLMatrix4 Operators LLVector4 operator*(const LLVector4 &a, const LLMatrix4 &b) { - // Operate "to the left" on row-vector a - return LLVector4(a.mV[VX] * b.mMatrix[VX][VX] + - a.mV[VY] * b.mMatrix[VY][VX] + - a.mV[VZ] * b.mMatrix[VZ][VX] + - a.mV[VW] * b.mMatrix[VW][VX], + // Operate "to the left" on row-vector a + return LLVector4(a.mV[VX] * b.mMatrix[VX][VX] + + a.mV[VY] * b.mMatrix[VY][VX] + + a.mV[VZ] * b.mMatrix[VZ][VX] + + a.mV[VW] * b.mMatrix[VW][VX], - a.mV[VX] * b.mMatrix[VX][VY] + - a.mV[VY] * b.mMatrix[VY][VY] + - a.mV[VZ] * b.mMatrix[VZ][VY] + - a.mV[VW] * b.mMatrix[VW][VY], + a.mV[VX] * b.mMatrix[VX][VY] + + a.mV[VY] * b.mMatrix[VY][VY] + + a.mV[VZ] * b.mMatrix[VZ][VY] + + a.mV[VW] * b.mMatrix[VW][VY], - a.mV[VX] * b.mMatrix[VX][VZ] + - a.mV[VY] * b.mMatrix[VY][VZ] + - a.mV[VZ] * b.mMatrix[VZ][VZ] + - a.mV[VW] * b.mMatrix[VW][VZ], + a.mV[VX] * b.mMatrix[VX][VZ] + + a.mV[VY] * b.mMatrix[VY][VZ] + + a.mV[VZ] * b.mMatrix[VZ][VZ] + + a.mV[VW] * b.mMatrix[VW][VZ], - a.mV[VX] * b.mMatrix[VX][VW] + - a.mV[VY] * b.mMatrix[VY][VW] + - a.mV[VZ] * b.mMatrix[VZ][VW] + - a.mV[VW] * b.mMatrix[VW][VW]); + a.mV[VX] * b.mMatrix[VX][VW] + + a.mV[VY] * b.mMatrix[VY][VW] + + a.mV[VZ] * b.mMatrix[VZ][VW] + + a.mV[VW] * b.mMatrix[VW][VW]); } LLVector4 rotate_vector(const LLVector4 &a, const LLMatrix4 &b) { - // Rotates but does not translate - // Operate "to the left" on row-vector a - LLVector4 vec; - vec.mV[VX] = a.mV[VX] * b.mMatrix[VX][VX] + - a.mV[VY] * b.mMatrix[VY][VX] + - a.mV[VZ] * b.mMatrix[VZ][VX]; + // Rotates but does not translate + // Operate "to the left" on row-vector a + LLVector4 vec; + vec.mV[VX] = a.mV[VX] * b.mMatrix[VX][VX] + + a.mV[VY] * b.mMatrix[VY][VX] + + a.mV[VZ] * b.mMatrix[VZ][VX]; - vec.mV[VY] = a.mV[VX] * b.mMatrix[VX][VY] + - a.mV[VY] * b.mMatrix[VY][VY] + - a.mV[VZ] * b.mMatrix[VZ][VY]; + vec.mV[VY] = a.mV[VX] * b.mMatrix[VX][VY] + + a.mV[VY] * b.mMatrix[VY][VY] + + a.mV[VZ] * b.mMatrix[VZ][VY]; - vec.mV[VZ] = a.mV[VX] * b.mMatrix[VX][VZ] + - a.mV[VY] * b.mMatrix[VY][VZ] + - a.mV[VZ] * b.mMatrix[VZ][VZ]; + vec.mV[VZ] = a.mV[VX] * b.mMatrix[VX][VZ] + + a.mV[VY] * b.mMatrix[VY][VZ] + + a.mV[VZ] * b.mMatrix[VZ][VZ]; -// vec.mV[VW] = a.mV[VX] * b.mMatrix[VX][VW] + -// a.mV[VY] * b.mMatrix[VY][VW] + -// a.mV[VZ] * b.mMatrix[VZ][VW] + - vec.mV[VW] = a.mV[VW]; - return vec; +// vec.mV[VW] = a.mV[VX] * b.mMatrix[VX][VW] + +// a.mV[VY] * b.mMatrix[VY][VW] + +// a.mV[VZ] * b.mMatrix[VZ][VW] + + vec.mV[VW] = a.mV[VW]; + return vec; } LLVector3 rotate_vector(const LLVector3 &a, const LLMatrix4 &b) { - // Rotates but does not translate - // Operate "to the left" on row-vector a - LLVector3 vec; - vec.mV[VX] = a.mV[VX] * b.mMatrix[VX][VX] + - a.mV[VY] * b.mMatrix[VY][VX] + - a.mV[VZ] * b.mMatrix[VZ][VX]; + // Rotates but does not translate + // Operate "to the left" on row-vector a + LLVector3 vec; + vec.mV[VX] = a.mV[VX] * b.mMatrix[VX][VX] + + a.mV[VY] * b.mMatrix[VY][VX] + + a.mV[VZ] * b.mMatrix[VZ][VX]; - vec.mV[VY] = a.mV[VX] * b.mMatrix[VX][VY] + - a.mV[VY] * b.mMatrix[VY][VY] + - a.mV[VZ] * b.mMatrix[VZ][VY]; + vec.mV[VY] = a.mV[VX] * b.mMatrix[VX][VY] + + a.mV[VY] * b.mMatrix[VY][VY] + + a.mV[VZ] * b.mMatrix[VZ][VY]; - vec.mV[VZ] = a.mV[VX] * b.mMatrix[VX][VZ] + - a.mV[VY] * b.mMatrix[VY][VZ] + - a.mV[VZ] * b.mMatrix[VZ][VZ]; - return vec; + vec.mV[VZ] = a.mV[VX] * b.mMatrix[VX][VZ] + + a.mV[VY] * b.mMatrix[VY][VZ] + + a.mV[VZ] * b.mMatrix[VZ][VZ]; + return vec; } bool operator==(const LLMatrix4 &a, const LLMatrix4 &b) { - U32 i, j; - for (i = 0; i < NUM_VALUES_IN_MAT4; i++) - { - for (j = 0; j < NUM_VALUES_IN_MAT4; j++) - { - if (a.mMatrix[j][i] != b.mMatrix[j][i]) - return false; - } - } - return true; + U32 i, j; + for (i = 0; i < NUM_VALUES_IN_MAT4; i++) + { + for (j = 0; j < NUM_VALUES_IN_MAT4; j++) + { + if (a.mMatrix[j][i] != b.mMatrix[j][i]) + return false; + } + } + return true; } bool operator!=(const LLMatrix4 &a, const LLMatrix4 &b) { - U32 i, j; - for (i = 0; i < NUM_VALUES_IN_MAT4; i++) - { - for (j = 0; j < NUM_VALUES_IN_MAT4; j++) - { - if (a.mMatrix[j][i] != b.mMatrix[j][i]) - return true; - } - } - return false; + U32 i, j; + for (i = 0; i < NUM_VALUES_IN_MAT4; i++) + { + for (j = 0; j < NUM_VALUES_IN_MAT4; j++) + { + if (a.mMatrix[j][i] != b.mMatrix[j][i]) + return true; + } + } + return false; } bool operator<(const LLMatrix4& a, const LLMatrix4 &b) { - U32 i, j; - for (i = 0; i < NUM_VALUES_IN_MAT4; i++) - { - for (j = 0; j < NUM_VALUES_IN_MAT4; j++) - { - if (a.mMatrix[i][j] != b.mMatrix[i][j]) - { - return a.mMatrix[i][j] < b.mMatrix[i][j]; - } - } - } + U32 i, j; + for (i = 0; i < NUM_VALUES_IN_MAT4; i++) + { + for (j = 0; j < NUM_VALUES_IN_MAT4; j++) + { + if (a.mMatrix[i][j] != b.mMatrix[i][j]) + { + return a.mMatrix[i][j] < b.mMatrix[i][j]; + } + } + } - return false; + return false; } const LLMatrix4& operator*=(LLMatrix4 &a, F32 k) { - U32 i, j; - for (i = 0; i < NUM_VALUES_IN_MAT4; i++) - { - for (j = 0; j < NUM_VALUES_IN_MAT4; j++) - { - a.mMatrix[j][i] *= k; - } - } - return a; -} - -std::ostream& operator<<(std::ostream& s, const LLMatrix4 &a) -{ - s << "{ " - << a.mMatrix[VX][VX] << ", " - << a.mMatrix[VX][VY] << ", " - << a.mMatrix[VX][VZ] << ", " - << a.mMatrix[VX][VW] - << "; " - << a.mMatrix[VY][VX] << ", " - << a.mMatrix[VY][VY] << ", " - << a.mMatrix[VY][VZ] << ", " - << a.mMatrix[VY][VW] - << "; " - << a.mMatrix[VZ][VX] << ", " - << a.mMatrix[VZ][VY] << ", " - << a.mMatrix[VZ][VZ] << ", " - << a.mMatrix[VZ][VW] - << "; " - << a.mMatrix[VW][VX] << ", " - << a.mMatrix[VW][VY] << ", " - << a.mMatrix[VW][VZ] << ", " - << a.mMatrix[VW][VW] - << " }"; - return s; + U32 i, j; + for (i = 0; i < NUM_VALUES_IN_MAT4; i++) + { + for (j = 0; j < NUM_VALUES_IN_MAT4; j++) + { + a.mMatrix[j][i] *= k; + } + } + return a; +} + +std::ostream& operator<<(std::ostream& s, const LLMatrix4 &a) +{ + s << "{ " + << a.mMatrix[VX][VX] << ", " + << a.mMatrix[VX][VY] << ", " + << a.mMatrix[VX][VZ] << ", " + << a.mMatrix[VX][VW] + << "; " + << a.mMatrix[VY][VX] << ", " + << a.mMatrix[VY][VY] << ", " + << a.mMatrix[VY][VZ] << ", " + << a.mMatrix[VY][VW] + << "; " + << a.mMatrix[VZ][VX] << ", " + << a.mMatrix[VZ][VY] << ", " + << a.mMatrix[VZ][VZ] << ", " + << a.mMatrix[VZ][VW] + << "; " + << a.mMatrix[VW][VX] << ", " + << a.mMatrix[VW][VY] << ", " + << a.mMatrix[VW][VZ] << ", " + << a.mMatrix[VW][VW] + << " }"; + return s; } LLSD LLMatrix4::getValue() const { - LLSD ret; - - ret[0] = mMatrix[0][0]; - ret[1] = mMatrix[0][1]; - ret[2] = mMatrix[0][2]; - ret[3] = mMatrix[0][3]; + LLSD ret; + + ret[0] = mMatrix[0][0]; + ret[1] = mMatrix[0][1]; + ret[2] = mMatrix[0][2]; + ret[3] = mMatrix[0][3]; - ret[4] = mMatrix[1][0]; - ret[5] = mMatrix[1][1]; - ret[6] = mMatrix[1][2]; - ret[7] = mMatrix[1][3]; + ret[4] = mMatrix[1][0]; + ret[5] = mMatrix[1][1]; + ret[6] = mMatrix[1][2]; + ret[7] = mMatrix[1][3]; - ret[8] = mMatrix[2][0]; - ret[9] = mMatrix[2][1]; - ret[10] = mMatrix[2][2]; - ret[11] = mMatrix[2][3]; + ret[8] = mMatrix[2][0]; + ret[9] = mMatrix[2][1]; + ret[10] = mMatrix[2][2]; + ret[11] = mMatrix[2][3]; - ret[12] = mMatrix[3][0]; - ret[13] = mMatrix[3][1]; - ret[14] = mMatrix[3][2]; - ret[15] = mMatrix[3][3]; + ret[12] = mMatrix[3][0]; + ret[13] = mMatrix[3][1]; + ret[14] = mMatrix[3][2]; + ret[15] = mMatrix[3][3]; - return ret; + return ret; } -void LLMatrix4::setValue(const LLSD& data) +void LLMatrix4::setValue(const LLSD& data) { - mMatrix[0][0] = (F32)data[0].asReal(); - mMatrix[0][1] = (F32)data[1].asReal(); - mMatrix[0][2] = (F32)data[2].asReal(); - mMatrix[0][3] = (F32)data[3].asReal(); + mMatrix[0][0] = (F32)data[0].asReal(); + mMatrix[0][1] = (F32)data[1].asReal(); + mMatrix[0][2] = (F32)data[2].asReal(); + mMatrix[0][3] = (F32)data[3].asReal(); - mMatrix[1][0] = (F32)data[4].asReal(); - mMatrix[1][1] = (F32)data[5].asReal(); - mMatrix[1][2] = (F32)data[6].asReal(); - mMatrix[1][3] = (F32)data[7].asReal(); + mMatrix[1][0] = (F32)data[4].asReal(); + mMatrix[1][1] = (F32)data[5].asReal(); + mMatrix[1][2] = (F32)data[6].asReal(); + mMatrix[1][3] = (F32)data[7].asReal(); - mMatrix[2][0] = (F32)data[8].asReal(); - mMatrix[2][1] = (F32)data[9].asReal(); - mMatrix[2][2] = (F32)data[10].asReal(); - mMatrix[2][3] = (F32)data[11].asReal(); + mMatrix[2][0] = (F32)data[8].asReal(); + mMatrix[2][1] = (F32)data[9].asReal(); + mMatrix[2][2] = (F32)data[10].asReal(); + mMatrix[2][3] = (F32)data[11].asReal(); - mMatrix[3][0] = (F32)data[12].asReal(); - mMatrix[3][1] = (F32)data[13].asReal(); - mMatrix[3][2] = (F32)data[14].asReal(); - mMatrix[3][3] = (F32)data[15].asReal(); + mMatrix[3][0] = (F32)data[12].asReal(); + mMatrix[3][1] = (F32)data[13].asReal(); + mMatrix[3][2] = (F32)data[14].asReal(); + mMatrix[3][3] = (F32)data[15].asReal(); } diff --git a/indra/llmath/m4math.h b/indra/llmath/m4math.h index b9da970cde..b0f8c90cdf 100644 --- a/indra/llmath/m4math.h +++ b/indra/llmath/m4math.h @@ -1,25 +1,25 @@ -/** +/** * @file m4math.h * @brief LLMatrix4 class header file. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -58,16 +58,16 @@ class LLMatrix4a; // One way to think about it is a matrix that takes the origin frame A // and rotates it into B': i.e. A*M = B // -// Vectors: -// f - forward axis of B expressed in A -// l - left axis of B expressed in A -// u - up axis of B expressed in A +// Vectors: +// f - forward axis of B expressed in A +// l - left axis of B expressed in A +// u - up axis of B expressed in A // -// | 0: fx 1: fy 2: fz 3:0 | +// | 0: fx 1: fy 2: fz 3:0 | // M = | 4: lx 5: ly 6: lz 7:0 | // | 8: ux 9: uy 10: uz 11:0 | // | 12: 0 13: 0 14: 0 15:1 | -// +// // // // @@ -76,18 +76,18 @@ class LLMatrix4a; // // so p*M = p' // -// Vectors: +// Vectors: // f - forward of frame B in frame A // l - left of frame B in frame A // u - up of frame B in frame A // o - origin of frame frame B in frame A // -// | 0: fx 1: lx 2: ux 3:0 | +// | 0: fx 1: lx 2: ux 3:0 | // M = | 4: fy 5: ly 6: uy 7:0 | // | 8: fz 9: lz 10: uz 11:0 | // | 12:-of 13:-ol 14:-ou 15:1 | // -// of, ol, and ou mean the component of the "global" origin o in the f axis, l axis, and u axis. +// of, ol, and ou mean the component of the "global" origin o in the f axis, l axis, and u axis. // static const U32 NUM_VALUES_IN_MAT4 = 4; @@ -95,283 +95,283 @@ static const U32 NUM_VALUES_IN_MAT4 = 4; class LLMatrix4 { public: - F32 mMatrix[NUM_VALUES_IN_MAT4][NUM_VALUES_IN_MAT4]; - - // Initializes Matrix to identity matrix - LLMatrix4() - { - setIdentity(); - } - explicit LLMatrix4(const F32 *mat); // Initializes Matrix to values in mat - explicit LLMatrix4(const LLMatrix3 &mat); // Initializes Matrix to values in mat and sets position to (0,0,0) - explicit LLMatrix4(const LLQuaternion &q); // Initializes Matrix with rotation q and sets position to (0,0,0) + F32 mMatrix[NUM_VALUES_IN_MAT4][NUM_VALUES_IN_MAT4]; + + // Initializes Matrix to identity matrix + LLMatrix4() + { + setIdentity(); + } + explicit LLMatrix4(const F32 *mat); // Initializes Matrix to values in mat + explicit LLMatrix4(const LLMatrix3 &mat); // Initializes Matrix to values in mat and sets position to (0,0,0) + explicit LLMatrix4(const LLQuaternion &q); // Initializes Matrix with rotation q and sets position to (0,0,0) explicit LLMatrix4(const LLMatrix4a& mat); - LLMatrix4(const LLMatrix3 &mat, const LLVector4 &pos); // Initializes Matrix to values in mat and pos + LLMatrix4(const LLMatrix3 &mat, const LLVector4 &pos); // Initializes Matrix to values in mat and pos + + // These are really, really, inefficient as implemented! - djs + LLMatrix4(const LLQuaternion &q, const LLVector4 &pos); // Initializes Matrix with rotation q and position pos + LLMatrix4(F32 angle, + const LLVector4 &vec, + const LLVector4 &pos); // Initializes Matrix with axis-angle and position + LLMatrix4(F32 angle, const LLVector4 &vec); // Initializes Matrix with axis-angle and sets position to (0,0,0) + LLMatrix4(const F32 roll, const F32 pitch, const F32 yaw, + const LLVector4 &pos); // Initializes Matrix with Euler angles + LLMatrix4(const F32 roll, const F32 pitch, const F32 yaw); // Initializes Matrix with Euler angles + + ~LLMatrix4(void); // Destructor + + LLSD getValue() const; + void setValue(const LLSD&); - // These are really, really, inefficient as implemented! - djs - LLMatrix4(const LLQuaternion &q, const LLVector4 &pos); // Initializes Matrix with rotation q and position pos - LLMatrix4(F32 angle, - const LLVector4 &vec, - const LLVector4 &pos); // Initializes Matrix with axis-angle and position - LLMatrix4(F32 angle, const LLVector4 &vec); // Initializes Matrix with axis-angle and sets position to (0,0,0) - LLMatrix4(const F32 roll, const F32 pitch, const F32 yaw, - const LLVector4 &pos); // Initializes Matrix with Euler angles - LLMatrix4(const F32 roll, const F32 pitch, const F32 yaw); // Initializes Matrix with Euler angles + ////////////////////////////// + // + // Matrix initializers - these replace any existing values in the matrix + // - ~LLMatrix4(void); // Destructor + void initRows(const LLVector4 &row0, + const LLVector4 &row1, + const LLVector4 &row2, + const LLVector4 &row3); - LLSD getValue() const; - void setValue(const LLSD&); + // various useful matrix functions + const LLMatrix4& setIdentity(); // Load identity matrix + bool isIdentity() const; + const LLMatrix4& setZero(); // Clears matrix to all zeros. - ////////////////////////////// - // - // Matrix initializers - these replace any existing values in the matrix - // + const LLMatrix4& initRotation(const F32 angle, const LLVector4 &axis); // Calculate rotation matrix for rotating angle radians about vec + const LLMatrix4& initRotation(const F32 roll, const F32 pitch, const F32 yaw); // Calculate rotation matrix from Euler angles + const LLMatrix4& initRotation(const LLQuaternion &q); // Set with Quaternion and position - void initRows(const LLVector4 &row0, - const LLVector4 &row1, - const LLVector4 &row2, - const LLVector4 &row3); + // Position Only + const LLMatrix4& initMatrix(const LLMatrix3 &mat); // + const LLMatrix4& initMatrix(const LLMatrix3 &mat, const LLVector4 &translation); - // various useful matrix functions - const LLMatrix4& setIdentity(); // Load identity matrix - bool isIdentity() const; - const LLMatrix4& setZero(); // Clears matrix to all zeros. + // These operation create a matrix that will rotate and translate by the + // specified amounts. + const LLMatrix4& initRotTrans(const F32 angle, const LLVector3 &axis, const LLVector3 &translation); // Rotation from axis angle + translation + const LLMatrix4& initRotTrans(const F32 roll, const F32 pitch, const F32 yaw, const LLVector4 &pos); // Rotation from Euler + translation + const LLMatrix4& initRotTrans(const LLQuaternion &q, const LLVector4 &pos); // Set with Quaternion and position - const LLMatrix4& initRotation(const F32 angle, const LLVector4 &axis); // Calculate rotation matrix for rotating angle radians about vec - const LLMatrix4& initRotation(const F32 roll, const F32 pitch, const F32 yaw); // Calculate rotation matrix from Euler angles - const LLMatrix4& initRotation(const LLQuaternion &q); // Set with Quaternion and position - - // Position Only - const LLMatrix4& initMatrix(const LLMatrix3 &mat); // - const LLMatrix4& initMatrix(const LLMatrix3 &mat, const LLVector4 &translation); + const LLMatrix4& initScale(const LLVector3 &scale); - // These operation create a matrix that will rotate and translate by the - // specified amounts. - const LLMatrix4& initRotTrans(const F32 angle, const LLVector3 &axis, const LLVector3 &translation); // Rotation from axis angle + translation - const LLMatrix4& initRotTrans(const F32 roll, const F32 pitch, const F32 yaw, const LLVector4 &pos); // Rotation from Euler + translation - const LLMatrix4& initRotTrans(const LLQuaternion &q, const LLVector4 &pos); // Set with Quaternion and position + // Set all + const LLMatrix4& initAll(const LLVector3 &scale, const LLQuaternion &q, const LLVector3 &pos); - const LLMatrix4& initScale(const LLVector3 &scale); - // Set all - const LLMatrix4& initAll(const LLVector3 &scale, const LLQuaternion &q, const LLVector3 &pos); + /////////////////////////// + // + // Matrix setters - set some properties without modifying others + // + const LLMatrix4& setTranslation(const F32 x, const F32 y, const F32 z); // Sets matrix to translate by (x,y,z) - /////////////////////////// - // - // Matrix setters - set some properties without modifying others - // + void setFwdRow(const LLVector3 &row); + void setLeftRow(const LLVector3 &row); + void setUpRow(const LLVector3 &row); - const LLMatrix4& setTranslation(const F32 x, const F32 y, const F32 z); // Sets matrix to translate by (x,y,z) + void setFwdCol(const LLVector3 &col); + void setLeftCol(const LLVector3 &col); + void setUpCol(const LLVector3 &col); - void setFwdRow(const LLVector3 &row); - void setLeftRow(const LLVector3 &row); - void setUpRow(const LLVector3 &row); + const LLMatrix4& setTranslation(const LLVector4 &translation); + const LLMatrix4& setTranslation(const LLVector3 &translation); - void setFwdCol(const LLVector3 &col); - void setLeftCol(const LLVector3 &col); - void setUpCol(const LLVector3 &col); + // Convenience func for simplifying comparison-heavy code by + // intentionally stomping values [-FLT_EPS,FLT_EPS] to 0.0 + // + void condition(void); - const LLMatrix4& setTranslation(const LLVector4 &translation); - const LLMatrix4& setTranslation(const LLVector3 &translation); + /////////////////////////// + // + // Get properties of a matrix + // - // Convenience func for simplifying comparison-heavy code by - // intentionally stomping values [-FLT_EPS,FLT_EPS] to 0.0 - // - void condition(void); + F32 determinant(void) const; // Return determinant + LLQuaternion quaternion(void) const; // Returns quaternion - /////////////////////////// - // - // Get properties of a matrix - // + LLVector4 getFwdRow4() const; + LLVector4 getLeftRow4() const; + LLVector4 getUpRow4() const; - F32 determinant(void) const; // Return determinant - LLQuaternion quaternion(void) const; // Returns quaternion + LLMatrix3 getMat3() const; - LLVector4 getFwdRow4() const; - LLVector4 getLeftRow4() const; - LLVector4 getUpRow4() const; + const LLVector3& getTranslation() const { return *(LLVector3*)&mMatrix[3][0]; } - LLMatrix3 getMat3() const; + /////////////////////////// + // + // Operations on an existing matrix + // - const LLVector3& getTranslation() const { return *(LLVector3*)&mMatrix[3][0]; } + const LLMatrix4& transpose(); // Transpose LLMatrix4 + const LLMatrix4& invert(); // Invert LLMatrix4 - /////////////////////////// - // - // Operations on an existing matrix - // + // Rotate existing matrix + // These are really, really, inefficient as implemented! - djs + const LLMatrix4& rotate(const F32 angle, const LLVector4 &vec); // Rotate matrix by rotating angle radians about vec + const LLMatrix4& rotate(const F32 roll, const F32 pitch, const F32 yaw); // Rotate matrix by Euler angles + const LLMatrix4& rotate(const LLQuaternion &q); // Rotate matrix by Quaternion - const LLMatrix4& transpose(); // Transpose LLMatrix4 - const LLMatrix4& invert(); // Invert LLMatrix4 - // Rotate existing matrix - // These are really, really, inefficient as implemented! - djs - const LLMatrix4& rotate(const F32 angle, const LLVector4 &vec); // Rotate matrix by rotating angle radians about vec - const LLMatrix4& rotate(const F32 roll, const F32 pitch, const F32 yaw); // Rotate matrix by Euler angles - const LLMatrix4& rotate(const LLQuaternion &q); // Rotate matrix by Quaternion + // Translate existing matrix + const LLMatrix4& translate(const LLVector3 &vec); // Translate matrix by (vec[VX], vec[VY], vec[VZ]) - - // Translate existing matrix - const LLMatrix4& translate(const LLVector3 &vec); // Translate matrix by (vec[VX], vec[VY], vec[VZ]) - - /////////////////////// - // - // Operators - // + /////////////////////// + // + // Operators + // - // friend inline LLMatrix4 operator*(const LLMatrix4 &a, const LLMatrix4 &b); // Return a * b - friend LLVector4 operator*(const LLVector4 &a, const LLMatrix4 &b); // Return transform of vector a by matrix b - friend const LLVector3 operator*(const LLVector3 &a, const LLMatrix4 &b); // Return full transform of a by matrix b - friend LLVector4 rotate_vector(const LLVector4 &a, const LLMatrix4 &b); // Rotates a but does not translate - friend LLVector3 rotate_vector(const LLVector3 &a, const LLMatrix4 &b); // Rotates a but does not translate + // friend inline LLMatrix4 operator*(const LLMatrix4 &a, const LLMatrix4 &b); // Return a * b + friend LLVector4 operator*(const LLVector4 &a, const LLMatrix4 &b); // Return transform of vector a by matrix b + friend const LLVector3 operator*(const LLVector3 &a, const LLMatrix4 &b); // Return full transform of a by matrix b + friend LLVector4 rotate_vector(const LLVector4 &a, const LLMatrix4 &b); // Rotates a but does not translate + friend LLVector3 rotate_vector(const LLVector3 &a, const LLMatrix4 &b); // Rotates a but does not translate - friend bool operator==(const LLMatrix4 &a, const LLMatrix4 &b); // Return a == b - friend bool operator!=(const LLMatrix4 &a, const LLMatrix4 &b); // Return a != b - friend bool operator<(const LLMatrix4 &a, const LLMatrix4& b); // Return a < b + friend bool operator==(const LLMatrix4 &a, const LLMatrix4 &b); // Return a == b + friend bool operator!=(const LLMatrix4 &a, const LLMatrix4 &b); // Return a != b + friend bool operator<(const LLMatrix4 &a, const LLMatrix4& b); // Return a < b - friend const LLMatrix4& operator+=(LLMatrix4 &a, const LLMatrix4 &b); // Return a + b - friend const LLMatrix4& operator-=(LLMatrix4 &a, const LLMatrix4 &b); // Return a - b - friend const LLMatrix4& operator*=(LLMatrix4 &a, const LLMatrix4 &b); // Return a * b - friend const LLMatrix4& operator*=(LLMatrix4 &a, const F32 &b); // Return a * b + friend const LLMatrix4& operator+=(LLMatrix4 &a, const LLMatrix4 &b); // Return a + b + friend const LLMatrix4& operator-=(LLMatrix4 &a, const LLMatrix4 &b); // Return a - b + friend const LLMatrix4& operator*=(LLMatrix4 &a, const LLMatrix4 &b); // Return a * b + friend const LLMatrix4& operator*=(LLMatrix4 &a, const F32 &b); // Return a * b - friend std::ostream& operator<<(std::ostream& s, const LLMatrix4 &a); // Stream a + friend std::ostream& operator<<(std::ostream& s, const LLMatrix4 &a); // Stream a }; -inline const LLMatrix4& LLMatrix4::setIdentity() +inline const LLMatrix4& LLMatrix4::setIdentity() { - mMatrix[0][0] = 1.f; - mMatrix[0][1] = 0.f; - mMatrix[0][2] = 0.f; - mMatrix[0][3] = 0.f; - - mMatrix[1][0] = 0.f; - mMatrix[1][1] = 1.f; - mMatrix[1][2] = 0.f; - mMatrix[1][3] = 0.f; - - mMatrix[2][0] = 0.f; - mMatrix[2][1] = 0.f; - mMatrix[2][2] = 1.f; - mMatrix[2][3] = 0.f; - - mMatrix[3][0] = 0.f; - mMatrix[3][1] = 0.f; - mMatrix[3][2] = 0.f; - mMatrix[3][3] = 1.f; - return (*this); + mMatrix[0][0] = 1.f; + mMatrix[0][1] = 0.f; + mMatrix[0][2] = 0.f; + mMatrix[0][3] = 0.f; + + mMatrix[1][0] = 0.f; + mMatrix[1][1] = 1.f; + mMatrix[1][2] = 0.f; + mMatrix[1][3] = 0.f; + + mMatrix[2][0] = 0.f; + mMatrix[2][1] = 0.f; + mMatrix[2][2] = 1.f; + mMatrix[2][3] = 0.f; + + mMatrix[3][0] = 0.f; + mMatrix[3][1] = 0.f; + mMatrix[3][2] = 0.f; + mMatrix[3][3] = 1.f; + return (*this); } inline bool LLMatrix4::isIdentity() const { - return - mMatrix[0][0] == 1.f && - mMatrix[0][1] == 0.f && - mMatrix[0][2] == 0.f && - mMatrix[0][3] == 0.f && - - mMatrix[1][0] == 0.f && - mMatrix[1][1] == 1.f && - mMatrix[1][2] == 0.f && - mMatrix[1][3] == 0.f && - - mMatrix[2][0] == 0.f && - mMatrix[2][1] == 0.f && - mMatrix[2][2] == 1.f && - mMatrix[2][3] == 0.f && - - mMatrix[3][0] == 0.f && - mMatrix[3][1] == 0.f && - mMatrix[3][2] == 0.f && - mMatrix[3][3] == 1.f; + return + mMatrix[0][0] == 1.f && + mMatrix[0][1] == 0.f && + mMatrix[0][2] == 0.f && + mMatrix[0][3] == 0.f && + + mMatrix[1][0] == 0.f && + mMatrix[1][1] == 1.f && + mMatrix[1][2] == 0.f && + mMatrix[1][3] == 0.f && + + mMatrix[2][0] == 0.f && + mMatrix[2][1] == 0.f && + mMatrix[2][2] == 1.f && + mMatrix[2][3] == 0.f && + + mMatrix[3][0] == 0.f && + mMatrix[3][1] == 0.f && + mMatrix[3][2] == 0.f && + mMatrix[3][3] == 1.f; } /* inline LLMatrix4 operator*(const LLMatrix4 &a, const LLMatrix4 &b) { - U32 i, j; - LLMatrix4 mat; - for (i = 0; i < NUM_VALUES_IN_MAT4; i++) - { - for (j = 0; j < NUM_VALUES_IN_MAT4; j++) - { - mat.mMatrix[j][i] = a.mMatrix[j][0] * b.mMatrix[0][i] + - a.mMatrix[j][1] * b.mMatrix[1][i] + - a.mMatrix[j][2] * b.mMatrix[2][i] + - a.mMatrix[j][3] * b.mMatrix[3][i]; - } - } - return mat; + U32 i, j; + LLMatrix4 mat; + for (i = 0; i < NUM_VALUES_IN_MAT4; i++) + { + for (j = 0; j < NUM_VALUES_IN_MAT4; j++) + { + mat.mMatrix[j][i] = a.mMatrix[j][0] * b.mMatrix[0][i] + + a.mMatrix[j][1] * b.mMatrix[1][i] + + a.mMatrix[j][2] * b.mMatrix[2][i] + + a.mMatrix[j][3] * b.mMatrix[3][i]; + } + } + return mat; } */ inline const LLMatrix4& operator*=(LLMatrix4 &a, const LLMatrix4 &b) { - U32 i, j; - LLMatrix4 mat; - for (i = 0; i < NUM_VALUES_IN_MAT4; i++) - { - for (j = 0; j < NUM_VALUES_IN_MAT4; j++) - { - mat.mMatrix[j][i] = a.mMatrix[j][0] * b.mMatrix[0][i] + - a.mMatrix[j][1] * b.mMatrix[1][i] + - a.mMatrix[j][2] * b.mMatrix[2][i] + - a.mMatrix[j][3] * b.mMatrix[3][i]; - } - } - a = mat; - return a; + U32 i, j; + LLMatrix4 mat; + for (i = 0; i < NUM_VALUES_IN_MAT4; i++) + { + for (j = 0; j < NUM_VALUES_IN_MAT4; j++) + { + mat.mMatrix[j][i] = a.mMatrix[j][0] * b.mMatrix[0][i] + + a.mMatrix[j][1] * b.mMatrix[1][i] + + a.mMatrix[j][2] * b.mMatrix[2][i] + + a.mMatrix[j][3] * b.mMatrix[3][i]; + } + } + a = mat; + return a; } inline const LLMatrix4& operator*=(LLMatrix4 &a, const F32 &b) { - U32 i, j; - LLMatrix4 mat; - for (i = 0; i < NUM_VALUES_IN_MAT4; i++) - { - for (j = 0; j < NUM_VALUES_IN_MAT4; j++) - { - mat.mMatrix[j][i] = a.mMatrix[j][i] * b; - } - } - a = mat; - return a; + U32 i, j; + LLMatrix4 mat; + for (i = 0; i < NUM_VALUES_IN_MAT4; i++) + { + for (j = 0; j < NUM_VALUES_IN_MAT4; j++) + { + mat.mMatrix[j][i] = a.mMatrix[j][i] * b; + } + } + a = mat; + return a; } inline const LLMatrix4& operator+=(LLMatrix4 &a, const LLMatrix4 &b) { - LLMatrix4 mat; - U32 i, j; - for (i = 0; i < NUM_VALUES_IN_MAT4; i++) - { - for (j = 0; j < NUM_VALUES_IN_MAT4; j++) - { - mat.mMatrix[j][i] = a.mMatrix[j][i] + b.mMatrix[j][i]; - } - } - a = mat; - return a; + LLMatrix4 mat; + U32 i, j; + for (i = 0; i < NUM_VALUES_IN_MAT4; i++) + { + for (j = 0; j < NUM_VALUES_IN_MAT4; j++) + { + mat.mMatrix[j][i] = a.mMatrix[j][i] + b.mMatrix[j][i]; + } + } + a = mat; + return a; } inline const LLMatrix4& operator-=(LLMatrix4 &a, const LLMatrix4 &b) { - LLMatrix4 mat; - U32 i, j; - for (i = 0; i < NUM_VALUES_IN_MAT4; i++) - { - for (j = 0; j < NUM_VALUES_IN_MAT4; j++) - { - mat.mMatrix[j][i] = a.mMatrix[j][i] - b.mMatrix[j][i]; - } - } - a = mat; - return a; + LLMatrix4 mat; + U32 i, j; + for (i = 0; i < NUM_VALUES_IN_MAT4; i++) + { + for (j = 0; j < NUM_VALUES_IN_MAT4; j++) + { + mat.mMatrix[j][i] = a.mMatrix[j][i] - b.mMatrix[j][i]; + } + } + a = mat; + return a; } // Operates "to the left" on row-vector a @@ -380,24 +380,24 @@ inline const LLMatrix4& operator-=(LLMatrix4 &a, const LLMatrix4 &b) // due to software skinning in LLViewerJointMesh::updateGeometry(). JC inline const LLVector3 operator*(const LLVector3 &a, const LLMatrix4 &b) { - // This is better than making a temporary LLVector3. This eliminates an - // unnecessary LLVector3() constructor and also helps the compiler to - // realize that the output floats do not alias the input floats, hence - // eliminating redundant loads of a.mV[0], etc. JC - return LLVector3(a.mV[VX] * b.mMatrix[VX][VX] + - a.mV[VY] * b.mMatrix[VY][VX] + - a.mV[VZ] * b.mMatrix[VZ][VX] + - b.mMatrix[VW][VX], - - a.mV[VX] * b.mMatrix[VX][VY] + - a.mV[VY] * b.mMatrix[VY][VY] + - a.mV[VZ] * b.mMatrix[VZ][VY] + - b.mMatrix[VW][VY], - - a.mV[VX] * b.mMatrix[VX][VZ] + - a.mV[VY] * b.mMatrix[VY][VZ] + - a.mV[VZ] * b.mMatrix[VZ][VZ] + - b.mMatrix[VW][VZ]); + // This is better than making a temporary LLVector3. This eliminates an + // unnecessary LLVector3() constructor and also helps the compiler to + // realize that the output floats do not alias the input floats, hence + // eliminating redundant loads of a.mV[0], etc. JC + return LLVector3(a.mV[VX] * b.mMatrix[VX][VX] + + a.mV[VY] * b.mMatrix[VY][VX] + + a.mV[VZ] * b.mMatrix[VZ][VX] + + b.mMatrix[VW][VX], + + a.mV[VX] * b.mMatrix[VX][VY] + + a.mV[VY] * b.mMatrix[VY][VY] + + a.mV[VZ] * b.mMatrix[VZ][VY] + + b.mMatrix[VW][VY], + + a.mV[VX] * b.mMatrix[VX][VZ] + + a.mV[VY] * b.mMatrix[VY][VZ] + + a.mV[VZ] * b.mMatrix[VZ][VZ] + + b.mMatrix[VW][VZ]); } #endif diff --git a/indra/llmath/raytrace.cpp b/indra/llmath/raytrace.cpp index 117ba2369e..893bf1fc70 100644 --- a/indra/llmath/raytrace.cpp +++ b/indra/llmath/raytrace.cpp @@ -1,25 +1,25 @@ -/** +/** * @file raytrace.cpp * @brief Functions called by box object scripts. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -35,1235 +35,1235 @@ bool line_plane(const LLVector3 &line_point, const LLVector3 &line_direction, - const LLVector3 &plane_point, const LLVector3 plane_normal, - LLVector3 &intersection) + const LLVector3 &plane_point, const LLVector3 plane_normal, + LLVector3 &intersection) { - F32 N = line_direction * plane_normal; - if (0.0f == N) - { - // line is perpendicular to plane normal - // so it is either entirely on plane, or not on plane at all - return false; - } - // Ax + By, + Cz + D = 0 - // D = - (plane_point * plane_normal) - // N = line_direction * plane_normal - // intersection = line_point - ((D + plane_normal * line_point) / N) * line_direction - intersection = line_point - ((plane_normal * line_point - plane_point * plane_normal) / N) * line_direction; - return true; + F32 N = line_direction * plane_normal; + if (0.0f == N) + { + // line is perpendicular to plane normal + // so it is either entirely on plane, or not on plane at all + return false; + } + // Ax + By, + Cz + D = 0 + // D = - (plane_point * plane_normal) + // N = line_direction * plane_normal + // intersection = line_point - ((D + plane_normal * line_point) / N) * line_direction + intersection = line_point - ((plane_normal * line_point - plane_point * plane_normal) / N) * line_direction; + return true; } bool ray_plane(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &plane_point, const LLVector3 plane_normal, - LLVector3 &intersection) + const LLVector3 &plane_point, const LLVector3 plane_normal, + LLVector3 &intersection) { - F32 N = ray_direction * plane_normal; - if (0.0f == N) - { - // ray is perpendicular to plane normal - // so it is either entirely on plane, or not on plane at all - return false; - } - // Ax + By, + Cz + D = 0 - // D = - (plane_point * plane_normal) - // N = ray_direction * plane_normal - // intersection = ray_point - ((D + plane_normal * ray_point) / N) * ray_direction - F32 alpha = -(plane_normal * ray_point - plane_point * plane_normal) / N; - if (alpha < 0.0f) - { - // ray points away from plane - return false; - } - intersection = ray_point + alpha * ray_direction; - return true; + F32 N = ray_direction * plane_normal; + if (0.0f == N) + { + // ray is perpendicular to plane normal + // so it is either entirely on plane, or not on plane at all + return false; + } + // Ax + By, + Cz + D = 0 + // D = - (plane_point * plane_normal) + // N = ray_direction * plane_normal + // intersection = ray_point - ((D + plane_normal * ray_point) / N) * ray_direction + F32 alpha = -(plane_normal * ray_point - plane_point * plane_normal) / N; + if (alpha < 0.0f) + { + // ray points away from plane + return false; + } + intersection = ray_point + alpha * ray_direction; + return true; } bool ray_circle(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &circle_center, const LLVector3 plane_normal, F32 circle_radius, - LLVector3 &intersection) + const LLVector3 &circle_center, const LLVector3 plane_normal, F32 circle_radius, + LLVector3 &intersection) { - if (ray_plane(ray_point, ray_direction, circle_center, plane_normal, intersection)) - { - if (circle_radius >= (intersection - circle_center).magVec()) - { - return true; - } - } - return false; + if (ray_plane(ray_point, ray_direction, circle_center, plane_normal, intersection)) + { + if (circle_radius >= (intersection - circle_center).magVec()) + { + return true; + } + } + return false; } bool ray_triangle(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2, - LLVector3 &intersection, LLVector3 &intersection_normal) + const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2, + LLVector3 &intersection, LLVector3 &intersection_normal) { - LLVector3 side_01 = point_1 - point_0; - LLVector3 side_12 = point_2 - point_1; - - intersection_normal = side_01 % side_12; - intersection_normal.normVec(); - - if (ray_plane(ray_point, ray_direction, point_0, intersection_normal, intersection)) - { - LLVector3 side_20 = point_0 - point_2; - if (intersection_normal * (side_01 % (intersection - point_0)) >= 0.0f && - intersection_normal * (side_12 % (intersection - point_1)) >= 0.0f && - intersection_normal * (side_20 % (intersection - point_2)) >= 0.0f) - { - return true; - } - } - return false; + LLVector3 side_01 = point_1 - point_0; + LLVector3 side_12 = point_2 - point_1; + + intersection_normal = side_01 % side_12; + intersection_normal.normVec(); + + if (ray_plane(ray_point, ray_direction, point_0, intersection_normal, intersection)) + { + LLVector3 side_20 = point_0 - point_2; + if (intersection_normal * (side_01 % (intersection - point_0)) >= 0.0f && + intersection_normal * (side_12 % (intersection - point_1)) >= 0.0f && + intersection_normal * (side_20 % (intersection - point_2)) >= 0.0f) + { + return true; + } + } + return false; } // assumes a parallelogram bool ray_quadrangle(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2, - LLVector3 &intersection, LLVector3 &intersection_normal) + const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2, + LLVector3 &intersection, LLVector3 &intersection_normal) { - LLVector3 side_01 = point_1 - point_0; - LLVector3 side_12 = point_2 - point_1; - - intersection_normal = side_01 % side_12; - intersection_normal.normVec(); - - if (ray_plane(ray_point, ray_direction, point_0, intersection_normal, intersection)) - { - LLVector3 point_3 = point_0 + (side_12); - LLVector3 side_23 = point_3 - point_2; - LLVector3 side_30 = point_0 - point_3; - if (intersection_normal * (side_01 % (intersection - point_0)) >= 0.0f && - intersection_normal * (side_12 % (intersection - point_1)) >= 0.0f && - intersection_normal * (side_23 % (intersection - point_2)) >= 0.0f && - intersection_normal * (side_30 % (intersection - point_3)) >= 0.0f) - { - return true; - } - } - return false; + LLVector3 side_01 = point_1 - point_0; + LLVector3 side_12 = point_2 - point_1; + + intersection_normal = side_01 % side_12; + intersection_normal.normVec(); + + if (ray_plane(ray_point, ray_direction, point_0, intersection_normal, intersection)) + { + LLVector3 point_3 = point_0 + (side_12); + LLVector3 side_23 = point_3 - point_2; + LLVector3 side_30 = point_0 - point_3; + if (intersection_normal * (side_01 % (intersection - point_0)) >= 0.0f && + intersection_normal * (side_12 % (intersection - point_1)) >= 0.0f && + intersection_normal * (side_23 % (intersection - point_2)) >= 0.0f && + intersection_normal * (side_30 % (intersection - point_3)) >= 0.0f) + { + return true; + } + } + return false; } bool ray_sphere(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &sphere_center, F32 sphere_radius, - LLVector3 &intersection, LLVector3 &intersection_normal) + const LLVector3 &sphere_center, F32 sphere_radius, + LLVector3 &intersection, LLVector3 &intersection_normal) { - LLVector3 ray_to_sphere = sphere_center - ray_point; - F32 dot = ray_to_sphere * ray_direction; - - LLVector3 closest_approach = dot * ray_direction - ray_to_sphere; - - F32 shortest_distance = closest_approach.magVecSquared(); - F32 radius_squared = sphere_radius * sphere_radius; - if (shortest_distance > radius_squared) - { - return false; - } - - F32 half_chord = (F32) sqrt(radius_squared - shortest_distance); - closest_approach = sphere_center + closest_approach; // closest_approach now in absolute coordinates - intersection = closest_approach + half_chord * ray_direction; - dot = ray_direction * (intersection - ray_point); - if (dot < 0.0f) - { - // ray shoots away from sphere and is not inside it - return false; - } - - shortest_distance = ray_direction * ((closest_approach - half_chord * ray_direction) - ray_point); - if (shortest_distance > 0.0f) - { - // ray enters sphere - intersection = intersection - (2.0f * half_chord) * ray_direction; - } - else - { - // do nothing - // ray starts inside sphere and intersects as it leaves the sphere - } - - intersection_normal = intersection - sphere_center; - if (sphere_radius > 0.0f) - { - intersection_normal *= 1.0f / sphere_radius; - } - else - { - intersection_normal.setVec(0.0f, 0.0f, 0.0f); - } - - return true; + LLVector3 ray_to_sphere = sphere_center - ray_point; + F32 dot = ray_to_sphere * ray_direction; + + LLVector3 closest_approach = dot * ray_direction - ray_to_sphere; + + F32 shortest_distance = closest_approach.magVecSquared(); + F32 radius_squared = sphere_radius * sphere_radius; + if (shortest_distance > radius_squared) + { + return false; + } + + F32 half_chord = (F32) sqrt(radius_squared - shortest_distance); + closest_approach = sphere_center + closest_approach; // closest_approach now in absolute coordinates + intersection = closest_approach + half_chord * ray_direction; + dot = ray_direction * (intersection - ray_point); + if (dot < 0.0f) + { + // ray shoots away from sphere and is not inside it + return false; + } + + shortest_distance = ray_direction * ((closest_approach - half_chord * ray_direction) - ray_point); + if (shortest_distance > 0.0f) + { + // ray enters sphere + intersection = intersection - (2.0f * half_chord) * ray_direction; + } + else + { + // do nothing + // ray starts inside sphere and intersects as it leaves the sphere + } + + intersection_normal = intersection - sphere_center; + if (sphere_radius > 0.0f) + { + intersection_normal *= 1.0f / sphere_radius; + } + else + { + intersection_normal.setVec(0.0f, 0.0f, 0.0f); + } + + return true; } bool ray_cylinder(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &cyl_center, const LLVector3 &cyl_scale, const LLQuaternion &cyl_rotation, - LLVector3 &intersection, LLVector3 &intersection_normal) + const LLVector3 &cyl_center, const LLVector3 &cyl_scale, const LLQuaternion &cyl_rotation, + LLVector3 &intersection, LLVector3 &intersection_normal) { - // calculate the centers of the cylinder caps in the absolute frame - LLVector3 cyl_top(0.0f, 0.0f, 0.5f * cyl_scale.mV[VZ]); - LLVector3 cyl_bottom(0.0f, 0.0f, -cyl_top.mV[VZ]); - cyl_top = (cyl_top * cyl_rotation) + cyl_center; - cyl_bottom = (cyl_bottom * cyl_rotation) + cyl_center; - - // we only handle cylinders with circular cross-sections at the moment - F32 cyl_radius = 0.5f * llmax(cyl_scale.mV[VX], cyl_scale.mV[VY]); // HACK until scaled cylinders are supported - - // This implementation is based on the intcyl() function from Graphics_Gems_IV, page 361 - LLVector3 cyl_axis; // axis direction (bottom toward top) - LLVector3 ray_to_cyl; // ray_point to cyl_top - F32 shortest_distance; // shortest distance from ray to axis - F32 cyl_length; - LLVector3 shortest_direction; - LLVector3 temp_vector; - - cyl_axis = cyl_bottom - cyl_top; - cyl_length = cyl_axis.normVec(); - ray_to_cyl = ray_point - cyl_bottom; - shortest_direction = ray_direction % cyl_axis; - shortest_distance = shortest_direction.normVec(); // recycle shortest_distance - - // check for ray parallel to cylinder axis - if (0.0f == shortest_distance) - { - // ray is parallel to cylinder axis - temp_vector = ray_to_cyl - (ray_to_cyl * cyl_axis) * cyl_axis; - shortest_distance = temp_vector.magVec(); - if (shortest_distance <= cyl_radius) - { - shortest_distance = ray_to_cyl * cyl_axis; - F32 dot = ray_direction * cyl_axis; - - if (shortest_distance > 0.0) - { - if (dot > 0.0f) - { - // ray points away from cylinder bottom - return false; - } - // ray hit bottom of cylinder from outside - intersection = ray_point - shortest_distance * cyl_axis; - intersection_normal = cyl_axis; - - } - else if (shortest_distance > -cyl_length) - { - // ray starts inside cylinder - if (dot < 0.0f) - { - // ray hit top from inside - intersection = ray_point - (cyl_length + shortest_distance) * cyl_axis; - intersection_normal = -cyl_axis; - } - else - { - // ray hit bottom from inside - intersection = ray_point - shortest_distance * cyl_axis; - intersection_normal = cyl_axis; - } - } - else - { - if (dot < 0.0f) - { - // ray points away from cylinder bottom - return false; - } - // ray hit top from outside - intersection = ray_point - (shortest_distance + cyl_length) * cyl_axis; - intersection_normal = -cyl_axis; - } - return true; - } - return false; - } - - // check for intersection with infinite cylinder - shortest_distance = (F32) fabs(ray_to_cyl * shortest_direction); - if (shortest_distance <= cyl_radius) - { - F32 dist_to_closest_point; // dist from ray_point to closest_point - F32 half_chord_length; // half length of intersection chord - F32 in, out; // distances to entering/exiting points - temp_vector = ray_to_cyl % cyl_axis; - dist_to_closest_point = - (temp_vector * shortest_direction); - temp_vector = shortest_direction % cyl_axis; - temp_vector.normVec(); - half_chord_length = (F32) fabs( sqrt(cyl_radius*cyl_radius - shortest_distance * shortest_distance) / - (ray_direction * temp_vector) ); - - out = dist_to_closest_point + half_chord_length; // dist to exiting point - if (out < 0.0f) - { - // cylinder is behind the ray, so we return false - return false; - } - - in = dist_to_closest_point - half_chord_length; // dist to entering point - if (in < 0.0f) - { - // ray_point is inside the cylinder - // so we store the exiting intersection - intersection = ray_point + out * ray_direction; - shortest_distance = out; - } - else - { - // ray hit cylinder from outside - // so we store the entering intersection - intersection = ray_point + in * ray_direction; - shortest_distance = in; - } - - // calculate the normal at intersection - if (0.0f == cyl_radius) - { - intersection_normal.setVec(0.0f, 0.0f, 0.0f); - } - else - { - temp_vector = intersection - cyl_bottom; - intersection_normal = temp_vector - (temp_vector * cyl_axis) * cyl_axis; - intersection_normal.normVec(); - } - - // check for intersection with end caps - // calculate intersection of ray and top plane - if (line_plane(ray_point, ray_direction, cyl_top, -cyl_axis, temp_vector)) // NOTE side-effect: changing temp_vector - { - shortest_distance = (temp_vector - ray_point).magVec(); - if ( (ray_direction * cyl_axis) > 0.0f) - { - // ray potentially enters the cylinder at top - if (shortest_distance > out) - { - // ray missed the finite cylinder - return false; - } - if (shortest_distance > in) - { - // ray intersects cylinder at top plane - intersection = temp_vector; - intersection_normal = -cyl_axis; - return true; - } - } - else - { - // ray potentially exits the cylinder at top - if (shortest_distance < in) - { - // missed the finite cylinder - return false; - } - } - - // calculate intersection of ray and bottom plane - line_plane(ray_point, ray_direction, cyl_bottom, cyl_axis, temp_vector); // NOTE side-effect: changing temp_vector - shortest_distance = (temp_vector - ray_point).magVec(); - if ( (ray_direction * cyl_axis) < 0.0) - { - // ray potentially enters the cylinder at bottom - if (shortest_distance > out) - { - // ray missed the finite cylinder - return false; - } - if (shortest_distance > in) - { - // ray intersects cylinder at bottom plane - intersection = temp_vector; - intersection_normal = cyl_axis; - return true; - } - } - else - { - // ray potentially exits the cylinder at bottom - if (shortest_distance < in) - { - // ray missed the finite cylinder - return false; - } - } - - } - else - { - // ray is parallel to end cap planes - temp_vector = cyl_bottom - ray_point; - shortest_distance = temp_vector * cyl_axis; - if (shortest_distance < 0.0f || shortest_distance > cyl_length) - { - // ray missed finite cylinder - return false; - } - } - - return true; - } - - return false; + // calculate the centers of the cylinder caps in the absolute frame + LLVector3 cyl_top(0.0f, 0.0f, 0.5f * cyl_scale.mV[VZ]); + LLVector3 cyl_bottom(0.0f, 0.0f, -cyl_top.mV[VZ]); + cyl_top = (cyl_top * cyl_rotation) + cyl_center; + cyl_bottom = (cyl_bottom * cyl_rotation) + cyl_center; + + // we only handle cylinders with circular cross-sections at the moment + F32 cyl_radius = 0.5f * llmax(cyl_scale.mV[VX], cyl_scale.mV[VY]); // HACK until scaled cylinders are supported + + // This implementation is based on the intcyl() function from Graphics_Gems_IV, page 361 + LLVector3 cyl_axis; // axis direction (bottom toward top) + LLVector3 ray_to_cyl; // ray_point to cyl_top + F32 shortest_distance; // shortest distance from ray to axis + F32 cyl_length; + LLVector3 shortest_direction; + LLVector3 temp_vector; + + cyl_axis = cyl_bottom - cyl_top; + cyl_length = cyl_axis.normVec(); + ray_to_cyl = ray_point - cyl_bottom; + shortest_direction = ray_direction % cyl_axis; + shortest_distance = shortest_direction.normVec(); // recycle shortest_distance + + // check for ray parallel to cylinder axis + if (0.0f == shortest_distance) + { + // ray is parallel to cylinder axis + temp_vector = ray_to_cyl - (ray_to_cyl * cyl_axis) * cyl_axis; + shortest_distance = temp_vector.magVec(); + if (shortest_distance <= cyl_radius) + { + shortest_distance = ray_to_cyl * cyl_axis; + F32 dot = ray_direction * cyl_axis; + + if (shortest_distance > 0.0) + { + if (dot > 0.0f) + { + // ray points away from cylinder bottom + return false; + } + // ray hit bottom of cylinder from outside + intersection = ray_point - shortest_distance * cyl_axis; + intersection_normal = cyl_axis; + + } + else if (shortest_distance > -cyl_length) + { + // ray starts inside cylinder + if (dot < 0.0f) + { + // ray hit top from inside + intersection = ray_point - (cyl_length + shortest_distance) * cyl_axis; + intersection_normal = -cyl_axis; + } + else + { + // ray hit bottom from inside + intersection = ray_point - shortest_distance * cyl_axis; + intersection_normal = cyl_axis; + } + } + else + { + if (dot < 0.0f) + { + // ray points away from cylinder bottom + return false; + } + // ray hit top from outside + intersection = ray_point - (shortest_distance + cyl_length) * cyl_axis; + intersection_normal = -cyl_axis; + } + return true; + } + return false; + } + + // check for intersection with infinite cylinder + shortest_distance = (F32) fabs(ray_to_cyl * shortest_direction); + if (shortest_distance <= cyl_radius) + { + F32 dist_to_closest_point; // dist from ray_point to closest_point + F32 half_chord_length; // half length of intersection chord + F32 in, out; // distances to entering/exiting points + temp_vector = ray_to_cyl % cyl_axis; + dist_to_closest_point = - (temp_vector * shortest_direction); + temp_vector = shortest_direction % cyl_axis; + temp_vector.normVec(); + half_chord_length = (F32) fabs( sqrt(cyl_radius*cyl_radius - shortest_distance * shortest_distance) / + (ray_direction * temp_vector) ); + + out = dist_to_closest_point + half_chord_length; // dist to exiting point + if (out < 0.0f) + { + // cylinder is behind the ray, so we return false + return false; + } + + in = dist_to_closest_point - half_chord_length; // dist to entering point + if (in < 0.0f) + { + // ray_point is inside the cylinder + // so we store the exiting intersection + intersection = ray_point + out * ray_direction; + shortest_distance = out; + } + else + { + // ray hit cylinder from outside + // so we store the entering intersection + intersection = ray_point + in * ray_direction; + shortest_distance = in; + } + + // calculate the normal at intersection + if (0.0f == cyl_radius) + { + intersection_normal.setVec(0.0f, 0.0f, 0.0f); + } + else + { + temp_vector = intersection - cyl_bottom; + intersection_normal = temp_vector - (temp_vector * cyl_axis) * cyl_axis; + intersection_normal.normVec(); + } + + // check for intersection with end caps + // calculate intersection of ray and top plane + if (line_plane(ray_point, ray_direction, cyl_top, -cyl_axis, temp_vector)) // NOTE side-effect: changing temp_vector + { + shortest_distance = (temp_vector - ray_point).magVec(); + if ( (ray_direction * cyl_axis) > 0.0f) + { + // ray potentially enters the cylinder at top + if (shortest_distance > out) + { + // ray missed the finite cylinder + return false; + } + if (shortest_distance > in) + { + // ray intersects cylinder at top plane + intersection = temp_vector; + intersection_normal = -cyl_axis; + return true; + } + } + else + { + // ray potentially exits the cylinder at top + if (shortest_distance < in) + { + // missed the finite cylinder + return false; + } + } + + // calculate intersection of ray and bottom plane + line_plane(ray_point, ray_direction, cyl_bottom, cyl_axis, temp_vector); // NOTE side-effect: changing temp_vector + shortest_distance = (temp_vector - ray_point).magVec(); + if ( (ray_direction * cyl_axis) < 0.0) + { + // ray potentially enters the cylinder at bottom + if (shortest_distance > out) + { + // ray missed the finite cylinder + return false; + } + if (shortest_distance > in) + { + // ray intersects cylinder at bottom plane + intersection = temp_vector; + intersection_normal = cyl_axis; + return true; + } + } + else + { + // ray potentially exits the cylinder at bottom + if (shortest_distance < in) + { + // ray missed the finite cylinder + return false; + } + } + + } + else + { + // ray is parallel to end cap planes + temp_vector = cyl_bottom - ray_point; + shortest_distance = temp_vector * cyl_axis; + if (shortest_distance < 0.0f || shortest_distance > cyl_length) + { + // ray missed finite cylinder + return false; + } + } + + return true; + } + + return false; } -U32 ray_box(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &box_center, const LLVector3 &box_scale, const LLQuaternion &box_rotation, - LLVector3 &intersection, LLVector3 &intersection_normal) +U32 ray_box(const LLVector3 &ray_point, const LLVector3 &ray_direction, + const LLVector3 &box_center, const LLVector3 &box_scale, const LLQuaternion &box_rotation, + LLVector3 &intersection, LLVector3 &intersection_normal) { - // Need to rotate into box frame - LLQuaternion into_box_frame(box_rotation); // rotates things from box frame to absolute - into_box_frame.conjQuat(); // now rotates things into box frame - LLVector3 line_point = (ray_point - box_center) * into_box_frame; - LLVector3 line_direction = ray_direction * into_box_frame; - - // Suppose we have a plane: Ax + By + Cz + D = 0 - // then, assuming [A, B, C] is a unit vector: - // - // plane_normal = [A, B, C] - // D = - (plane_normal * plane_point) - // - // Suppose we have a line: X = line_point + alpha * line_direction - // - // the intersection of the plane and line determines alpha - // - // alpha = - (D + plane_normal * line_point) / (plane_normal * line_direction) - - LLVector3 line_plane_intersection; - - F32 pointX = line_point.mV[VX]; - F32 pointY = line_point.mV[VY]; - F32 pointZ = line_point.mV[VZ]; - - F32 dirX = line_direction.mV[VX]; - F32 dirY = line_direction.mV[VY]; - F32 dirZ = line_direction.mV[VZ]; - - // we'll be using the half-scales of the box - F32 boxX = 0.5f * box_scale.mV[VX]; - F32 boxY = 0.5f * box_scale.mV[VY]; - F32 boxZ = 0.5f * box_scale.mV[VZ]; - - // check to see if line_point is OUTSIDE the box - if (pointX < -boxX || - pointX > boxX || - pointY < -boxY || - pointY > boxY || - pointZ < -boxZ || - pointZ > boxZ) - { - // -------------- point is OUTSIDE the box ---------------- - - // front - if (pointX > 0.0f && dirX < 0.0f) - { - // plane_normal = [ 1, 0, 0] - // plane_normal*line_point = pointX - // plane_normal*line_direction = dirX - // D = -boxX - // alpha = - (-boxX + pointX) / dirX - line_plane_intersection = line_point - ((pointX - boxX) / dirX) * line_direction; - if (line_plane_intersection.mV[VY] < boxY && - line_plane_intersection.mV[VY] > -boxY && - line_plane_intersection.mV[VZ] < boxZ && - line_plane_intersection.mV[VZ] > -boxZ ) - { - intersection = (line_plane_intersection * box_rotation) + box_center; - intersection_normal = LLVector3(1.0f, 0.0f, 0.0f) * box_rotation; - return FRONT_SIDE; - } - } - - // back - if (pointX < 0.0f && dirX > 0.0f) - { - // plane_normal = [ -1, 0, 0] - // plane_normal*line_point = -pX - // plane_normal*line_direction = -direction.mV[VX] - // D = -bX - // alpha = - (-bX - pX) / (-dirX) - line_plane_intersection = line_point - ((boxX + pointX)/ dirX) * line_direction; - if (line_plane_intersection.mV[VY] < boxY && - line_plane_intersection.mV[VY] > -boxY && - line_plane_intersection.mV[VZ] < boxZ && - line_plane_intersection.mV[VZ] > -boxZ ) - { - intersection = (line_plane_intersection * box_rotation) + box_center; - intersection_normal = LLVector3(-1.0f, 0.0f, 0.0f) * box_rotation; - return BACK_SIDE; - } - } - - // left - if (pointY > 0.0f && dirY < 0.0f) - { - // plane_normal = [0, 1, 0] - // plane_normal*line_point = pointY - // plane_normal*line_direction = dirY - // D = -boxY - // alpha = - (-boxY + pointY) / dirY - line_plane_intersection = line_point + ((boxY - pointY)/dirY) * line_direction; - - if (line_plane_intersection.mV[VX] < boxX && - line_plane_intersection.mV[VX] > -boxX && - line_plane_intersection.mV[VZ] < boxZ && - line_plane_intersection.mV[VZ] > -boxZ ) - { - intersection = (line_plane_intersection * box_rotation) + box_center; - intersection_normal = LLVector3(0.0f, 1.0f, 0.0f) * box_rotation; - return LEFT_SIDE; - } - } - - // right - if (pointY < 0.0f && dirY > 0.0f) - { - // plane_normal = [0, -1, 0] - // plane_normal*line_point = -pointY - // plane_normal*line_direction = -dirY - // D = -boxY - // alpha = - (-boxY - pointY) / (-dirY) - line_plane_intersection = line_point - ((boxY + pointY)/dirY) * line_direction; - if (line_plane_intersection.mV[VX] < boxX && - line_plane_intersection.mV[VX] > -boxX && - line_plane_intersection.mV[VZ] < boxZ && - line_plane_intersection.mV[VZ] > -boxZ ) - { - intersection = (line_plane_intersection * box_rotation) + box_center; - intersection_normal = LLVector3(0.0f, -1.0f, 0.0f) * box_rotation; - return RIGHT_SIDE; - } - } - - // top - if (pointZ > 0.0f && dirZ < 0.0f) - { - // plane_normal = [0, 0, 1] - // plane_normal*line_point = pointZ - // plane_normal*line_direction = dirZ - // D = -boxZ - // alpha = - (-boxZ + pointZ) / dirZ - line_plane_intersection = line_point - ((pointZ - boxZ)/dirZ) * line_direction; - if (line_plane_intersection.mV[VX] < boxX && - line_plane_intersection.mV[VX] > -boxX && - line_plane_intersection.mV[VY] < boxY && - line_plane_intersection.mV[VY] > -boxY ) - { - intersection = (line_plane_intersection * box_rotation) + box_center; - intersection_normal = LLVector3(0.0f, 0.0f, 1.0f) * box_rotation; - return TOP_SIDE; - } - } - - // bottom - if (pointZ < 0.0f && dirZ > 0.0f) - { - // plane_normal = [0, 0, -1] - // plane_normal*line_point = -pointZ - // plane_normal*line_direction = -dirZ - // D = -boxZ - // alpha = - (-boxZ - pointZ) / (-dirZ) - line_plane_intersection = line_point - ((boxZ + pointZ)/dirZ) * line_direction; - if (line_plane_intersection.mV[VX] < boxX && - line_plane_intersection.mV[VX] > -boxX && - line_plane_intersection.mV[VY] < boxY && - line_plane_intersection.mV[VY] > -boxY ) - { - intersection = (line_plane_intersection * box_rotation) + box_center; - intersection_normal = LLVector3(0.0f, 0.0f, -1.0f) * box_rotation; - return BOTTOM_SIDE; - } - } - return NO_SIDE; - } - - // -------------- point is INSIDE the box ---------------- - - // front - if (dirX > 0.0f) - { - // plane_normal = [ 1, 0, 0] - // plane_normal*line_point = pointX - // plane_normal*line_direction = dirX - // D = -boxX - // alpha = - (-boxX + pointX) / dirX - line_plane_intersection = line_point - ((pointX - boxX) / dirX) * line_direction; - if (line_plane_intersection.mV[VY] < boxY && - line_plane_intersection.mV[VY] > -boxY && - line_plane_intersection.mV[VZ] < boxZ && - line_plane_intersection.mV[VZ] > -boxZ ) - { - intersection = (line_plane_intersection * box_rotation) + box_center; - intersection_normal = LLVector3(1.0f, 0.0f, 0.0f) * box_rotation; - return FRONT_SIDE; - } - } - - // back - if (dirX < 0.0f) - { - // plane_normal = [ -1, 0, 0] - // plane_normal*line_point = -pX - // plane_normal*line_direction = -direction.mV[VX] - // D = -bX - // alpha = - (-bX - pX) / (-dirX) - line_plane_intersection = line_point - ((boxX + pointX)/ dirX) * line_direction; - if (line_plane_intersection.mV[VY] < boxY && - line_plane_intersection.mV[VY] > -boxY && - line_plane_intersection.mV[VZ] < boxZ && - line_plane_intersection.mV[VZ] > -boxZ ) - { - intersection = (line_plane_intersection * box_rotation) + box_center; - intersection_normal = LLVector3(-1.0f, 0.0f, 0.0f) * box_rotation; - return BACK_SIDE; - } - } - - // left - if (dirY > 0.0f) - { - // plane_normal = [0, 1, 0] - // plane_normal*line_point = pointY - // plane_normal*line_direction = dirY - // D = -boxY - // alpha = - (-boxY + pointY) / dirY - line_plane_intersection = line_point + ((boxY - pointY)/dirY) * line_direction; - - if (line_plane_intersection.mV[VX] < boxX && - line_plane_intersection.mV[VX] > -boxX && - line_plane_intersection.mV[VZ] < boxZ && - line_plane_intersection.mV[VZ] > -boxZ ) - { - intersection = (line_plane_intersection * box_rotation) + box_center; - intersection_normal = LLVector3(0.0f, 1.0f, 0.0f) * box_rotation; - return LEFT_SIDE; - } - } - - // right - if (dirY < 0.0f) - { - // plane_normal = [0, -1, 0] - // plane_normal*line_point = -pointY - // plane_normal*line_direction = -dirY - // D = -boxY - // alpha = - (-boxY - pointY) / (-dirY) - line_plane_intersection = line_point - ((boxY + pointY)/dirY) * line_direction; - if (line_plane_intersection.mV[VX] < boxX && - line_plane_intersection.mV[VX] > -boxX && - line_plane_intersection.mV[VZ] < boxZ && - line_plane_intersection.mV[VZ] > -boxZ ) - { - intersection = (line_plane_intersection * box_rotation) + box_center; - intersection_normal = LLVector3(0.0f, -1.0f, 0.0f) * box_rotation; - return RIGHT_SIDE; - } - } - - // top - if (dirZ > 0.0f) - { - // plane_normal = [0, 0, 1] - // plane_normal*line_point = pointZ - // plane_normal*line_direction = dirZ - // D = -boxZ - // alpha = - (-boxZ + pointZ) / dirZ - line_plane_intersection = line_point - ((pointZ - boxZ)/dirZ) * line_direction; - if (line_plane_intersection.mV[VX] < boxX && - line_plane_intersection.mV[VX] > -boxX && - line_plane_intersection.mV[VY] < boxY && - line_plane_intersection.mV[VY] > -boxY ) - { - intersection = (line_plane_intersection * box_rotation) + box_center; - intersection_normal = LLVector3(0.0f, 0.0f, 1.0f) * box_rotation; - return TOP_SIDE; - } - } - - // bottom - if (dirZ < 0.0f) - { - // plane_normal = [0, 0, -1] - // plane_normal*line_point = -pointZ - // plane_normal*line_direction = -dirZ - // D = -boxZ - // alpha = - (-boxZ - pointZ) / (-dirZ) - line_plane_intersection = line_point - ((boxZ + pointZ)/dirZ) * line_direction; - if (line_plane_intersection.mV[VX] < boxX && - line_plane_intersection.mV[VX] > -boxX && - line_plane_intersection.mV[VY] < boxY && - line_plane_intersection.mV[VY] > -boxY ) - { - intersection = (line_plane_intersection * box_rotation) + box_center; - intersection_normal = LLVector3(0.0f, 0.0f, -1.0f) * box_rotation; - return BOTTOM_SIDE; - } - } - - // should never get here unless line instersects at tangent point on edge or corner - // however such cases will be EXTREMELY rare - return NO_SIDE; + // Need to rotate into box frame + LLQuaternion into_box_frame(box_rotation); // rotates things from box frame to absolute + into_box_frame.conjQuat(); // now rotates things into box frame + LLVector3 line_point = (ray_point - box_center) * into_box_frame; + LLVector3 line_direction = ray_direction * into_box_frame; + + // Suppose we have a plane: Ax + By + Cz + D = 0 + // then, assuming [A, B, C] is a unit vector: + // + // plane_normal = [A, B, C] + // D = - (plane_normal * plane_point) + // + // Suppose we have a line: X = line_point + alpha * line_direction + // + // the intersection of the plane and line determines alpha + // + // alpha = - (D + plane_normal * line_point) / (plane_normal * line_direction) + + LLVector3 line_plane_intersection; + + F32 pointX = line_point.mV[VX]; + F32 pointY = line_point.mV[VY]; + F32 pointZ = line_point.mV[VZ]; + + F32 dirX = line_direction.mV[VX]; + F32 dirY = line_direction.mV[VY]; + F32 dirZ = line_direction.mV[VZ]; + + // we'll be using the half-scales of the box + F32 boxX = 0.5f * box_scale.mV[VX]; + F32 boxY = 0.5f * box_scale.mV[VY]; + F32 boxZ = 0.5f * box_scale.mV[VZ]; + + // check to see if line_point is OUTSIDE the box + if (pointX < -boxX || + pointX > boxX || + pointY < -boxY || + pointY > boxY || + pointZ < -boxZ || + pointZ > boxZ) + { + // -------------- point is OUTSIDE the box ---------------- + + // front + if (pointX > 0.0f && dirX < 0.0f) + { + // plane_normal = [ 1, 0, 0] + // plane_normal*line_point = pointX + // plane_normal*line_direction = dirX + // D = -boxX + // alpha = - (-boxX + pointX) / dirX + line_plane_intersection = line_point - ((pointX - boxX) / dirX) * line_direction; + if (line_plane_intersection.mV[VY] < boxY && + line_plane_intersection.mV[VY] > -boxY && + line_plane_intersection.mV[VZ] < boxZ && + line_plane_intersection.mV[VZ] > -boxZ ) + { + intersection = (line_plane_intersection * box_rotation) + box_center; + intersection_normal = LLVector3(1.0f, 0.0f, 0.0f) * box_rotation; + return FRONT_SIDE; + } + } + + // back + if (pointX < 0.0f && dirX > 0.0f) + { + // plane_normal = [ -1, 0, 0] + // plane_normal*line_point = -pX + // plane_normal*line_direction = -direction.mV[VX] + // D = -bX + // alpha = - (-bX - pX) / (-dirX) + line_plane_intersection = line_point - ((boxX + pointX)/ dirX) * line_direction; + if (line_plane_intersection.mV[VY] < boxY && + line_plane_intersection.mV[VY] > -boxY && + line_plane_intersection.mV[VZ] < boxZ && + line_plane_intersection.mV[VZ] > -boxZ ) + { + intersection = (line_plane_intersection * box_rotation) + box_center; + intersection_normal = LLVector3(-1.0f, 0.0f, 0.0f) * box_rotation; + return BACK_SIDE; + } + } + + // left + if (pointY > 0.0f && dirY < 0.0f) + { + // plane_normal = [0, 1, 0] + // plane_normal*line_point = pointY + // plane_normal*line_direction = dirY + // D = -boxY + // alpha = - (-boxY + pointY) / dirY + line_plane_intersection = line_point + ((boxY - pointY)/dirY) * line_direction; + + if (line_plane_intersection.mV[VX] < boxX && + line_plane_intersection.mV[VX] > -boxX && + line_plane_intersection.mV[VZ] < boxZ && + line_plane_intersection.mV[VZ] > -boxZ ) + { + intersection = (line_plane_intersection * box_rotation) + box_center; + intersection_normal = LLVector3(0.0f, 1.0f, 0.0f) * box_rotation; + return LEFT_SIDE; + } + } + + // right + if (pointY < 0.0f && dirY > 0.0f) + { + // plane_normal = [0, -1, 0] + // plane_normal*line_point = -pointY + // plane_normal*line_direction = -dirY + // D = -boxY + // alpha = - (-boxY - pointY) / (-dirY) + line_plane_intersection = line_point - ((boxY + pointY)/dirY) * line_direction; + if (line_plane_intersection.mV[VX] < boxX && + line_plane_intersection.mV[VX] > -boxX && + line_plane_intersection.mV[VZ] < boxZ && + line_plane_intersection.mV[VZ] > -boxZ ) + { + intersection = (line_plane_intersection * box_rotation) + box_center; + intersection_normal = LLVector3(0.0f, -1.0f, 0.0f) * box_rotation; + return RIGHT_SIDE; + } + } + + // top + if (pointZ > 0.0f && dirZ < 0.0f) + { + // plane_normal = [0, 0, 1] + // plane_normal*line_point = pointZ + // plane_normal*line_direction = dirZ + // D = -boxZ + // alpha = - (-boxZ + pointZ) / dirZ + line_plane_intersection = line_point - ((pointZ - boxZ)/dirZ) * line_direction; + if (line_plane_intersection.mV[VX] < boxX && + line_plane_intersection.mV[VX] > -boxX && + line_plane_intersection.mV[VY] < boxY && + line_plane_intersection.mV[VY] > -boxY ) + { + intersection = (line_plane_intersection * box_rotation) + box_center; + intersection_normal = LLVector3(0.0f, 0.0f, 1.0f) * box_rotation; + return TOP_SIDE; + } + } + + // bottom + if (pointZ < 0.0f && dirZ > 0.0f) + { + // plane_normal = [0, 0, -1] + // plane_normal*line_point = -pointZ + // plane_normal*line_direction = -dirZ + // D = -boxZ + // alpha = - (-boxZ - pointZ) / (-dirZ) + line_plane_intersection = line_point - ((boxZ + pointZ)/dirZ) * line_direction; + if (line_plane_intersection.mV[VX] < boxX && + line_plane_intersection.mV[VX] > -boxX && + line_plane_intersection.mV[VY] < boxY && + line_plane_intersection.mV[VY] > -boxY ) + { + intersection = (line_plane_intersection * box_rotation) + box_center; + intersection_normal = LLVector3(0.0f, 0.0f, -1.0f) * box_rotation; + return BOTTOM_SIDE; + } + } + return NO_SIDE; + } + + // -------------- point is INSIDE the box ---------------- + + // front + if (dirX > 0.0f) + { + // plane_normal = [ 1, 0, 0] + // plane_normal*line_point = pointX + // plane_normal*line_direction = dirX + // D = -boxX + // alpha = - (-boxX + pointX) / dirX + line_plane_intersection = line_point - ((pointX - boxX) / dirX) * line_direction; + if (line_plane_intersection.mV[VY] < boxY && + line_plane_intersection.mV[VY] > -boxY && + line_plane_intersection.mV[VZ] < boxZ && + line_plane_intersection.mV[VZ] > -boxZ ) + { + intersection = (line_plane_intersection * box_rotation) + box_center; + intersection_normal = LLVector3(1.0f, 0.0f, 0.0f) * box_rotation; + return FRONT_SIDE; + } + } + + // back + if (dirX < 0.0f) + { + // plane_normal = [ -1, 0, 0] + // plane_normal*line_point = -pX + // plane_normal*line_direction = -direction.mV[VX] + // D = -bX + // alpha = - (-bX - pX) / (-dirX) + line_plane_intersection = line_point - ((boxX + pointX)/ dirX) * line_direction; + if (line_plane_intersection.mV[VY] < boxY && + line_plane_intersection.mV[VY] > -boxY && + line_plane_intersection.mV[VZ] < boxZ && + line_plane_intersection.mV[VZ] > -boxZ ) + { + intersection = (line_plane_intersection * box_rotation) + box_center; + intersection_normal = LLVector3(-1.0f, 0.0f, 0.0f) * box_rotation; + return BACK_SIDE; + } + } + + // left + if (dirY > 0.0f) + { + // plane_normal = [0, 1, 0] + // plane_normal*line_point = pointY + // plane_normal*line_direction = dirY + // D = -boxY + // alpha = - (-boxY + pointY) / dirY + line_plane_intersection = line_point + ((boxY - pointY)/dirY) * line_direction; + + if (line_plane_intersection.mV[VX] < boxX && + line_plane_intersection.mV[VX] > -boxX && + line_plane_intersection.mV[VZ] < boxZ && + line_plane_intersection.mV[VZ] > -boxZ ) + { + intersection = (line_plane_intersection * box_rotation) + box_center; + intersection_normal = LLVector3(0.0f, 1.0f, 0.0f) * box_rotation; + return LEFT_SIDE; + } + } + + // right + if (dirY < 0.0f) + { + // plane_normal = [0, -1, 0] + // plane_normal*line_point = -pointY + // plane_normal*line_direction = -dirY + // D = -boxY + // alpha = - (-boxY - pointY) / (-dirY) + line_plane_intersection = line_point - ((boxY + pointY)/dirY) * line_direction; + if (line_plane_intersection.mV[VX] < boxX && + line_plane_intersection.mV[VX] > -boxX && + line_plane_intersection.mV[VZ] < boxZ && + line_plane_intersection.mV[VZ] > -boxZ ) + { + intersection = (line_plane_intersection * box_rotation) + box_center; + intersection_normal = LLVector3(0.0f, -1.0f, 0.0f) * box_rotation; + return RIGHT_SIDE; + } + } + + // top + if (dirZ > 0.0f) + { + // plane_normal = [0, 0, 1] + // plane_normal*line_point = pointZ + // plane_normal*line_direction = dirZ + // D = -boxZ + // alpha = - (-boxZ + pointZ) / dirZ + line_plane_intersection = line_point - ((pointZ - boxZ)/dirZ) * line_direction; + if (line_plane_intersection.mV[VX] < boxX && + line_plane_intersection.mV[VX] > -boxX && + line_plane_intersection.mV[VY] < boxY && + line_plane_intersection.mV[VY] > -boxY ) + { + intersection = (line_plane_intersection * box_rotation) + box_center; + intersection_normal = LLVector3(0.0f, 0.0f, 1.0f) * box_rotation; + return TOP_SIDE; + } + } + + // bottom + if (dirZ < 0.0f) + { + // plane_normal = [0, 0, -1] + // plane_normal*line_point = -pointZ + // plane_normal*line_direction = -dirZ + // D = -boxZ + // alpha = - (-boxZ - pointZ) / (-dirZ) + line_plane_intersection = line_point - ((boxZ + pointZ)/dirZ) * line_direction; + if (line_plane_intersection.mV[VX] < boxX && + line_plane_intersection.mV[VX] > -boxX && + line_plane_intersection.mV[VY] < boxY && + line_plane_intersection.mV[VY] > -boxY ) + { + intersection = (line_plane_intersection * box_rotation) + box_center; + intersection_normal = LLVector3(0.0f, 0.0f, -1.0f) * box_rotation; + return BOTTOM_SIDE; + } + } + + // should never get here unless line instersects at tangent point on edge or corner + // however such cases will be EXTREMELY rare + return NO_SIDE; } bool ray_prism(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &prism_center, const LLVector3 &prism_scale, const LLQuaternion &prism_rotation, - LLVector3 &intersection, LLVector3 &intersection_normal) + const LLVector3 &prism_center, const LLVector3 &prism_scale, const LLQuaternion &prism_rotation, + LLVector3 &intersection, LLVector3 &intersection_normal) { - // (0) Z - // /| \ . - // (1)| \ /|\ _.Y - // | \ \ | /| - // | |\ \ | / - // | | \(0)\ | / - // | | \ \ |/ - // | | \ \ (*)----> X - // |(3)---\---(2) - // |/ \ / - // (4)-------(5) - - // need to calculate the points of the prism so we can run ray tests with each face - F32 x = prism_scale.mV[VX]; - F32 y = prism_scale.mV[VY]; - F32 z = prism_scale.mV[VZ]; - - F32 tx = x * 2.0f / 3.0f; - F32 ty = y * 0.5f; - F32 tz = z * 2.0f / 3.0f; - - LLVector3 point0(tx-x, ty, tz); - LLVector3 point1(tx-x, -ty, tz); - LLVector3 point2(tx, ty, tz-z); - LLVector3 point3(tx-x, ty, tz-z); - LLVector3 point4(tx-x, -ty, tz-z); - LLVector3 point5(tx, -ty, tz-z); - - // transform these points into absolute frame - point0 = (point0 * prism_rotation) + prism_center; - point1 = (point1 * prism_rotation) + prism_center; - point2 = (point2 * prism_rotation) + prism_center; - point3 = (point3 * prism_rotation) + prism_center; - point4 = (point4 * prism_rotation) + prism_center; - point5 = (point5 * prism_rotation) + prism_center; - - // test ray intersection for each face - bool b_hit = false; - LLVector3 face_intersection, face_normal; - F32 distance_squared = 0.0f; - F32 temp; - - // face 0 - if (ray_direction * ( (point0 - point2) % (point5 - point2)) < 0.0f && - ray_quadrangle(ray_point, ray_direction, point5, point2, point0, intersection, intersection_normal)) - { - distance_squared = (ray_point - intersection).magVecSquared(); - b_hit = true; - } - - // face 1 - if (ray_direction * ( (point0 - point3) % (point2 - point3)) < 0.0f && - ray_triangle(ray_point, ray_direction, point2, point3, point0, face_intersection, face_normal)) - { - if (b_hit) - { - temp = (ray_point - face_intersection).magVecSquared(); - if (temp < distance_squared) - { - distance_squared = temp; - intersection = face_intersection; - intersection_normal = face_normal; - } - } - else - { - distance_squared = (ray_point - face_intersection).magVecSquared(); - intersection = face_intersection; - intersection_normal = face_normal; - b_hit = true; - } - } - - // face 2 - if (ray_direction * ( (point1 - point4) % (point3 - point4)) < 0.0f && - ray_quadrangle(ray_point, ray_direction, point3, point4, point1, face_intersection, face_normal)) - { - if (b_hit) - { - temp = (ray_point - face_intersection).magVecSquared(); - if (temp < distance_squared) - { - distance_squared = temp; - intersection = face_intersection; - intersection_normal = face_normal; - } - } - else - { - distance_squared = (ray_point - face_intersection).magVecSquared(); - intersection = face_intersection; - intersection_normal = face_normal; - b_hit = true; - } - } - - // face 3 - if (ray_direction * ( (point5 - point4) % (point1 - point4)) < 0.0f && - ray_triangle(ray_point, ray_direction, point1, point4, point5, face_intersection, face_normal)) - { - if (b_hit) - { - temp = (ray_point - face_intersection).magVecSquared(); - if (temp < distance_squared) - { - distance_squared = temp; - intersection = face_intersection; - intersection_normal = face_normal; - } - } - else - { - distance_squared = (ray_point - face_intersection).magVecSquared(); - intersection = face_intersection; - intersection_normal = face_normal; - b_hit = true; - } - } - - // face 4 - if (ray_direction * ( (point4 - point5) % (point2 - point5)) < 0.0f && - ray_quadrangle(ray_point, ray_direction, point2, point5, point4, face_intersection, face_normal)) - { - if (b_hit) - { - temp = (ray_point - face_intersection).magVecSquared(); - if (temp < distance_squared) - { - distance_squared = temp; - intersection = face_intersection; - intersection_normal = face_normal; - } - } - else - { - distance_squared = (ray_point - face_intersection).magVecSquared(); - intersection = face_intersection; - intersection_normal = face_normal; - b_hit = true; - } - } - - return b_hit; + // (0) Z + // /| \ . + // (1)| \ /|\ _.Y + // | \ \ | /| + // | |\ \ | / + // | | \(0)\ | / + // | | \ \ |/ + // | | \ \ (*)----> X + // |(3)---\---(2) + // |/ \ / + // (4)-------(5) + + // need to calculate the points of the prism so we can run ray tests with each face + F32 x = prism_scale.mV[VX]; + F32 y = prism_scale.mV[VY]; + F32 z = prism_scale.mV[VZ]; + + F32 tx = x * 2.0f / 3.0f; + F32 ty = y * 0.5f; + F32 tz = z * 2.0f / 3.0f; + + LLVector3 point0(tx-x, ty, tz); + LLVector3 point1(tx-x, -ty, tz); + LLVector3 point2(tx, ty, tz-z); + LLVector3 point3(tx-x, ty, tz-z); + LLVector3 point4(tx-x, -ty, tz-z); + LLVector3 point5(tx, -ty, tz-z); + + // transform these points into absolute frame + point0 = (point0 * prism_rotation) + prism_center; + point1 = (point1 * prism_rotation) + prism_center; + point2 = (point2 * prism_rotation) + prism_center; + point3 = (point3 * prism_rotation) + prism_center; + point4 = (point4 * prism_rotation) + prism_center; + point5 = (point5 * prism_rotation) + prism_center; + + // test ray intersection for each face + bool b_hit = false; + LLVector3 face_intersection, face_normal; + F32 distance_squared = 0.0f; + F32 temp; + + // face 0 + if (ray_direction * ( (point0 - point2) % (point5 - point2)) < 0.0f && + ray_quadrangle(ray_point, ray_direction, point5, point2, point0, intersection, intersection_normal)) + { + distance_squared = (ray_point - intersection).magVecSquared(); + b_hit = true; + } + + // face 1 + if (ray_direction * ( (point0 - point3) % (point2 - point3)) < 0.0f && + ray_triangle(ray_point, ray_direction, point2, point3, point0, face_intersection, face_normal)) + { + if (b_hit) + { + temp = (ray_point - face_intersection).magVecSquared(); + if (temp < distance_squared) + { + distance_squared = temp; + intersection = face_intersection; + intersection_normal = face_normal; + } + } + else + { + distance_squared = (ray_point - face_intersection).magVecSquared(); + intersection = face_intersection; + intersection_normal = face_normal; + b_hit = true; + } + } + + // face 2 + if (ray_direction * ( (point1 - point4) % (point3 - point4)) < 0.0f && + ray_quadrangle(ray_point, ray_direction, point3, point4, point1, face_intersection, face_normal)) + { + if (b_hit) + { + temp = (ray_point - face_intersection).magVecSquared(); + if (temp < distance_squared) + { + distance_squared = temp; + intersection = face_intersection; + intersection_normal = face_normal; + } + } + else + { + distance_squared = (ray_point - face_intersection).magVecSquared(); + intersection = face_intersection; + intersection_normal = face_normal; + b_hit = true; + } + } + + // face 3 + if (ray_direction * ( (point5 - point4) % (point1 - point4)) < 0.0f && + ray_triangle(ray_point, ray_direction, point1, point4, point5, face_intersection, face_normal)) + { + if (b_hit) + { + temp = (ray_point - face_intersection).magVecSquared(); + if (temp < distance_squared) + { + distance_squared = temp; + intersection = face_intersection; + intersection_normal = face_normal; + } + } + else + { + distance_squared = (ray_point - face_intersection).magVecSquared(); + intersection = face_intersection; + intersection_normal = face_normal; + b_hit = true; + } + } + + // face 4 + if (ray_direction * ( (point4 - point5) % (point2 - point5)) < 0.0f && + ray_quadrangle(ray_point, ray_direction, point2, point5, point4, face_intersection, face_normal)) + { + if (b_hit) + { + temp = (ray_point - face_intersection).magVecSquared(); + if (temp < distance_squared) + { + distance_squared = temp; + intersection = face_intersection; + intersection_normal = face_normal; + } + } + else + { + distance_squared = (ray_point - face_intersection).magVecSquared(); + intersection = face_intersection; + intersection_normal = face_normal; + b_hit = true; + } + } + + return b_hit; } bool ray_tetrahedron(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &t_center, const LLVector3 &t_scale, const LLQuaternion &t_rotation, - LLVector3 &intersection, LLVector3 &intersection_normal) + const LLVector3 &t_center, const LLVector3 &t_scale, const LLQuaternion &t_rotation, + LLVector3 &intersection, LLVector3 &intersection_normal) { - F32 a = 0.5f * F_SQRT3; // height of unit triangle - F32 b = 1.0f / F_SQRT3; // distance of center of unit triangle to each point - F32 c = F_SQRT2 / F_SQRT3; // height of unit tetrahedron - F32 d = 0.5f * F_SQRT3 / F_SQRT2; // distance of center of tetrahedron to each point - - // if we want the tetrahedron to have unit height (c = 1.0) then we need to divide - // each constant by hieght of a unit tetrahedron - F32 oo_c = 1.0f / c; - a = a * oo_c; - b = b * oo_c; - c = 1.0f; - d = d * oo_c; - F32 e = 0.5f * oo_c; - - LLVector3 point0( 0.0f, 0.0f, t_scale.mV[VZ] * d); - LLVector3 point1(t_scale.mV[VX] * b, 0.0f, t_scale.mV[VZ] * (d-c)); - LLVector3 point2(t_scale.mV[VX] * (b-a), e * t_scale.mV[VY], t_scale.mV[VZ] * (d-c)); - LLVector3 point3(t_scale.mV[VX] * (b-a), -e * t_scale.mV[VY], t_scale.mV[VZ] * (d-c)); - - // transform these points into absolute frame - point0 = (point0 * t_rotation) + t_center; - point1 = (point1 * t_rotation) + t_center; - point2 = (point2 * t_rotation) + t_center; - point3 = (point3 * t_rotation) + t_center; - - // test ray intersection for each face - bool b_hit = false; - LLVector3 face_intersection, face_normal; - F32 distance_squared = 1.0e12f; - F32 temp; - - // face 0 - if (ray_direction * ( (point2 - point1) % (point0 - point1)) < 0.0f && - ray_triangle(ray_point, ray_direction, point1, point2, point0, intersection, intersection_normal)) - { - distance_squared = (ray_point - intersection).magVecSquared(); - b_hit = true; - } - - // face 1 - if (ray_direction * ( (point3 - point2) % (point0 - point2)) < 0.0f && - ray_triangle(ray_point, ray_direction, point2, point3, point0, face_intersection, face_normal)) - { - if (b_hit) - { - temp = (ray_point - face_intersection).magVecSquared(); - if (temp < distance_squared) - { - distance_squared = temp; - intersection = face_intersection; - intersection_normal = face_normal; - } - } - else - { - distance_squared = (ray_point - face_intersection).magVecSquared(); - intersection = face_intersection; - intersection_normal = face_normal; - b_hit = true; - } - } - - // face 2 - if (ray_direction * ( (point1 - point3) % (point0 - point3)) < 0.0f && - ray_triangle(ray_point, ray_direction, point3, point1, point0, face_intersection, face_normal)) - { - if (b_hit) - { - temp = (ray_point - face_intersection).magVecSquared(); - if (temp < distance_squared) - { - distance_squared = temp; - intersection = face_intersection; - intersection_normal = face_normal; - } - } - else - { - distance_squared = (ray_point - face_intersection).magVecSquared(); - intersection = face_intersection; - intersection_normal = face_normal; - b_hit = true; - } - } - - // face 3 - if (ray_direction * ( (point2 - point3) % (point1 - point3)) < 0.0f && - ray_triangle(ray_point, ray_direction, point3, point2, point1, face_intersection, face_normal)) - { - if (b_hit) - { - temp = (ray_point - face_intersection).magVecSquared(); - if (temp < distance_squared) - { - intersection = face_intersection; - intersection_normal = face_normal; - } - } - else - { - intersection = face_intersection; - intersection_normal = face_normal; - b_hit = true; - } - } - - return b_hit; + F32 a = 0.5f * F_SQRT3; // height of unit triangle + F32 b = 1.0f / F_SQRT3; // distance of center of unit triangle to each point + F32 c = F_SQRT2 / F_SQRT3; // height of unit tetrahedron + F32 d = 0.5f * F_SQRT3 / F_SQRT2; // distance of center of tetrahedron to each point + + // if we want the tetrahedron to have unit height (c = 1.0) then we need to divide + // each constant by hieght of a unit tetrahedron + F32 oo_c = 1.0f / c; + a = a * oo_c; + b = b * oo_c; + c = 1.0f; + d = d * oo_c; + F32 e = 0.5f * oo_c; + + LLVector3 point0( 0.0f, 0.0f, t_scale.mV[VZ] * d); + LLVector3 point1(t_scale.mV[VX] * b, 0.0f, t_scale.mV[VZ] * (d-c)); + LLVector3 point2(t_scale.mV[VX] * (b-a), e * t_scale.mV[VY], t_scale.mV[VZ] * (d-c)); + LLVector3 point3(t_scale.mV[VX] * (b-a), -e * t_scale.mV[VY], t_scale.mV[VZ] * (d-c)); + + // transform these points into absolute frame + point0 = (point0 * t_rotation) + t_center; + point1 = (point1 * t_rotation) + t_center; + point2 = (point2 * t_rotation) + t_center; + point3 = (point3 * t_rotation) + t_center; + + // test ray intersection for each face + bool b_hit = false; + LLVector3 face_intersection, face_normal; + F32 distance_squared = 1.0e12f; + F32 temp; + + // face 0 + if (ray_direction * ( (point2 - point1) % (point0 - point1)) < 0.0f && + ray_triangle(ray_point, ray_direction, point1, point2, point0, intersection, intersection_normal)) + { + distance_squared = (ray_point - intersection).magVecSquared(); + b_hit = true; + } + + // face 1 + if (ray_direction * ( (point3 - point2) % (point0 - point2)) < 0.0f && + ray_triangle(ray_point, ray_direction, point2, point3, point0, face_intersection, face_normal)) + { + if (b_hit) + { + temp = (ray_point - face_intersection).magVecSquared(); + if (temp < distance_squared) + { + distance_squared = temp; + intersection = face_intersection; + intersection_normal = face_normal; + } + } + else + { + distance_squared = (ray_point - face_intersection).magVecSquared(); + intersection = face_intersection; + intersection_normal = face_normal; + b_hit = true; + } + } + + // face 2 + if (ray_direction * ( (point1 - point3) % (point0 - point3)) < 0.0f && + ray_triangle(ray_point, ray_direction, point3, point1, point0, face_intersection, face_normal)) + { + if (b_hit) + { + temp = (ray_point - face_intersection).magVecSquared(); + if (temp < distance_squared) + { + distance_squared = temp; + intersection = face_intersection; + intersection_normal = face_normal; + } + } + else + { + distance_squared = (ray_point - face_intersection).magVecSquared(); + intersection = face_intersection; + intersection_normal = face_normal; + b_hit = true; + } + } + + // face 3 + if (ray_direction * ( (point2 - point3) % (point1 - point3)) < 0.0f && + ray_triangle(ray_point, ray_direction, point3, point2, point1, face_intersection, face_normal)) + { + if (b_hit) + { + temp = (ray_point - face_intersection).magVecSquared(); + if (temp < distance_squared) + { + intersection = face_intersection; + intersection_normal = face_normal; + } + } + else + { + intersection = face_intersection; + intersection_normal = face_normal; + b_hit = true; + } + } + + return b_hit; } bool ray_pyramid(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &p_center, const LLVector3 &p_scale, const LLQuaternion &p_rotation, - LLVector3 &intersection, LLVector3 &intersection_normal) + const LLVector3 &p_center, const LLVector3 &p_scale, const LLQuaternion &p_rotation, + LLVector3 &intersection, LLVector3 &intersection_normal) { - // center of mass of pyramid is located 1/4 its height from the base - F32 x = 0.5f * p_scale.mV[VX]; - F32 y = 0.5f * p_scale.mV[VY]; - F32 z = 0.25f * p_scale.mV[VZ]; - - LLVector3 point0(0.0f, 0.0f, p_scale.mV[VZ] - z); - LLVector3 point1( x, y, -z); - LLVector3 point2(-x, y, -z); - LLVector3 point3(-x, -y, -z); - LLVector3 point4( x, -y, -z); - - // transform these points into absolute frame - point0 = (point0 * p_rotation) + p_center; - point1 = (point1 * p_rotation) + p_center; - point2 = (point2 * p_rotation) + p_center; - point3 = (point3 * p_rotation) + p_center; - point4 = (point4 * p_rotation) + p_center; - - // test ray intersection for each face - bool b_hit = false; - LLVector3 face_intersection, face_normal; - F32 distance_squared = 1.0e12f; - F32 temp; - - // face 0 - if (ray_direction * ( (point1 - point4) % (point0 - point4)) < 0.0f && - ray_triangle(ray_point, ray_direction, point4, point1, point0, intersection, intersection_normal)) - { - distance_squared = (ray_point - intersection).magVecSquared(); - b_hit = true; - } - - // face 1 - if (ray_direction * ( (point2 - point1) % (point0 - point1)) < 0.0f && - ray_triangle(ray_point, ray_direction, point1, point2, point0, face_intersection, face_normal)) - { - if (b_hit) - { - temp = (ray_point - face_intersection).magVecSquared(); - if (temp < distance_squared) - { - distance_squared = temp; - intersection = face_intersection; - intersection_normal = face_normal; - } - } - else - { - distance_squared = (ray_point - face_intersection).magVecSquared(); - intersection = face_intersection; - intersection_normal = face_normal; - b_hit = true; - } - } - - // face 2 - if (ray_direction * ( (point3 - point2) % (point0 - point2)) < 0.0f && - ray_triangle(ray_point, ray_direction, point2, point3, point0, face_intersection, face_normal)) - { - if (b_hit) - { - temp = (ray_point - face_intersection).magVecSquared(); - if (temp < distance_squared) - { - distance_squared = temp; - intersection = face_intersection; - intersection_normal = face_normal; - } - } - else - { - distance_squared = (ray_point - face_intersection).magVecSquared(); - intersection = face_intersection; - intersection_normal = face_normal; - b_hit = true; - } - } - - // face 3 - if (ray_direction * ( (point4 - point3) % (point0 - point3)) < 0.0f && - ray_triangle(ray_point, ray_direction, point3, point4, point0, face_intersection, face_normal)) - { - if (b_hit) - { - temp = (ray_point - face_intersection).magVecSquared(); - if (temp < distance_squared) - { - distance_squared = temp; - intersection = face_intersection; - intersection_normal = face_normal; - } - } - else - { - distance_squared = (ray_point - face_intersection).magVecSquared(); - intersection = face_intersection; - intersection_normal = face_normal; - b_hit = true; - } - } - - // face 4 - if (ray_direction * ( (point3 - point4) % (point2 - point4)) < 0.0f && - ray_quadrangle(ray_point, ray_direction, point4, point3, point2, face_intersection, face_normal)) - { - if (b_hit) - { - temp = (ray_point - face_intersection).magVecSquared(); - if (temp < distance_squared) - { - intersection = face_intersection; - intersection_normal = face_normal; - } - } - else - { - intersection = face_intersection; - intersection_normal = face_normal; - b_hit = true; - } - } - - return b_hit; + // center of mass of pyramid is located 1/4 its height from the base + F32 x = 0.5f * p_scale.mV[VX]; + F32 y = 0.5f * p_scale.mV[VY]; + F32 z = 0.25f * p_scale.mV[VZ]; + + LLVector3 point0(0.0f, 0.0f, p_scale.mV[VZ] - z); + LLVector3 point1( x, y, -z); + LLVector3 point2(-x, y, -z); + LLVector3 point3(-x, -y, -z); + LLVector3 point4( x, -y, -z); + + // transform these points into absolute frame + point0 = (point0 * p_rotation) + p_center; + point1 = (point1 * p_rotation) + p_center; + point2 = (point2 * p_rotation) + p_center; + point3 = (point3 * p_rotation) + p_center; + point4 = (point4 * p_rotation) + p_center; + + // test ray intersection for each face + bool b_hit = false; + LLVector3 face_intersection, face_normal; + F32 distance_squared = 1.0e12f; + F32 temp; + + // face 0 + if (ray_direction * ( (point1 - point4) % (point0 - point4)) < 0.0f && + ray_triangle(ray_point, ray_direction, point4, point1, point0, intersection, intersection_normal)) + { + distance_squared = (ray_point - intersection).magVecSquared(); + b_hit = true; + } + + // face 1 + if (ray_direction * ( (point2 - point1) % (point0 - point1)) < 0.0f && + ray_triangle(ray_point, ray_direction, point1, point2, point0, face_intersection, face_normal)) + { + if (b_hit) + { + temp = (ray_point - face_intersection).magVecSquared(); + if (temp < distance_squared) + { + distance_squared = temp; + intersection = face_intersection; + intersection_normal = face_normal; + } + } + else + { + distance_squared = (ray_point - face_intersection).magVecSquared(); + intersection = face_intersection; + intersection_normal = face_normal; + b_hit = true; + } + } + + // face 2 + if (ray_direction * ( (point3 - point2) % (point0 - point2)) < 0.0f && + ray_triangle(ray_point, ray_direction, point2, point3, point0, face_intersection, face_normal)) + { + if (b_hit) + { + temp = (ray_point - face_intersection).magVecSquared(); + if (temp < distance_squared) + { + distance_squared = temp; + intersection = face_intersection; + intersection_normal = face_normal; + } + } + else + { + distance_squared = (ray_point - face_intersection).magVecSquared(); + intersection = face_intersection; + intersection_normal = face_normal; + b_hit = true; + } + } + + // face 3 + if (ray_direction * ( (point4 - point3) % (point0 - point3)) < 0.0f && + ray_triangle(ray_point, ray_direction, point3, point4, point0, face_intersection, face_normal)) + { + if (b_hit) + { + temp = (ray_point - face_intersection).magVecSquared(); + if (temp < distance_squared) + { + distance_squared = temp; + intersection = face_intersection; + intersection_normal = face_normal; + } + } + else + { + distance_squared = (ray_point - face_intersection).magVecSquared(); + intersection = face_intersection; + intersection_normal = face_normal; + b_hit = true; + } + } + + // face 4 + if (ray_direction * ( (point3 - point4) % (point2 - point4)) < 0.0f && + ray_quadrangle(ray_point, ray_direction, point4, point3, point2, face_intersection, face_normal)) + { + if (b_hit) + { + temp = (ray_point - face_intersection).magVecSquared(); + if (temp < distance_squared) + { + intersection = face_intersection; + intersection_normal = face_normal; + } + } + else + { + intersection = face_intersection; + intersection_normal = face_normal; + b_hit = true; + } + } + + return b_hit; } bool linesegment_circle(const LLVector3 &point_a, const LLVector3 &point_b, - const LLVector3 &circle_center, const LLVector3 plane_normal, F32 circle_radius, - LLVector3 &intersection) + const LLVector3 &circle_center, const LLVector3 plane_normal, F32 circle_radius, + LLVector3 &intersection) { - LLVector3 ray_direction = point_b - point_a; - F32 segment_length = ray_direction.normVec(); - - if (ray_circle(point_a, ray_direction, circle_center, plane_normal, circle_radius, intersection)) - { - if (segment_length >= (point_a - intersection).magVec()) - { - return true; - } - } - return false; + LLVector3 ray_direction = point_b - point_a; + F32 segment_length = ray_direction.normVec(); + + if (ray_circle(point_a, ray_direction, circle_center, plane_normal, circle_radius, intersection)) + { + if (segment_length >= (point_a - intersection).magVec()) + { + return true; + } + } + return false; } bool linesegment_triangle(const LLVector3 &point_a, const LLVector3 &point_b, - const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2, - LLVector3 &intersection, LLVector3 &intersection_normal) + const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2, + LLVector3 &intersection, LLVector3 &intersection_normal) { - LLVector3 ray_direction = point_b - point_a; - F32 segment_length = ray_direction.normVec(); - - if (ray_triangle(point_a, ray_direction, point_0, point_1, point_2, intersection, intersection_normal)) - { - if (segment_length >= (point_a - intersection).magVec()) - { - return true; - } - } - return false; + LLVector3 ray_direction = point_b - point_a; + F32 segment_length = ray_direction.normVec(); + + if (ray_triangle(point_a, ray_direction, point_0, point_1, point_2, intersection, intersection_normal)) + { + if (segment_length >= (point_a - intersection).magVec()) + { + return true; + } + } + return false; } bool linesegment_quadrangle(const LLVector3 &point_a, const LLVector3 &point_b, - const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2, - LLVector3 &intersection, LLVector3 &intersection_normal) + const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2, + LLVector3 &intersection, LLVector3 &intersection_normal) { - LLVector3 ray_direction = point_b - point_a; - F32 segment_length = ray_direction.normVec(); - - if (ray_quadrangle(point_a, ray_direction, point_0, point_1, point_2, intersection, intersection_normal)) - { - if (segment_length >= (point_a - intersection).magVec()) - { - return true; - } - } - return false; + LLVector3 ray_direction = point_b - point_a; + F32 segment_length = ray_direction.normVec(); + + if (ray_quadrangle(point_a, ray_direction, point_0, point_1, point_2, intersection, intersection_normal)) + { + if (segment_length >= (point_a - intersection).magVec()) + { + return true; + } + } + return false; } bool linesegment_sphere(const LLVector3 &point_a, const LLVector3 &point_b, - const LLVector3 &sphere_center, F32 sphere_radius, - LLVector3 &intersection, LLVector3 &intersection_normal) + const LLVector3 &sphere_center, F32 sphere_radius, + LLVector3 &intersection, LLVector3 &intersection_normal) { - LLVector3 ray_direction = point_b - point_a; - F32 segment_length = ray_direction.normVec(); - - if (ray_sphere(point_a, ray_direction, sphere_center, sphere_radius, intersection, intersection_normal)) - { - if (segment_length >= (point_a - intersection).magVec()) - { - return true; - } - } - return false; + LLVector3 ray_direction = point_b - point_a; + F32 segment_length = ray_direction.normVec(); + + if (ray_sphere(point_a, ray_direction, sphere_center, sphere_radius, intersection, intersection_normal)) + { + if (segment_length >= (point_a - intersection).magVec()) + { + return true; + } + } + return false; } bool linesegment_cylinder(const LLVector3 &point_a, const LLVector3 &point_b, - const LLVector3 &cyl_center, const LLVector3 &cyl_scale, const LLQuaternion &cyl_rotation, - LLVector3 &intersection, LLVector3 &intersection_normal) + const LLVector3 &cyl_center, const LLVector3 &cyl_scale, const LLQuaternion &cyl_rotation, + LLVector3 &intersection, LLVector3 &intersection_normal) { - LLVector3 ray_direction = point_b - point_a; - F32 segment_length = ray_direction.normVec(); - - if (ray_cylinder(point_a, ray_direction, cyl_center, cyl_scale, cyl_rotation, intersection, intersection_normal)) - { - if (segment_length >= (point_a - intersection).magVec()) - { - return true; - } - } - return false; + LLVector3 ray_direction = point_b - point_a; + F32 segment_length = ray_direction.normVec(); + + if (ray_cylinder(point_a, ray_direction, cyl_center, cyl_scale, cyl_rotation, intersection, intersection_normal)) + { + if (segment_length >= (point_a - intersection).magVec()) + { + return true; + } + } + return false; } -U32 linesegment_box(const LLVector3 &point_a, const LLVector3 &point_b, - const LLVector3 &box_center, const LLVector3 &box_scale, const LLQuaternion &box_rotation, - LLVector3 &intersection, LLVector3 &intersection_normal) +U32 linesegment_box(const LLVector3 &point_a, const LLVector3 &point_b, + const LLVector3 &box_center, const LLVector3 &box_scale, const LLQuaternion &box_rotation, + LLVector3 &intersection, LLVector3 &intersection_normal) { - LLVector3 direction = point_b - point_a; - if (direction.isNull()) - { - return NO_SIDE; - } - - F32 segment_length = direction.normVec(); - U32 box_side = ray_box(point_a, direction, box_center, box_scale, box_rotation, intersection, intersection_normal); - if (NO_SIDE == box_side || segment_length < (intersection - point_a).magVec()) - { - return NO_SIDE; - } - - return box_side; + LLVector3 direction = point_b - point_a; + if (direction.isNull()) + { + return NO_SIDE; + } + + F32 segment_length = direction.normVec(); + U32 box_side = ray_box(point_a, direction, box_center, box_scale, box_rotation, intersection, intersection_normal); + if (NO_SIDE == box_side || segment_length < (intersection - point_a).magVec()) + { + return NO_SIDE; + } + + return box_side; } bool linesegment_prism(const LLVector3 &point_a, const LLVector3 &point_b, - const LLVector3 &prism_center, const LLVector3 &prism_scale, const LLQuaternion &prism_rotation, - LLVector3 &intersection, LLVector3 &intersection_normal) + const LLVector3 &prism_center, const LLVector3 &prism_scale, const LLQuaternion &prism_rotation, + LLVector3 &intersection, LLVector3 &intersection_normal) { - LLVector3 ray_direction = point_b - point_a; - F32 segment_length = ray_direction.normVec(); - - if (ray_prism(point_a, ray_direction, prism_center, prism_scale, prism_rotation, intersection, intersection_normal)) - { - if (segment_length >= (point_a - intersection).magVec()) - { - return true; - } - } - return false; + LLVector3 ray_direction = point_b - point_a; + F32 segment_length = ray_direction.normVec(); + + if (ray_prism(point_a, ray_direction, prism_center, prism_scale, prism_rotation, intersection, intersection_normal)) + { + if (segment_length >= (point_a - intersection).magVec()) + { + return true; + } + } + return false; } bool linesegment_tetrahedron(const LLVector3 &point_a, const LLVector3 &point_b, - const LLVector3 &t_center, const LLVector3 &t_scale, const LLQuaternion &t_rotation, - LLVector3 &intersection, LLVector3 &intersection_normal) + const LLVector3 &t_center, const LLVector3 &t_scale, const LLQuaternion &t_rotation, + LLVector3 &intersection, LLVector3 &intersection_normal) { - LLVector3 ray_direction = point_b - point_a; - F32 segment_length = ray_direction.normVec(); - - if (ray_tetrahedron(point_a, ray_direction, t_center, t_scale, t_rotation, intersection, intersection_normal)) - { - if (segment_length >= (point_a - intersection).magVec()) - { - return true; - } - } - return false; + LLVector3 ray_direction = point_b - point_a; + F32 segment_length = ray_direction.normVec(); + + if (ray_tetrahedron(point_a, ray_direction, t_center, t_scale, t_rotation, intersection, intersection_normal)) + { + if (segment_length >= (point_a - intersection).magVec()) + { + return true; + } + } + return false; } bool linesegment_pyramid(const LLVector3 &point_a, const LLVector3 &point_b, - const LLVector3 &p_center, const LLVector3 &p_scale, const LLQuaternion &p_rotation, - LLVector3 &intersection, LLVector3 &intersection_normal) + const LLVector3 &p_center, const LLVector3 &p_scale, const LLQuaternion &p_rotation, + LLVector3 &intersection, LLVector3 &intersection_normal) { - LLVector3 ray_direction = point_b - point_a; - F32 segment_length = ray_direction.normVec(); - - if (ray_pyramid(point_a, ray_direction, p_center, p_scale, p_rotation, intersection, intersection_normal)) - { - if (segment_length >= (point_a - intersection).magVec()) - { - return true; - } - } - return false; + LLVector3 ray_direction = point_b - point_a; + F32 segment_length = ray_direction.normVec(); + + if (ray_pyramid(point_a, ray_direction, p_center, p_scale, p_rotation, intersection, intersection_normal)) + { + if (segment_length >= (point_a - intersection).magVec()) + { + return true; + } + } + return false; } diff --git a/indra/llmath/raytrace.h b/indra/llmath/raytrace.h index 2352790b1f..b55f29aef6 100644 --- a/indra/llmath/raytrace.h +++ b/indra/llmath/raytrace.h @@ -1,25 +1,25 @@ -/** +/** * @file raytrace.h * @brief Ray intersection tests for primitives. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -39,7 +39,7 @@ class LLQuaternion; // object along the three axes. // // All functions return the expected true or false, unless otherwise noted. -// When false is returned, any resulting values that might have been stored +// When false is returned, any resulting values that might have been stored // are undefined. // // Rays are defined by a "ray_point" and a "ray_direction" (unit). @@ -55,7 +55,7 @@ class LLQuaternion; // Intersection normals always point outside the object, normal to the object's // surface at the point of intersection. // -// Object rotations passed as quaternions are expected to rotate from the +// Object rotations passed as quaternions are expected to rotate from the // object's local frame to the absolute frame. So, if "foo" is a vector in // the object's local frame, then "foo * object_rotation" is in the absolute // frame. @@ -63,25 +63,25 @@ class LLQuaternion; // returns true if line is not parallel to plane. bool line_plane(const LLVector3 &line_point, const LLVector3 &line_direction, - const LLVector3 &plane_point, const LLVector3 plane_normal, - LLVector3 &intersection); + const LLVector3 &plane_point, const LLVector3 plane_normal, + LLVector3 &intersection); // returns true if line is not parallel to plane. bool ray_plane(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &plane_point, const LLVector3 plane_normal, - LLVector3 &intersection); + const LLVector3 &plane_point, const LLVector3 plane_normal, + LLVector3 &intersection); bool ray_circle(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &circle_center, const LLVector3 plane_normal, F32 circle_radius, - LLVector3 &intersection); + const LLVector3 &circle_center, const LLVector3 plane_normal, F32 circle_radius, + LLVector3 &intersection); // point_0 through point_2 define the plane_normal via the right-hand rule: // circle from point_0 to point_2 with fingers ==> thumb points in direction of normal bool ray_triangle(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2, - LLVector3 &intersection, LLVector3 &intersection_normal); + const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2, + LLVector3 &intersection, LLVector3 &intersection_normal); // point_0 is the lower-left corner, point_1 is the lower-right, point_2 is the upper-right @@ -89,96 +89,96 @@ bool ray_triangle(const LLVector3 &ray_point, const LLVector3 &ray_direction, // ==> thumb points in direction of normal // assumes a parallelogram, so point_3 is determined by the other points bool ray_quadrangle(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2, - LLVector3 &intersection, LLVector3 &intersection_normal); + const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2, + LLVector3 &intersection, LLVector3 &intersection_normal); bool ray_sphere(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &sphere_center, F32 sphere_radius, - LLVector3 &intersection, LLVector3 &intersection_normal); + const LLVector3 &sphere_center, F32 sphere_radius, + LLVector3 &intersection, LLVector3 &intersection_normal); -// finite right cylinder is defined by end centers: "cyl_top", "cyl_bottom", +// finite right cylinder is defined by end centers: "cyl_top", "cyl_bottom", // and by the cylinder radius "cyl_radius" bool ray_cylinder(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &cyl_center, const LLVector3 &cyl_scale, const LLQuaternion &cyl_rotation, - LLVector3 &intersection, LLVector3 &intersection_normal); + const LLVector3 &cyl_center, const LLVector3 &cyl_scale, const LLQuaternion &cyl_rotation, + LLVector3 &intersection, LLVector3 &intersection_normal); // this function doesn't just return a bool because the return is currently -// used to decide how to break up boxes that have been hit by shots... +// used to decide how to break up boxes that have been hit by shots... // a hack that will probably be changed later // // returns a number representing the side of the box that was hit by the ray, // or NO_SIDE if intersection test failed. U32 ray_box(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &box_center, const LLVector3 &box_scale, const LLQuaternion &box_rotation, - LLVector3 &intersection, LLVector3 &intersection_normal); + const LLVector3 &box_center, const LLVector3 &box_scale, const LLQuaternion &box_rotation, + LLVector3 &intersection, LLVector3 &intersection_normal); /* TODO bool ray_ellipsoid(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &e_center, const LLVector3 &e_scale, const LLQuaternion &e_rotation, - LLVector3 &intersection, LLVector3 &intersection_normal); + const LLVector3 &e_center, const LLVector3 &e_scale, const LLQuaternion &e_rotation, + LLVector3 &intersection, LLVector3 &intersection_normal); bool ray_cone(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &cone_tip, const LLVector3 &cone_bottom, - const LLVector3 &cone_scale, const LLQuaternion &cone_rotation, - LLVector3 &intersection, LLVector3 &intersection_normal); + const LLVector3 &cone_tip, const LLVector3 &cone_bottom, + const LLVector3 &cone_scale, const LLQuaternion &cone_rotation, + LLVector3 &intersection, LLVector3 &intersection_normal); */ bool ray_prism(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &prism_center, const LLVector3 &prism_scale, const LLQuaternion &prism_rotation, - LLVector3 &intersection, LLVector3 &intersection_normal); + const LLVector3 &prism_center, const LLVector3 &prism_scale, const LLQuaternion &prism_rotation, + LLVector3 &intersection, LLVector3 &intersection_normal); bool ray_tetrahedron(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &t_center, const LLVector3 &t_scale, const LLQuaternion &t_rotation, - LLVector3 &intersection, LLVector3 &intersection_normal); + const LLVector3 &t_center, const LLVector3 &t_scale, const LLQuaternion &t_rotation, + LLVector3 &intersection, LLVector3 &intersection_normal); bool ray_pyramid(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &p_center, const LLVector3 &p_scale, const LLQuaternion &p_rotation, - LLVector3 &intersection, LLVector3 &intersection_normal); + const LLVector3 &p_center, const LLVector3 &p_scale, const LLQuaternion &p_rotation, + LLVector3 &intersection, LLVector3 &intersection_normal); /* TODO bool ray_hemiellipsoid(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &e_center, const LLVector3 &e_scale, const LLQuaternion &e_rotation, - const LLVector3 &e_cut_normal, - LLVector3 &intersection, LLVector3 &intersection_normal); + const LLVector3 &e_center, const LLVector3 &e_scale, const LLQuaternion &e_rotation, + const LLVector3 &e_cut_normal, + LLVector3 &intersection, LLVector3 &intersection_normal); bool ray_hemisphere(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &sphere_center, F32 sphere_radius, const LLVector3 &sphere_cut_normal, - LLVector3 &intersection, LLVector3 &intersection_normal); + const LLVector3 &sphere_center, F32 sphere_radius, const LLVector3 &sphere_cut_normal, + LLVector3 &intersection, LLVector3 &intersection_normal); bool ray_hemicylinder(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &cyl_top, const LLVector3 &cyl_bottom, F32 cyl_radius, - const LLVector3 &cyl_cut_normal, - LLVector3 &intersection, LLVector3 &intersection_normal); + const LLVector3 &cyl_top, const LLVector3 &cyl_bottom, F32 cyl_radius, + const LLVector3 &cyl_cut_normal, + LLVector3 &intersection, LLVector3 &intersection_normal); bool ray_hemicone(const LLVector3 &ray_point, const LLVector3 &ray_direction, - const LLVector3 &cone_tip, const LLVector3 &cone_bottom, - const LLVector3 &cone_scale, const LLVector3 &cyl_cut_normal, - LLVector3 &intersection, LLVector3 &intersection_normal); + const LLVector3 &cone_tip, const LLVector3 &cone_bottom, + const LLVector3 &cone_scale, const LLVector3 &cyl_cut_normal, + LLVector3 &intersection, LLVector3 &intersection_normal); */ bool linesegment_circle(const LLVector3 &point_a, const LLVector3 &point_b, - const LLVector3 &circle_center, const LLVector3 plane_normal, F32 circle_radius, - LLVector3 &intersection); + const LLVector3 &circle_center, const LLVector3 plane_normal, F32 circle_radius, + LLVector3 &intersection); // point_0 through point_2 define the plane_normal via the right-hand rule: // circle from point_0 to point_2 with fingers ==> thumb points in direction of normal bool linesegment_triangle(const LLVector3 &point_a, const LLVector3 &point_b, - const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2, - LLVector3 &intersection, LLVector3 &intersection_normal); + const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2, + LLVector3 &intersection, LLVector3 &intersection_normal); // point_0 is the lower-left corner, point_1 is the lower-right, point_2 is the upper-right @@ -186,44 +186,44 @@ bool linesegment_triangle(const LLVector3 &point_a, const LLVector3 &point_b, // ==> thumb points in direction of normal // assumes a parallelogram, so point_3 is determined by the other points bool linesegment_quadrangle(const LLVector3 &point_a, const LLVector3 &point_b, - const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2, - LLVector3 &intersection, LLVector3 &intersection_normal); + const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2, + LLVector3 &intersection, LLVector3 &intersection_normal); bool linesegment_sphere(const LLVector3 &point_a, const LLVector3 &point_b, - const LLVector3 &sphere_center, F32 sphere_radius, - LLVector3 &intersection, LLVector3 &intersection_normal); + const LLVector3 &sphere_center, F32 sphere_radius, + LLVector3 &intersection, LLVector3 &intersection_normal); -// finite right cylinder is defined by end centers: "cyl_top", "cyl_bottom", +// finite right cylinder is defined by end centers: "cyl_top", "cyl_bottom", // and by the cylinder radius "cyl_radius" bool linesegment_cylinder(const LLVector3 &point_a, const LLVector3 &point_b, - const LLVector3 &cyl_center, const LLVector3 &cyl_scale, const LLQuaternion &cyl_rotation, - LLVector3 &intersection, LLVector3 &intersection_normal); + const LLVector3 &cyl_center, const LLVector3 &cyl_scale, const LLQuaternion &cyl_rotation, + LLVector3 &intersection, LLVector3 &intersection_normal); // this function doesn't just return a bool because the return is currently -// used to decide how to break up boxes that have been hit by shots... +// used to decide how to break up boxes that have been hit by shots... // a hack that will probably be changed later // // returns a number representing the side of the box that was hit by the ray, // or NO_SIDE if intersection test failed. -U32 linesegment_box(const LLVector3 &point_a, const LLVector3 &point_b, - const LLVector3 &box_center, const LLVector3 &box_scale, const LLQuaternion &box_rotation, - LLVector3 &intersection, LLVector3 &intersection_normal); +U32 linesegment_box(const LLVector3 &point_a, const LLVector3 &point_b, + const LLVector3 &box_center, const LLVector3 &box_scale, const LLQuaternion &box_rotation, + LLVector3 &intersection, LLVector3 &intersection_normal); bool linesegment_prism(const LLVector3 &point_a, const LLVector3 &point_b, - const LLVector3 &prism_center, const LLVector3 &prism_scale, const LLQuaternion &prism_rotation, - LLVector3 &intersection, LLVector3 &intersection_normal); + const LLVector3 &prism_center, const LLVector3 &prism_scale, const LLQuaternion &prism_rotation, + LLVector3 &intersection, LLVector3 &intersection_normal); bool linesegment_tetrahedron(const LLVector3 &point_a, const LLVector3 &point_b, - const LLVector3 &t_center, const LLVector3 &t_scale, const LLQuaternion &t_rotation, - LLVector3 &intersection, LLVector3 &intersection_normal); + const LLVector3 &t_center, const LLVector3 &t_scale, const LLQuaternion &t_rotation, + LLVector3 &intersection, LLVector3 &intersection_normal); bool linesegment_pyramid(const LLVector3 &point_a, const LLVector3 &point_b, - const LLVector3 &p_center, const LLVector3 &p_scale, const LLQuaternion &p_rotation, - LLVector3 &intersection, LLVector3 &intersection_normal); + const LLVector3 &p_center, const LLVector3 &p_scale, const LLQuaternion &p_rotation, + LLVector3 &intersection, LLVector3 &intersection_normal); #endif diff --git a/indra/llmath/tests/alignment_test.cpp b/indra/llmath/tests/alignment_test.cpp index 5ee3c45502..eb6fa4a3b8 100644 --- a/indra/llmath/tests/alignment_test.cpp +++ b/indra/llmath/tests/alignment_test.cpp @@ -7,21 +7,21 @@ * $LicenseInfo:firstyear=2011&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2011, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -50,27 +50,27 @@ LL_ALIGN_PREFIX(16) class MyVector4a { public: - void* operator new(size_t size) - { - return ll_aligned_malloc_16(size); - } - - void operator delete(void *p) - { - ll_aligned_free_16(p); - } - - void* operator new[](size_t count) - { // try to allocate count bytes for an array - return ll_aligned_malloc_16(count); - } - - void operator delete[](void *p) - { - ll_aligned_free_16(p); - } - - LLQuad mQ; + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void *p) + { + ll_aligned_free_16(p); + } + + void* operator new[](size_t count) + { // try to allocate count bytes for an array + return ll_aligned_malloc_16(count); + } + + void operator delete[](void *p) + { + ll_aligned_free_16(p); + } + + LLQuad mQ; } LL_ALIGN_POSTFIX(16); @@ -79,36 +79,36 @@ template<> template<> void alignment_test_object_t::test<1>() { # ifdef LL_DEBUG -// skip("This test fails on Windows when compiled in debug mode."); +// skip("This test fails on Windows when compiled in debug mode."); # endif - - const int num_tests = 7; - void *align_ptr; - for (int i=0; i<num_tests; i++) - { - align_ptr = ll_aligned_malloc_16(sizeof(MyVector4a)); - ensure("ll_aligned_malloc_16 failed", is_aligned(align_ptr,16)); - - align_ptr = ll_aligned_realloc_16(align_ptr,2*sizeof(MyVector4a), sizeof(MyVector4a)); - ensure("ll_aligned_realloc_16 failed", is_aligned(align_ptr,16)); - - ll_aligned_free_16(align_ptr); - - align_ptr = ll_aligned_malloc_32(sizeof(MyVector4a)); - ensure("ll_aligned_malloc_32 failed", is_aligned(align_ptr,32)); - ll_aligned_free_32(align_ptr); - } + + const int num_tests = 7; + void *align_ptr; + for (int i=0; i<num_tests; i++) + { + align_ptr = ll_aligned_malloc_16(sizeof(MyVector4a)); + ensure("ll_aligned_malloc_16 failed", is_aligned(align_ptr,16)); + + align_ptr = ll_aligned_realloc_16(align_ptr,2*sizeof(MyVector4a), sizeof(MyVector4a)); + ensure("ll_aligned_realloc_16 failed", is_aligned(align_ptr,16)); + + ll_aligned_free_16(align_ptr); + + align_ptr = ll_aligned_malloc_32(sizeof(MyVector4a)); + ensure("ll_aligned_malloc_32 failed", is_aligned(align_ptr,32)); + ll_aligned_free_32(align_ptr); + } } // In-place allocation of objects and arrays. template<> template<> void alignment_test_object_t::test<2>() { - MyVector4a vec1; - ensure("LLAlignment vec1 unaligned", is_aligned(&vec1,16)); - - MyVector4a veca[12]; - ensure("LLAlignment veca unaligned", is_aligned(veca,16)); + MyVector4a vec1; + ensure("LLAlignment vec1 unaligned", is_aligned(&vec1,16)); + + MyVector4a veca[12]; + ensure("LLAlignment veca unaligned", is_aligned(veca,16)); } // Heap allocation of objects and arrays. @@ -116,26 +116,26 @@ template<> template<> void alignment_test_object_t::test<3>() { # ifdef LL_DEBUG -// skip("This test fails on Windows when compiled in debug mode."); +// skip("This test fails on Windows when compiled in debug mode."); # endif - - const int ARR_SIZE = 7; - for(int i=0; i<ARR_SIZE; i++) - { - MyVector4a *vecp = new MyVector4a; - ensure("LLAlignment vecp unaligned", is_aligned(vecp,16)); - delete vecp; - } - - MyVector4a *veca = new MyVector4a[ARR_SIZE]; - //std::cout << "veca base is " << (S32) veca << std::endl; - ensure("LLAligment veca base", is_aligned(veca,16)); - for(int i=0; i<ARR_SIZE; i++) - { - std::cout << "veca[" << i << "]" << std::endl; - ensure("LLAlignment veca member unaligned", is_aligned(&veca[i],16)); - } - delete [] veca; + + const int ARR_SIZE = 7; + for(int i=0; i<ARR_SIZE; i++) + { + MyVector4a *vecp = new MyVector4a; + ensure("LLAlignment vecp unaligned", is_aligned(vecp,16)); + delete vecp; + } + + MyVector4a *veca = new MyVector4a[ARR_SIZE]; + //std::cout << "veca base is " << (S32) veca << std::endl; + ensure("LLAligment veca base", is_aligned(veca,16)); + for(int i=0; i<ARR_SIZE; i++) + { + std::cout << "veca[" << i << "]" << std::endl; + ensure("LLAlignment veca member unaligned", is_aligned(&veca[i],16)); + } + delete [] veca; } } diff --git a/indra/llmath/tests/llbbox_test.cpp b/indra/llmath/tests/llbbox_test.cpp index 373e2d02a0..bd6bd9e4b0 100644 --- a/indra/llmath/tests/llbbox_test.cpp +++ b/indra/llmath/tests/llbbox_test.cpp @@ -3,25 +3,25 @@ * @author Martin Reddy * @date 2009-06-25 * @brief Test for llbbox.cpp. - * + * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,330 +38,330 @@ namespace tut { - struct LLBBoxData - { - }; + struct LLBBoxData + { + }; - typedef test_group<LLBBoxData> factory; - typedef factory::object object; + typedef test_group<LLBBoxData> factory; + typedef factory::object object; } namespace { - tut::factory llbbox_test_factory("LLBBox"); + tut::factory llbbox_test_factory("LLBBox"); } namespace tut { - template<> template<> - void object::test<1>() - { - // - // test the default constructor - // - - LLBBox bbox1; - - ensure_equals("Default bbox min", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, 0.0f)); - ensure_equals("Default bbox max", bbox1.getMaxLocal(), LLVector3(0.0f, 0.0f, 0.0f)); - ensure_equals("Default bbox pos agent", bbox1.getPositionAgent(), LLVector3(0.0f, 0.0f, 0.0f)); - ensure_equals("Default bbox rotation", bbox1.getRotation(), LLQuaternion(0.0f, 0.0f, 0.0f, 1.0f)); - } - - template<> template<> - void object::test<2>() - { - // - // test the non-default constructor - // - - LLBBox bbox2(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(), - LLVector3(2.0f, 3.0f, 4.0f), LLVector3(4.0f, 5.0f, 6.0f)); - - ensure_equals("Custom bbox min", bbox2.getMinLocal(), LLVector3(2.0f, 3.0f, 4.0f)); - ensure_equals("Custom bbox max", bbox2.getMaxLocal(), LLVector3(4.0f, 5.0f, 6.0f)); - ensure_equals("Custom bbox pos agent", bbox2.getPositionAgent(), LLVector3(1.0f, 2.0f, 3.0f)); - ensure_equals("Custom bbox rotation", bbox2.getRotation(), LLQuaternion(0.0f, 0.0f, 0.0f, 1.0f)); - } - - template<> template<> - void object::test<3>() - { - // - // test the setMinLocal() method - // - LLBBox bbox2; - bbox2.setMinLocal(LLVector3(3.0f, 3.0f, 3.0f)); - ensure_equals("Custom bbox min (2)", bbox2.getMinLocal(), LLVector3(3.0f, 3.0f, 3.0f)); - } - - template<> template<> - void object::test<4>() - { - // - // test the setMaxLocal() method - // - LLBBox bbox2; - bbox2.setMaxLocal(LLVector3(5.0f, 5.0f, 5.0f)); - ensure_equals("Custom bbox max (2)", bbox2.getMaxLocal(), LLVector3(5.0f, 5.0f, 5.0f)); - } - - template<> template<> - void object::test<5>() - { - // - // test the getCenterLocal() method - // - - ensure_equals("Default bbox local center", LLBBox().getCenterLocal(), LLVector3(0.0f, 0.0f, 0.0f)); - - LLBBox bbox1(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(), - LLVector3(2.0f, 4.0f, 6.0f), LLVector3(4.0f, 6.0f, 8.0f)); - - ensure_equals("Custom bbox center local", bbox1.getCenterLocal(), LLVector3(3.0f, 5.0f, 7.0f)); - - LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(0.0f, 0.0f, 1.0f)), - LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f)); - - ensure_equals("Custom bbox center local with rot", bbox2.getCenterLocal(), LLVector3(3.0f, 3.0f, 3.0f)); - } - - template<> template<> - void object::test<6>() - { - // - // test the getCenterAgent() - // - - ensure_equals("Default bbox agent center", LLBBox().getCenterAgent(), LLVector3(0.0f, 0.0f, 0.0f)); - - LLBBox bbox1(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(), - LLVector3(2.0f, 4.0f, 6.0f), LLVector3(4.0f, 6.0f, 8.0f)); - - ensure_equals("Custom bbox center agent", bbox1.getCenterAgent(), LLVector3(4.0f, 7.0f, 10.0f)); - - LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(0.0f, 0.0f, 1.0f)), - LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f)); - - ensure("Custom bbox center agent with rot", APPROX_EQUAL(bbox2.getCenterAgent(), LLVector3(-2.0f, 4.0f, 4.0f))); - } - - template<> template<> - void object::test<7>() - { - // - // test the getExtentLocal() method - // - - ensure_equals("Default bbox local extent", LLBBox().getExtentLocal(), LLVector3(0.0f, 0.0f, 0.0f)); - - LLBBox bbox1(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(), - LLVector3(2.0f, 4.0f, 6.0f), LLVector3(4.0f, 6.0f, 8.0f)); - - ensure_equals("Custom bbox extent local", bbox1.getExtentLocal(), LLVector3(2.0f, 2.0f, 2.0f)); - - LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(0.0f, 0.0f, 1.0f)), - LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f)); - - ensure_equals("Custom bbox extent local with rot", bbox1.getExtentLocal(), LLVector3(2.0f, 2.0f, 2.0f)); - } - - template<> template<> - void object::test<8>() - { - // - // test the addPointLocal() method - // - - LLBBox bbox1; - bbox1.addPointLocal(LLVector3(1.0f, 1.0f, 1.0f)); - bbox1.addPointLocal(LLVector3(3.0f, 3.0f, 3.0f)); - - ensure_equals("addPointLocal center local (1)", bbox1.getCenterLocal(), LLVector3(2.0f, 2.0f, 2.0f)); - ensure_equals("addPointLocal center agent (1)", bbox1.getCenterAgent(), LLVector3(2.0f, 2.0f, 2.0f)); - ensure_equals("addPointLocal min (1)", bbox1.getMinLocal(), LLVector3(1.0f, 1.0f, 1.0f)); - ensure_equals("addPointLocal max (1)", bbox1.getMaxLocal(), LLVector3(3.0f, 3.0f, 3.0f)); - - bbox1.addPointLocal(LLVector3(0.0f, 0.0f, 0.0f)); - bbox1.addPointLocal(LLVector3(1.0f, 1.0f, 1.0f)); - bbox1.addPointLocal(LLVector3(2.0f, 2.0f, 2.0f)); - - ensure_equals("addPointLocal center local (2)", bbox1.getCenterLocal(), LLVector3(1.5f, 1.5f, 1.5f)); - ensure_equals("addPointLocal min (2)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, 0.0f)); - ensure_equals("addPointLocal max (2)", bbox1.getMaxLocal(), LLVector3(3.0f, 3.0f, 3.0f)); - } - - template<> template<> - void object::test<9>() - { - // - // test the addBBoxLocal() method - // - - LLBBox bbox1; - bbox1.addBBoxLocal(LLBBox(LLVector3(), LLQuaternion(), - LLVector3(0.0f, 0.0f, 0.0f), LLVector3(3.0f, 3.0f, 3.0f))); - - ensure_equals("addPointLocal center local (3)", bbox1.getCenterLocal(), LLVector3(1.5f, 1.5f, 1.5f)); - ensure_equals("addPointLocal min (3)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, 0.0f)); - ensure_equals("addPointLocal max (3)", bbox1.getMaxLocal(), LLVector3(3.0f, 3.0f, 3.0f)); - - bbox1.addBBoxLocal(LLBBox(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(), - LLVector3(5.0f, 5.0f, 5.0f), LLVector3(10.0f, 10.0f, 10.0f))); - - ensure_equals("addPointLocal center local (4)", bbox1.getCenterLocal(), LLVector3(5.0f, 5.0f, 5.0f)); - ensure_equals("addPointLocal center agent (4)", bbox1.getCenterAgent(), LLVector3(5.0f, 5.0f, 5.0f)); - ensure_equals("addPointLocal min (4)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, 0.0f)); - ensure_equals("addPointLocal max (4)", bbox1.getMaxLocal(), LLVector3(10.0f, 10.0f, 10.0f)); - } - - template<> template<> - void object::test<10>() - { - // - // test the addPointAgent() method - // - - LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(1.0, 0.0, 0.0, 1.0), - LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f)); - - bbox1.addPointAgent(LLVector3(1.0f, 1.0f, 1.0f)); - bbox1.addPointAgent(LLVector3(3.0f, 3.0f, 3.0f)); - - ensure_equals("addPointAgent center local (1)", bbox1.getCenterLocal(), LLVector3(2.0f, 2.0f, -2.0f)); - ensure_equals("addPointAgent center agent (1)", bbox1.getCenterAgent(), LLVector3(3.0f, 3.0f, 7.0f)); - ensure_equals("addPointAgent min (1)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, -4.0f)); - ensure_equals("addPointAgent max (1)", bbox1.getMaxLocal(), LLVector3(4.0f, 4.0f, 0.0f)); - } - - template<> template<> - void object::test<11>() - { - // - // test the addBBoxAgent() method - // - - LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(1.0, 0.0, 0.0, 1.0), - LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f)); - - bbox1.addPointAgent(LLVector3(1.0f, 1.0f, 1.0f)); - bbox1.addPointAgent(LLVector3(3.0f, 3.0f, 3.0f)); - - bbox1.addBBoxLocal(LLBBox(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(), - LLVector3(5.0f, 5.0f, 5.0f), LLVector3(10.0f, 10.0f, 10.0f))); - - ensure_equals("addPointAgent center local (2)", bbox1.getCenterLocal(), LLVector3(5.0f, 5.0f, 3.0f)); - ensure_equals("addPointAgent center agent (2)", bbox1.getCenterAgent(), LLVector3(6.0f, -10.0f, 8.0f)); - ensure_equals("addPointAgent min (2)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, -4.0f)); - ensure_equals("addPointAgent max (2)", bbox1.getMaxLocal(), LLVector3(10.0f, 10.0f, 10.0f)); - } - - template<> template<> - void object::test<12>() - { - // - // test the expand() method - // - - LLBBox bbox1; - bbox1.expand(0.0); - - ensure_equals("Zero-expanded Default BBox center", bbox1.getCenterLocal(), LLVector3(0.0f, 0.0f, 0.0f)); - - LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(), - LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f)); - bbox2.expand(0.0); - - ensure_equals("Zero-expanded center local", bbox2.getCenterLocal(), LLVector3(2.0f, 2.0f, 2.0f)); - ensure_equals("Zero-expanded center agent", bbox2.getCenterAgent(), LLVector3(3.0f, 3.0f, 3.0f)); - ensure_equals("Zero-expanded min", bbox2.getMinLocal(), LLVector3(1.0f, 1.0f, 1.0f)); - ensure_equals("Zero-expanded max", bbox2.getMaxLocal(), LLVector3(3.0f, 3.0f, 3.0f)); - - bbox2.expand(0.5); - - ensure_equals("Positive-expanded center", bbox2.getCenterLocal(), LLVector3(2.0f, 2.0f, 2.0f)); - ensure_equals("Positive-expanded min", bbox2.getMinLocal(), LLVector3(0.5f, 0.5f, 0.5f)); - ensure_equals("Positive-expanded max", bbox2.getMaxLocal(), LLVector3(3.5f, 3.5f, 3.5f)); - - bbox2.expand(-1.0); - - ensure_equals("Negative-expanded center", bbox2.getCenterLocal(), LLVector3(2.0f, 2.0f, 2.0f)); - ensure_equals("Negative-expanded min", bbox2.getMinLocal(), LLVector3(1.5f, 1.5f, 1.5f)); - ensure_equals("Negative-expanded max", bbox2.getMaxLocal(), LLVector3(2.5f, 2.5f, 2.5f)); - } - - template<> template<> - void object::test<13>() - { - // - // test the localToAgent() method - // - - LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(), - LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f)); - - ensure_equals("localToAgent(1,2,3)", bbox1.localToAgent(LLVector3(1.0f, 2.0f, 3.0f)), LLVector3(2.0f, 3.0f, 4.0f)); - - LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(1.0f, 0.0f, 0.0f)), - LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f)); - - ensure("localToAgent(1,2,3) rot", APPROX_EQUAL(bbox2.localToAgent(LLVector3(1.0f, 2.0f, 3.0f)), LLVector3(2.0f, -2.0f, 3.0f))); - } - - template<> template<> - void object::test<14>() - { - // - // test the agentToLocal() method - // - - LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(), - LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f)); - - ensure_equals("agentToLocal(1,2,3)", bbox1.agentToLocal(LLVector3(1.0f, 2.0f, 3.0f)), LLVector3(0.0f, 1.0f, 2.0f)); - ensure_equals("agentToLocal(localToAgent)", bbox1.agentToLocal(bbox1.localToAgent(LLVector3(1.0f, 2.0f, 3.0f))), - LLVector3(1.0f, 2.0f, 3.0f)); - - LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(1.0f, 0.0f, 0.0f)), - LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f)); - - ensure("agentToLocal(1,2,3) rot", APPROX_EQUAL(bbox2.agentToLocal(LLVector3(1.0f, 2.0f, 3.0f)), LLVector3(0.0f, 2.0f, -1.0f))); - ensure("agentToLocal(localToAgent) rot", APPROX_EQUAL(bbox2.agentToLocal(bbox2.localToAgent(LLVector3(1.0f, 2.0f, 3.0f))), - LLVector3(1.0f, 2.0f, 3.0f))); - } - - template<> template<> - void object::test<15>() - { - // - // test the containsPointLocal() method - // - - LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(), - LLVector3(1.0f, 2.0f, 3.0f), LLVector3(3.0f, 4.0f, 5.0f)); - - ensure("containsPointLocal(0,0,0)", bbox1.containsPointLocal(LLVector3(0.0f, 0.0f, 0.0f)) == false); - ensure("containsPointLocal(1,2,3)", bbox1.containsPointLocal(LLVector3(1.0f, 2.0f, 3.0f)) == true); - ensure("containsPointLocal(0.999,2,3)", bbox1.containsPointLocal(LLVector3(0.999f, 2.0f, 3.0f)) == false); - ensure("containsPointLocal(3,4,5)", bbox1.containsPointLocal(LLVector3(3.0f, 4.0f, 5.0f)) == true); - ensure("containsPointLocal(3,4,5.001)", bbox1.containsPointLocal(LLVector3(3.0f, 4.0f, 5.001f)) == false); - } - - template<> template<> - void object::test<16>() - { - // - // test the containsPointAgent() method - // - - LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(), - LLVector3(1.0f, 2.0f, 3.0f), LLVector3(3.0f, 4.0f, 5.0f)); - - ensure("containsPointAgent(0,0,0)", bbox1.containsPointAgent(LLVector3(0.0f, 0.0f, 0.0f)) == false); - ensure("containsPointAgent(2,3,4)", bbox1.containsPointAgent(LLVector3(2.0f, 3.0f, 4.0f)) == true); - ensure("containsPointAgent(2,2.999,4)", bbox1.containsPointAgent(LLVector3(2.0f, 2.999f, 4.0f)) == false); - ensure("containsPointAgent(4,5,6)", bbox1.containsPointAgent(LLVector3(4.0f, 5.0f, 6.0f)) == true); - ensure("containsPointAgent(4,5.001,6)", bbox1.containsPointAgent(LLVector3(4.0f, 5.001f, 6.0f)) == false); - } + template<> template<> + void object::test<1>() + { + // + // test the default constructor + // + + LLBBox bbox1; + + ensure_equals("Default bbox min", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, 0.0f)); + ensure_equals("Default bbox max", bbox1.getMaxLocal(), LLVector3(0.0f, 0.0f, 0.0f)); + ensure_equals("Default bbox pos agent", bbox1.getPositionAgent(), LLVector3(0.0f, 0.0f, 0.0f)); + ensure_equals("Default bbox rotation", bbox1.getRotation(), LLQuaternion(0.0f, 0.0f, 0.0f, 1.0f)); + } + + template<> template<> + void object::test<2>() + { + // + // test the non-default constructor + // + + LLBBox bbox2(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(), + LLVector3(2.0f, 3.0f, 4.0f), LLVector3(4.0f, 5.0f, 6.0f)); + + ensure_equals("Custom bbox min", bbox2.getMinLocal(), LLVector3(2.0f, 3.0f, 4.0f)); + ensure_equals("Custom bbox max", bbox2.getMaxLocal(), LLVector3(4.0f, 5.0f, 6.0f)); + ensure_equals("Custom bbox pos agent", bbox2.getPositionAgent(), LLVector3(1.0f, 2.0f, 3.0f)); + ensure_equals("Custom bbox rotation", bbox2.getRotation(), LLQuaternion(0.0f, 0.0f, 0.0f, 1.0f)); + } + + template<> template<> + void object::test<3>() + { + // + // test the setMinLocal() method + // + LLBBox bbox2; + bbox2.setMinLocal(LLVector3(3.0f, 3.0f, 3.0f)); + ensure_equals("Custom bbox min (2)", bbox2.getMinLocal(), LLVector3(3.0f, 3.0f, 3.0f)); + } + + template<> template<> + void object::test<4>() + { + // + // test the setMaxLocal() method + // + LLBBox bbox2; + bbox2.setMaxLocal(LLVector3(5.0f, 5.0f, 5.0f)); + ensure_equals("Custom bbox max (2)", bbox2.getMaxLocal(), LLVector3(5.0f, 5.0f, 5.0f)); + } + + template<> template<> + void object::test<5>() + { + // + // test the getCenterLocal() method + // + + ensure_equals("Default bbox local center", LLBBox().getCenterLocal(), LLVector3(0.0f, 0.0f, 0.0f)); + + LLBBox bbox1(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(), + LLVector3(2.0f, 4.0f, 6.0f), LLVector3(4.0f, 6.0f, 8.0f)); + + ensure_equals("Custom bbox center local", bbox1.getCenterLocal(), LLVector3(3.0f, 5.0f, 7.0f)); + + LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(0.0f, 0.0f, 1.0f)), + LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f)); + + ensure_equals("Custom bbox center local with rot", bbox2.getCenterLocal(), LLVector3(3.0f, 3.0f, 3.0f)); + } + + template<> template<> + void object::test<6>() + { + // + // test the getCenterAgent() + // + + ensure_equals("Default bbox agent center", LLBBox().getCenterAgent(), LLVector3(0.0f, 0.0f, 0.0f)); + + LLBBox bbox1(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(), + LLVector3(2.0f, 4.0f, 6.0f), LLVector3(4.0f, 6.0f, 8.0f)); + + ensure_equals("Custom bbox center agent", bbox1.getCenterAgent(), LLVector3(4.0f, 7.0f, 10.0f)); + + LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(0.0f, 0.0f, 1.0f)), + LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f)); + + ensure("Custom bbox center agent with rot", APPROX_EQUAL(bbox2.getCenterAgent(), LLVector3(-2.0f, 4.0f, 4.0f))); + } + + template<> template<> + void object::test<7>() + { + // + // test the getExtentLocal() method + // + + ensure_equals("Default bbox local extent", LLBBox().getExtentLocal(), LLVector3(0.0f, 0.0f, 0.0f)); + + LLBBox bbox1(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(), + LLVector3(2.0f, 4.0f, 6.0f), LLVector3(4.0f, 6.0f, 8.0f)); + + ensure_equals("Custom bbox extent local", bbox1.getExtentLocal(), LLVector3(2.0f, 2.0f, 2.0f)); + + LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(0.0f, 0.0f, 1.0f)), + LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f)); + + ensure_equals("Custom bbox extent local with rot", bbox1.getExtentLocal(), LLVector3(2.0f, 2.0f, 2.0f)); + } + + template<> template<> + void object::test<8>() + { + // + // test the addPointLocal() method + // + + LLBBox bbox1; + bbox1.addPointLocal(LLVector3(1.0f, 1.0f, 1.0f)); + bbox1.addPointLocal(LLVector3(3.0f, 3.0f, 3.0f)); + + ensure_equals("addPointLocal center local (1)", bbox1.getCenterLocal(), LLVector3(2.0f, 2.0f, 2.0f)); + ensure_equals("addPointLocal center agent (1)", bbox1.getCenterAgent(), LLVector3(2.0f, 2.0f, 2.0f)); + ensure_equals("addPointLocal min (1)", bbox1.getMinLocal(), LLVector3(1.0f, 1.0f, 1.0f)); + ensure_equals("addPointLocal max (1)", bbox1.getMaxLocal(), LLVector3(3.0f, 3.0f, 3.0f)); + + bbox1.addPointLocal(LLVector3(0.0f, 0.0f, 0.0f)); + bbox1.addPointLocal(LLVector3(1.0f, 1.0f, 1.0f)); + bbox1.addPointLocal(LLVector3(2.0f, 2.0f, 2.0f)); + + ensure_equals("addPointLocal center local (2)", bbox1.getCenterLocal(), LLVector3(1.5f, 1.5f, 1.5f)); + ensure_equals("addPointLocal min (2)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, 0.0f)); + ensure_equals("addPointLocal max (2)", bbox1.getMaxLocal(), LLVector3(3.0f, 3.0f, 3.0f)); + } + + template<> template<> + void object::test<9>() + { + // + // test the addBBoxLocal() method + // + + LLBBox bbox1; + bbox1.addBBoxLocal(LLBBox(LLVector3(), LLQuaternion(), + LLVector3(0.0f, 0.0f, 0.0f), LLVector3(3.0f, 3.0f, 3.0f))); + + ensure_equals("addPointLocal center local (3)", bbox1.getCenterLocal(), LLVector3(1.5f, 1.5f, 1.5f)); + ensure_equals("addPointLocal min (3)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, 0.0f)); + ensure_equals("addPointLocal max (3)", bbox1.getMaxLocal(), LLVector3(3.0f, 3.0f, 3.0f)); + + bbox1.addBBoxLocal(LLBBox(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(), + LLVector3(5.0f, 5.0f, 5.0f), LLVector3(10.0f, 10.0f, 10.0f))); + + ensure_equals("addPointLocal center local (4)", bbox1.getCenterLocal(), LLVector3(5.0f, 5.0f, 5.0f)); + ensure_equals("addPointLocal center agent (4)", bbox1.getCenterAgent(), LLVector3(5.0f, 5.0f, 5.0f)); + ensure_equals("addPointLocal min (4)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, 0.0f)); + ensure_equals("addPointLocal max (4)", bbox1.getMaxLocal(), LLVector3(10.0f, 10.0f, 10.0f)); + } + + template<> template<> + void object::test<10>() + { + // + // test the addPointAgent() method + // + + LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(1.0, 0.0, 0.0, 1.0), + LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f)); + + bbox1.addPointAgent(LLVector3(1.0f, 1.0f, 1.0f)); + bbox1.addPointAgent(LLVector3(3.0f, 3.0f, 3.0f)); + + ensure_equals("addPointAgent center local (1)", bbox1.getCenterLocal(), LLVector3(2.0f, 2.0f, -2.0f)); + ensure_equals("addPointAgent center agent (1)", bbox1.getCenterAgent(), LLVector3(3.0f, 3.0f, 7.0f)); + ensure_equals("addPointAgent min (1)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, -4.0f)); + ensure_equals("addPointAgent max (1)", bbox1.getMaxLocal(), LLVector3(4.0f, 4.0f, 0.0f)); + } + + template<> template<> + void object::test<11>() + { + // + // test the addBBoxAgent() method + // + + LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(1.0, 0.0, 0.0, 1.0), + LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f)); + + bbox1.addPointAgent(LLVector3(1.0f, 1.0f, 1.0f)); + bbox1.addPointAgent(LLVector3(3.0f, 3.0f, 3.0f)); + + bbox1.addBBoxLocal(LLBBox(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(), + LLVector3(5.0f, 5.0f, 5.0f), LLVector3(10.0f, 10.0f, 10.0f))); + + ensure_equals("addPointAgent center local (2)", bbox1.getCenterLocal(), LLVector3(5.0f, 5.0f, 3.0f)); + ensure_equals("addPointAgent center agent (2)", bbox1.getCenterAgent(), LLVector3(6.0f, -10.0f, 8.0f)); + ensure_equals("addPointAgent min (2)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, -4.0f)); + ensure_equals("addPointAgent max (2)", bbox1.getMaxLocal(), LLVector3(10.0f, 10.0f, 10.0f)); + } + + template<> template<> + void object::test<12>() + { + // + // test the expand() method + // + + LLBBox bbox1; + bbox1.expand(0.0); + + ensure_equals("Zero-expanded Default BBox center", bbox1.getCenterLocal(), LLVector3(0.0f, 0.0f, 0.0f)); + + LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(), + LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f)); + bbox2.expand(0.0); + + ensure_equals("Zero-expanded center local", bbox2.getCenterLocal(), LLVector3(2.0f, 2.0f, 2.0f)); + ensure_equals("Zero-expanded center agent", bbox2.getCenterAgent(), LLVector3(3.0f, 3.0f, 3.0f)); + ensure_equals("Zero-expanded min", bbox2.getMinLocal(), LLVector3(1.0f, 1.0f, 1.0f)); + ensure_equals("Zero-expanded max", bbox2.getMaxLocal(), LLVector3(3.0f, 3.0f, 3.0f)); + + bbox2.expand(0.5); + + ensure_equals("Positive-expanded center", bbox2.getCenterLocal(), LLVector3(2.0f, 2.0f, 2.0f)); + ensure_equals("Positive-expanded min", bbox2.getMinLocal(), LLVector3(0.5f, 0.5f, 0.5f)); + ensure_equals("Positive-expanded max", bbox2.getMaxLocal(), LLVector3(3.5f, 3.5f, 3.5f)); + + bbox2.expand(-1.0); + + ensure_equals("Negative-expanded center", bbox2.getCenterLocal(), LLVector3(2.0f, 2.0f, 2.0f)); + ensure_equals("Negative-expanded min", bbox2.getMinLocal(), LLVector3(1.5f, 1.5f, 1.5f)); + ensure_equals("Negative-expanded max", bbox2.getMaxLocal(), LLVector3(2.5f, 2.5f, 2.5f)); + } + + template<> template<> + void object::test<13>() + { + // + // test the localToAgent() method + // + + LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(), + LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f)); + + ensure_equals("localToAgent(1,2,3)", bbox1.localToAgent(LLVector3(1.0f, 2.0f, 3.0f)), LLVector3(2.0f, 3.0f, 4.0f)); + + LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(1.0f, 0.0f, 0.0f)), + LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f)); + + ensure("localToAgent(1,2,3) rot", APPROX_EQUAL(bbox2.localToAgent(LLVector3(1.0f, 2.0f, 3.0f)), LLVector3(2.0f, -2.0f, 3.0f))); + } + + template<> template<> + void object::test<14>() + { + // + // test the agentToLocal() method + // + + LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(), + LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f)); + + ensure_equals("agentToLocal(1,2,3)", bbox1.agentToLocal(LLVector3(1.0f, 2.0f, 3.0f)), LLVector3(0.0f, 1.0f, 2.0f)); + ensure_equals("agentToLocal(localToAgent)", bbox1.agentToLocal(bbox1.localToAgent(LLVector3(1.0f, 2.0f, 3.0f))), + LLVector3(1.0f, 2.0f, 3.0f)); + + LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(1.0f, 0.0f, 0.0f)), + LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f)); + + ensure("agentToLocal(1,2,3) rot", APPROX_EQUAL(bbox2.agentToLocal(LLVector3(1.0f, 2.0f, 3.0f)), LLVector3(0.0f, 2.0f, -1.0f))); + ensure("agentToLocal(localToAgent) rot", APPROX_EQUAL(bbox2.agentToLocal(bbox2.localToAgent(LLVector3(1.0f, 2.0f, 3.0f))), + LLVector3(1.0f, 2.0f, 3.0f))); + } + + template<> template<> + void object::test<15>() + { + // + // test the containsPointLocal() method + // + + LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(), + LLVector3(1.0f, 2.0f, 3.0f), LLVector3(3.0f, 4.0f, 5.0f)); + + ensure("containsPointLocal(0,0,0)", bbox1.containsPointLocal(LLVector3(0.0f, 0.0f, 0.0f)) == false); + ensure("containsPointLocal(1,2,3)", bbox1.containsPointLocal(LLVector3(1.0f, 2.0f, 3.0f)) == true); + ensure("containsPointLocal(0.999,2,3)", bbox1.containsPointLocal(LLVector3(0.999f, 2.0f, 3.0f)) == false); + ensure("containsPointLocal(3,4,5)", bbox1.containsPointLocal(LLVector3(3.0f, 4.0f, 5.0f)) == true); + ensure("containsPointLocal(3,4,5.001)", bbox1.containsPointLocal(LLVector3(3.0f, 4.0f, 5.001f)) == false); + } + + template<> template<> + void object::test<16>() + { + // + // test the containsPointAgent() method + // + + LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(), + LLVector3(1.0f, 2.0f, 3.0f), LLVector3(3.0f, 4.0f, 5.0f)); + + ensure("containsPointAgent(0,0,0)", bbox1.containsPointAgent(LLVector3(0.0f, 0.0f, 0.0f)) == false); + ensure("containsPointAgent(2,3,4)", bbox1.containsPointAgent(LLVector3(2.0f, 3.0f, 4.0f)) == true); + ensure("containsPointAgent(2,2.999,4)", bbox1.containsPointAgent(LLVector3(2.0f, 2.999f, 4.0f)) == false); + ensure("containsPointAgent(4,5,6)", bbox1.containsPointAgent(LLVector3(4.0f, 5.0f, 6.0f)) == true); + ensure("containsPointAgent(4,5.001,6)", bbox1.containsPointAgent(LLVector3(4.0f, 5.001f, 6.0f)) == false); + } } diff --git a/indra/llmath/tests/llbboxlocal_test.cpp b/indra/llmath/tests/llbboxlocal_test.cpp index f31e4126c4..120e18cadf 100644 --- a/indra/llmath/tests/llbboxlocal_test.cpp +++ b/indra/llmath/tests/llbboxlocal_test.cpp @@ -3,25 +3,25 @@ * @author Martin Reddy * @date 2009-06-25 * @brief Test for llbboxlocal.cpp. - * + * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -32,201 +32,201 @@ namespace tut { - struct LLBBoxLocalData - { - }; + struct LLBBoxLocalData + { + }; - typedef test_group<LLBBoxLocalData> factory; - typedef factory::object object; + typedef test_group<LLBBoxLocalData> factory; + typedef factory::object object; } namespace { - tut::factory llbboxlocal_test_factory("LLBBoxLocal"); + tut::factory llbboxlocal_test_factory("LLBBoxLocal"); } namespace tut { - template<> template<> - void object::test<1>() - { - // - // test the default constructor - // - - LLBBoxLocal bbox1; - - ensure_equals("Default bbox min", bbox1.getMin(), LLVector3(0.0f, 0.0f, 0.0f)); - ensure_equals("Default bbox max", bbox1.getMax(), LLVector3(0.0f, 0.0f, 0.0f)); - } - - template<> template<> - void object::test<2>() - { - // - // test the non-default constructor - // - - LLBBoxLocal bbox2(LLVector3(-1.0f, -2.0f, 0.0f), LLVector3(1.0f, 2.0f, 3.0f)); - - ensure_equals("Custom bbox min", bbox2.getMin(), LLVector3(-1.0f, -2.0f, 0.0f)); - ensure_equals("Custom bbox max", bbox2.getMax(), LLVector3(1.0f, 2.0f, 3.0f)); - } - - template<> template<> - void object::test<3>() - { - // - // test the setMin() - // - // N.B. no validation is currently performed to ensure that the min - // and max vectors are actually the min/max values. - // - - LLBBoxLocal bbox2; - bbox2.setMin(LLVector3(1.0f, 2.0f, 3.0f)); - - ensure_equals("Custom bbox min (2)", bbox2.getMin(), LLVector3(1.0f, 2.0f, 3.0f)); - } - - template<> template<> - void object::test<4>() - { - // - // test the setMax() - // - // N.B. no validation is currently performed to ensure that the min - // and max vectors are actually the min/max values. - // - - LLBBoxLocal bbox2; - bbox2.setMax(LLVector3(10.0f, 20.0f, 30.0f)); - - ensure_equals("Custom bbox max (2)", bbox2.getMax(), LLVector3(10.0f, 20.0f, 30.0f)); - } - - template<> template<> - void object::test<5>() - { - // - // test the getCenter() method - // - - ensure_equals("Default bbox center", LLBBoxLocal().getCenter(), LLVector3(0.0f, 0.0f, 0.0f)); - - LLBBoxLocal bbox1(LLVector3(-1.0f, -1.0f, -1.0f), LLVector3(0.0f, 0.0f, 0.0f)); - - ensure_equals("Custom bbox center", bbox1.getCenter(), LLVector3(-0.5f, -0.5f, -0.5f)); - - LLBBoxLocal bbox2(LLVector3(0.0f, 0.0f, 0.0f), LLVector3(-1.0f, -1.0f, -1.0f)); - - ensure_equals("Invalid bbox center", bbox2.getCenter(), LLVector3(-0.5f, -0.5f, -0.5f)); - } - - template<> template<> - void object::test<6>() - { - // - // test the getExtent() method - // - - LLBBoxLocal bbox2(LLVector3(0.0f, 0.0f, 0.0f), LLVector3(-1.0f, -1.0f, -1.0f)); - - ensure_equals("Default bbox extent", LLBBoxLocal().getExtent(), LLVector3(0.0f, 0.0f, 0.0f)); - - LLBBoxLocal bbox3(LLVector3(-1.0f, -1.0f, -1.0f), LLVector3(1.0f, 2.0f, 0.0f)); - - ensure_equals("Custom bbox extent", bbox3.getExtent(), LLVector3(2.0f, 3.0f, 1.0f)); - } - - template<> template<> - void object::test<7>() - { - // - // test the addPoint() method - // - // N.B. if you create an empty bbox and then add points, - // the vector (0, 0, 0) will always be part of the bbox. - // (Fixing this would require adding a bool to the class size). - // - - LLBBoxLocal bbox1; - bbox1.addPoint(LLVector3(-1.0f, -2.0f, -3.0f)); - bbox1.addPoint(LLVector3(3.0f, 4.0f, 5.0f)); - - ensure_equals("Custom BBox center (1)", bbox1.getCenter(), LLVector3(1.0f, 1.0f, 1.0f)); - ensure_equals("Custom BBox min (1)", bbox1.getMin(), LLVector3(-1.0f, -2.0f, -3.0f)); - ensure_equals("Custom BBox max (1)", bbox1.getMax(), LLVector3(3.0f, 4.0f, 5.0f)); - - bbox1.addPoint(LLVector3(0.0f, 0.0f, 0.0f)); - bbox1.addPoint(LLVector3(1.0f, 2.0f, 3.0f)); - bbox1.addPoint(LLVector3(2.0f, 2.0f, 2.0f)); - - ensure_equals("Custom BBox center (2)", bbox1.getCenter(), LLVector3(1.0f, 1.0f, 1.0f)); - ensure_equals("Custom BBox min (2)", bbox1.getMin(), LLVector3(-1.0f, -2.0f, -3.0f)); - ensure_equals("Custom BBox max (2)", bbox1.getMax(), LLVector3(3.0f, 4.0f, 5.0f)); - - bbox1.addPoint(LLVector3(5.0f, 5.0f, 5.0f)); - - ensure_equals("Custom BBox center (3)", bbox1.getCenter(), LLVector3(2.0f, 1.5f, 1.0f)); - ensure_equals("Custom BBox min (3)", bbox1.getMin(), LLVector3(-1.0f, -2.0f, -3.0f)); - ensure_equals("Custom BBox max (3)", bbox1.getMax(), LLVector3(5.0f, 5.0f, 5.0f)); - } - - template<> template<> - void object::test<8>() - { - // - // test the addBBox() methods - // - // N.B. if you create an empty bbox and then add points, - // the vector (0, 0, 0) will always be part of the bbox. - // (Fixing this would require adding a bool to the class size). - // - - LLBBoxLocal bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLVector3(2.0f, 2.0f, 2.0f)); - bbox2.addBBox(LLBBoxLocal(LLVector3(1.5f, 1.5f, 1.5f), LLVector3(3.0f, 3.0f, 3.0f))); - - ensure_equals("Custom BBox center (4)", bbox2.getCenter(), LLVector3(2.0f, 2.0f, 2.0f)); - ensure_equals("Custom BBox min (4)", bbox2.getMin(), LLVector3(1.0f, 1.0f, 1.0f)); - ensure_equals("Custom BBox max (4)", bbox2.getMax(), LLVector3(3.0f, 3.0f, 3.0f)); - - bbox2.addBBox(LLBBoxLocal(LLVector3(-1.0f, -1.0f, -1.0f), LLVector3(0.0f, 0.0f, 0.0f))); - - ensure_equals("Custom BBox center (5)", bbox2.getCenter(), LLVector3(1.0f, 1.0f, 1.0f)); - ensure_equals("Custom BBox min (5)", bbox2.getMin(), LLVector3(-1.0f, -1.0f, -1.0f)); - ensure_equals("Custom BBox max (5)", bbox2.getMax(), LLVector3(3.0f, 3.0f, 3.0f)); - } - - template<> template<> - void object::test<9>() - { - // - // test the expand() method - // - - LLBBoxLocal bbox1; - bbox1.expand(0.0f); - - ensure_equals("Zero-expanded Default BBox center", bbox1.getCenter(), LLVector3(0.0f, 0.0f, 0.0f)); - - LLBBoxLocal bbox2(LLVector3(1.0f, 2.0f, 3.0f), LLVector3(3.0f, 4.0f, 5.0f)); - bbox2.expand(0.0f); - - ensure_equals("Zero-expanded BBox center", bbox2.getCenter(), LLVector3(2.0f, 3.0f, 4.0f)); - ensure_equals("Zero-expanded BBox min", bbox2.getMin(), LLVector3(1.0f, 2.0f, 3.0f)); - ensure_equals("Zero-expanded BBox max", bbox2.getMax(), LLVector3(3.0f, 4.0f, 5.0f)); - - bbox2.expand(0.5f); - - ensure_equals("Positive-expanded BBox center", bbox2.getCenter(), LLVector3(2.0f, 3.0f, 4.0f)); - ensure_equals("Positive-expanded BBox min", bbox2.getMin(), LLVector3(0.5f, 1.5f, 2.5f)); - ensure_equals("Positive-expanded BBox max", bbox2.getMax(), LLVector3(3.5f, 4.5f, 5.5f)); - - bbox2.expand(-1.0f); - - ensure_equals("Negative-expanded BBox center", bbox2.getCenter(), LLVector3(2.0f, 3.0f, 4.0f)); - ensure_equals("Negative-expanded BBox min", bbox2.getMin(), LLVector3(1.5f, 2.5f, 3.5f)); - ensure_equals("Negative-expanded BBox max", bbox2.getMax(), LLVector3(2.5f, 3.5f, 4.5f)); - } + template<> template<> + void object::test<1>() + { + // + // test the default constructor + // + + LLBBoxLocal bbox1; + + ensure_equals("Default bbox min", bbox1.getMin(), LLVector3(0.0f, 0.0f, 0.0f)); + ensure_equals("Default bbox max", bbox1.getMax(), LLVector3(0.0f, 0.0f, 0.0f)); + } + + template<> template<> + void object::test<2>() + { + // + // test the non-default constructor + // + + LLBBoxLocal bbox2(LLVector3(-1.0f, -2.0f, 0.0f), LLVector3(1.0f, 2.0f, 3.0f)); + + ensure_equals("Custom bbox min", bbox2.getMin(), LLVector3(-1.0f, -2.0f, 0.0f)); + ensure_equals("Custom bbox max", bbox2.getMax(), LLVector3(1.0f, 2.0f, 3.0f)); + } + + template<> template<> + void object::test<3>() + { + // + // test the setMin() + // + // N.B. no validation is currently performed to ensure that the min + // and max vectors are actually the min/max values. + // + + LLBBoxLocal bbox2; + bbox2.setMin(LLVector3(1.0f, 2.0f, 3.0f)); + + ensure_equals("Custom bbox min (2)", bbox2.getMin(), LLVector3(1.0f, 2.0f, 3.0f)); + } + + template<> template<> + void object::test<4>() + { + // + // test the setMax() + // + // N.B. no validation is currently performed to ensure that the min + // and max vectors are actually the min/max values. + // + + LLBBoxLocal bbox2; + bbox2.setMax(LLVector3(10.0f, 20.0f, 30.0f)); + + ensure_equals("Custom bbox max (2)", bbox2.getMax(), LLVector3(10.0f, 20.0f, 30.0f)); + } + + template<> template<> + void object::test<5>() + { + // + // test the getCenter() method + // + + ensure_equals("Default bbox center", LLBBoxLocal().getCenter(), LLVector3(0.0f, 0.0f, 0.0f)); + + LLBBoxLocal bbox1(LLVector3(-1.0f, -1.0f, -1.0f), LLVector3(0.0f, 0.0f, 0.0f)); + + ensure_equals("Custom bbox center", bbox1.getCenter(), LLVector3(-0.5f, -0.5f, -0.5f)); + + LLBBoxLocal bbox2(LLVector3(0.0f, 0.0f, 0.0f), LLVector3(-1.0f, -1.0f, -1.0f)); + + ensure_equals("Invalid bbox center", bbox2.getCenter(), LLVector3(-0.5f, -0.5f, -0.5f)); + } + + template<> template<> + void object::test<6>() + { + // + // test the getExtent() method + // + + LLBBoxLocal bbox2(LLVector3(0.0f, 0.0f, 0.0f), LLVector3(-1.0f, -1.0f, -1.0f)); + + ensure_equals("Default bbox extent", LLBBoxLocal().getExtent(), LLVector3(0.0f, 0.0f, 0.0f)); + + LLBBoxLocal bbox3(LLVector3(-1.0f, -1.0f, -1.0f), LLVector3(1.0f, 2.0f, 0.0f)); + + ensure_equals("Custom bbox extent", bbox3.getExtent(), LLVector3(2.0f, 3.0f, 1.0f)); + } + + template<> template<> + void object::test<7>() + { + // + // test the addPoint() method + // + // N.B. if you create an empty bbox and then add points, + // the vector (0, 0, 0) will always be part of the bbox. + // (Fixing this would require adding a bool to the class size). + // + + LLBBoxLocal bbox1; + bbox1.addPoint(LLVector3(-1.0f, -2.0f, -3.0f)); + bbox1.addPoint(LLVector3(3.0f, 4.0f, 5.0f)); + + ensure_equals("Custom BBox center (1)", bbox1.getCenter(), LLVector3(1.0f, 1.0f, 1.0f)); + ensure_equals("Custom BBox min (1)", bbox1.getMin(), LLVector3(-1.0f, -2.0f, -3.0f)); + ensure_equals("Custom BBox max (1)", bbox1.getMax(), LLVector3(3.0f, 4.0f, 5.0f)); + + bbox1.addPoint(LLVector3(0.0f, 0.0f, 0.0f)); + bbox1.addPoint(LLVector3(1.0f, 2.0f, 3.0f)); + bbox1.addPoint(LLVector3(2.0f, 2.0f, 2.0f)); + + ensure_equals("Custom BBox center (2)", bbox1.getCenter(), LLVector3(1.0f, 1.0f, 1.0f)); + ensure_equals("Custom BBox min (2)", bbox1.getMin(), LLVector3(-1.0f, -2.0f, -3.0f)); + ensure_equals("Custom BBox max (2)", bbox1.getMax(), LLVector3(3.0f, 4.0f, 5.0f)); + + bbox1.addPoint(LLVector3(5.0f, 5.0f, 5.0f)); + + ensure_equals("Custom BBox center (3)", bbox1.getCenter(), LLVector3(2.0f, 1.5f, 1.0f)); + ensure_equals("Custom BBox min (3)", bbox1.getMin(), LLVector3(-1.0f, -2.0f, -3.0f)); + ensure_equals("Custom BBox max (3)", bbox1.getMax(), LLVector3(5.0f, 5.0f, 5.0f)); + } + + template<> template<> + void object::test<8>() + { + // + // test the addBBox() methods + // + // N.B. if you create an empty bbox and then add points, + // the vector (0, 0, 0) will always be part of the bbox. + // (Fixing this would require adding a bool to the class size). + // + + LLBBoxLocal bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLVector3(2.0f, 2.0f, 2.0f)); + bbox2.addBBox(LLBBoxLocal(LLVector3(1.5f, 1.5f, 1.5f), LLVector3(3.0f, 3.0f, 3.0f))); + + ensure_equals("Custom BBox center (4)", bbox2.getCenter(), LLVector3(2.0f, 2.0f, 2.0f)); + ensure_equals("Custom BBox min (4)", bbox2.getMin(), LLVector3(1.0f, 1.0f, 1.0f)); + ensure_equals("Custom BBox max (4)", bbox2.getMax(), LLVector3(3.0f, 3.0f, 3.0f)); + + bbox2.addBBox(LLBBoxLocal(LLVector3(-1.0f, -1.0f, -1.0f), LLVector3(0.0f, 0.0f, 0.0f))); + + ensure_equals("Custom BBox center (5)", bbox2.getCenter(), LLVector3(1.0f, 1.0f, 1.0f)); + ensure_equals("Custom BBox min (5)", bbox2.getMin(), LLVector3(-1.0f, -1.0f, -1.0f)); + ensure_equals("Custom BBox max (5)", bbox2.getMax(), LLVector3(3.0f, 3.0f, 3.0f)); + } + + template<> template<> + void object::test<9>() + { + // + // test the expand() method + // + + LLBBoxLocal bbox1; + bbox1.expand(0.0f); + + ensure_equals("Zero-expanded Default BBox center", bbox1.getCenter(), LLVector3(0.0f, 0.0f, 0.0f)); + + LLBBoxLocal bbox2(LLVector3(1.0f, 2.0f, 3.0f), LLVector3(3.0f, 4.0f, 5.0f)); + bbox2.expand(0.0f); + + ensure_equals("Zero-expanded BBox center", bbox2.getCenter(), LLVector3(2.0f, 3.0f, 4.0f)); + ensure_equals("Zero-expanded BBox min", bbox2.getMin(), LLVector3(1.0f, 2.0f, 3.0f)); + ensure_equals("Zero-expanded BBox max", bbox2.getMax(), LLVector3(3.0f, 4.0f, 5.0f)); + + bbox2.expand(0.5f); + + ensure_equals("Positive-expanded BBox center", bbox2.getCenter(), LLVector3(2.0f, 3.0f, 4.0f)); + ensure_equals("Positive-expanded BBox min", bbox2.getMin(), LLVector3(0.5f, 1.5f, 2.5f)); + ensure_equals("Positive-expanded BBox max", bbox2.getMax(), LLVector3(3.5f, 4.5f, 5.5f)); + + bbox2.expand(-1.0f); + + ensure_equals("Negative-expanded BBox center", bbox2.getCenter(), LLVector3(2.0f, 3.0f, 4.0f)); + ensure_equals("Negative-expanded BBox min", bbox2.getMin(), LLVector3(1.5f, 2.5f, 3.5f)); + ensure_equals("Negative-expanded BBox max", bbox2.getMax(), LLVector3(2.5f, 3.5f, 4.5f)); + } } diff --git a/indra/llmath/tests/llmodularmath_test.cpp b/indra/llmath/tests/llmodularmath_test.cpp index 063d3ef79f..399b3af05d 100644 --- a/indra/llmath/tests/llmodularmath_test.cpp +++ b/indra/llmath/tests/llmodularmath_test.cpp @@ -7,25 +7,25 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ - + #include "linden_common.h" #include "../llmodularmath.h" @@ -34,43 +34,43 @@ namespace tut { - struct modularmath_data - { - }; - typedef test_group<modularmath_data> modularmath_test; - typedef modularmath_test::object modularmath_object; - tut::modularmath_test modularmath_testcase("LLModularMath"); + struct modularmath_data + { + }; + typedef test_group<modularmath_data> modularmath_test; + typedef modularmath_test::object modularmath_object; + tut::modularmath_test modularmath_testcase("LLModularMath"); - template<> template<> - void modularmath_object::test<1>() - { - // lhs < rhs - const U32 lhs = 0x000001; - const U32 rhs = 0xFFFFFF; - const U32 width = 24; - U32 result = LLModularMath::subtract<width>(lhs, rhs); - ensure_equals("diff(0x000001, 0xFFFFFF, 24)", result, 2); - } + template<> template<> + void modularmath_object::test<1>() + { + // lhs < rhs + const U32 lhs = 0x000001; + const U32 rhs = 0xFFFFFF; + const U32 width = 24; + U32 result = LLModularMath::subtract<width>(lhs, rhs); + ensure_equals("diff(0x000001, 0xFFFFFF, 24)", result, 2); + } - template<> template<> - void modularmath_object::test<2>() - { - // lhs > rhs - const U32 lhs = 0x000002; - const U32 rhs = 0x000001; - const U32 width = 24; - U32 result = LLModularMath::subtract<width>(lhs, rhs); - ensure_equals("diff(0x000002, 0x000001, 24)", result, 1); - } + template<> template<> + void modularmath_object::test<2>() + { + // lhs > rhs + const U32 lhs = 0x000002; + const U32 rhs = 0x000001; + const U32 width = 24; + U32 result = LLModularMath::subtract<width>(lhs, rhs); + ensure_equals("diff(0x000002, 0x000001, 24)", result, 1); + } - template<> template<> - void modularmath_object::test<3>() - { - // lhs == rhs - const U32 lhs = 0xABCDEF; - const U32 rhs = 0xABCDEF; - const U32 width = 24; - U32 result = LLModularMath::subtract<width>(lhs, rhs); - ensure_equals("diff(0xABCDEF, 0xABCDEF, 24)", result, 0); - } + template<> template<> + void modularmath_object::test<3>() + { + // lhs == rhs + const U32 lhs = 0xABCDEF; + const U32 rhs = 0xABCDEF; + const U32 width = 24; + U32 result = LLModularMath::subtract<width>(lhs, rhs); + ensure_equals("diff(0xABCDEF, 0xABCDEF, 24)", result, 0); + } } diff --git a/indra/llmath/tests/llquaternion_test.cpp b/indra/llmath/tests/llquaternion_test.cpp index 3490829743..aa3c0ad843 100644 --- a/indra/llmath/tests/llquaternion_test.cpp +++ b/indra/llmath/tests/llquaternion_test.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llquaternion_test.cpp * @author Adroit * @date 2007-03 @@ -7,21 +7,21 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,623 +38,623 @@ namespace tut { - struct llquat_test - { - }; - typedef test_group<llquat_test> llquat_test_t; - typedef llquat_test_t::object llquat_test_object_t; - tut::llquat_test_t tut_llquat_test("LLQuaternion"); - - //test case for LLQuaternion::LLQuaternion(void) fn. - template<> template<> - void llquat_test_object_t::test<1>() - { - LLQuaternion llquat; - ensure("LLQuaternion::LLQuaternion() failed", 0.f == llquat.mQ[0] && - 0.f == llquat.mQ[1] && - 0.f == llquat.mQ[2] && - 1.f == llquat.mQ[3]); - } - - //test case for explicit LLQuaternion(const LLMatrix4 &mat) fn. - template<> template<> - void llquat_test_object_t::test<2>() - { - LLMatrix4 llmat; - LLVector4 vector1(2.0f, 1.0f, 3.0f, 6.0f); - LLVector4 vector2(5.0f, 6.0f, 0.0f, 1.0f); - LLVector4 vector3(2.0f, 1.0f, 2.0f, 9.0f); - LLVector4 vector4(3.0f, 8.0f, 1.0f, 5.0f); - - llmat.initRows(vector1, vector2, vector3, vector4); - ensure("explicit LLQuaternion(const LLMatrix4 &mat) failed", 2.0f == llmat.mMatrix[0][0] && - 1.0f == llmat.mMatrix[0][1] && - 3.0f == llmat.mMatrix[0][2] && - 6.0f == llmat.mMatrix[0][3] && - 5.0f == llmat.mMatrix[1][0] && - 6.0f == llmat.mMatrix[1][1] && - 0.0f == llmat.mMatrix[1][2] && - 1.0f == llmat.mMatrix[1][3] && - 2.0f == llmat.mMatrix[2][0] && - 1.0f == llmat.mMatrix[2][1] && - 2.0f == llmat.mMatrix[2][2] && - 9.0f == llmat.mMatrix[2][3] && - 3.0f == llmat.mMatrix[3][0] && - 8.0f == llmat.mMatrix[3][1] && - 1.0f == llmat.mMatrix[3][2] && - 5.0f == llmat.mMatrix[3][3]); - } - - template<> template<> - void llquat_test_object_t::test<3>() - { - LLMatrix3 llmat; - - LLVector3 vect1(3.4028234660000000f , 234.56f, 4234.442234f); - LLVector3 vect2(741.434f, 23.00034f, 6567.223423f); - LLVector3 vect3(566.003034f, 12.98705f, 234.764423f); - llmat.setRows(vect1, vect2, vect3); - - ensure("LLMatrix3::setRows fn failed.", 3.4028234660000000f == llmat.mMatrix[0][0] && - 234.56f == llmat.mMatrix[0][1] && - 4234.442234f == llmat.mMatrix[0][2] && - 741.434f == llmat.mMatrix[1][0] && - 23.00034f == llmat.mMatrix[1][1] && - 6567.223423f == llmat.mMatrix[1][2] && - 566.003034f == llmat.mMatrix[2][0] && - 12.98705f == llmat.mMatrix[2][1] && - 234.764423f == llmat.mMatrix[2][2]); - } - - //test case for LLQuaternion(F32 x, F32 y, F32 z, F32 w), setQuatInit() and normQuat() fns. - template<> template<> - void llquat_test_object_t::test<4>() - { - F32 x_val = 3.0f; - F32 y_val = 2.0f; - F32 z_val = 6.0f; - F32 w_val = 1.0f; - - LLQuaternion res_quat; - res_quat.setQuatInit(x_val, y_val, z_val, w_val); - res_quat.normQuat(); - - ensure("LLQuaternion::normQuat() fn failed", - is_approx_equal(0.42426407f, res_quat.mQ[0]) && - is_approx_equal(0.28284273f, res_quat.mQ[1]) && - is_approx_equal(0.84852815f, res_quat.mQ[2]) && - is_approx_equal(0.14142136f, res_quat.mQ[3])); - - x_val = 0.0f; - y_val = 0.0f; - z_val = 0.0f; - w_val = 0.0f; - - res_quat.setQuatInit(x_val, y_val, z_val, w_val); - res_quat.normQuat(); - - ensure("LLQuaternion::normQuat() fn. failed.", - is_approx_equal(0.0f, res_quat.mQ[0]) && - is_approx_equal(0.0f, res_quat.mQ[1]) && - is_approx_equal(0.0f, res_quat.mQ[2]) && - is_approx_equal(1.0f, res_quat.mQ[3])); - - - ensure("LLQuaternion::normQuat() fn. failed.", - is_approx_equal(0.0f, res_quat.mQ[0]) && - is_approx_equal(0.0f, res_quat.mQ[1]) && - is_approx_equal(0.0f, res_quat.mQ[2]) && - is_approx_equal(1.0f, res_quat.mQ[3])); - } - - //test case for conjQuat() and transQuat() fns. - template<> template<> - void llquat_test_object_t::test<5>() - { - F32 x_val = 3.0f; - F32 y_val = 2.0f; - F32 z_val = 6.0f; - F32 w_val = 1.0f; - - LLQuaternion res_quat; - LLQuaternion result, result1; - result1 = result = res_quat.setQuatInit(x_val, y_val, z_val, w_val); - - result.conjQuat(); - result1.transQuat(); - - ensure("LLQuaternion::conjQuat and LLQuaternion::transQuat failed ", - is_approx_equal(result1.mQ[0], result.mQ[0]) && - is_approx_equal(result1.mQ[1], result.mQ[1]) && - is_approx_equal(result1.mQ[2], result.mQ[2])); - - } - - //test case for dot(const LLQuaternion &a, const LLQuaternion &b) fn. - template<> template<> - void llquat_test_object_t::test<6>() - { - LLQuaternion quat1(3.0f, 2.0f, 6.0f, 0.0f), quat2(1.0f, 1.0f, 1.0f, 1.0f); - ensure("1. The two values are different", ll_round(12.000000f, 2) == ll_round(dot(quat1, quat2), 2)); - - LLQuaternion quat0(3.0f, 9.334f, 34.5f, 23.0f), quat(34.5f, 23.23f, 2.0f, 45.5f); - ensure("2. The two values are different", ll_round(1435.828807f, 2) == ll_round(dot(quat0, quat), 2)); - } - - //test case for LLQuaternion &LLQuaternion::constrain(F32 radians) fn. - template<> template<> - void llquat_test_object_t::test<7>() - { - F32 radian = 60.0f; - LLQuaternion quat(3.0f, 2.0f, 6.0f, 0.0f); - LLQuaternion quat1; - quat1 = quat.constrain(radian); - ensure("1. LLQuaternion::constrain(F32 radians) failed", - is_approx_equal_fraction(-0.423442f, quat1.mQ[0], 8) && - is_approx_equal_fraction(-0.282295f, quat1.mQ[1], 8) && - is_approx_equal_fraction(-0.846884f, quat1.mQ[2], 8) && - is_approx_equal_fraction(0.154251f, quat1.mQ[3], 8)); - - - radian = 30.0f; - LLQuaternion quat0(37.50f, 12.0f, 86.023f, 40.32f); - quat1 = quat0.constrain(radian); - - ensure("2. LLQuaternion::constrain(F32 radians) failed", - is_approx_equal_fraction(37.500000f, quat1.mQ[0], 8) && - is_approx_equal_fraction(12.0000f, quat1.mQ[1], 8) && - is_approx_equal_fraction(86.0230f, quat1.mQ[2], 8) && - is_approx_equal_fraction(40.320000f, quat1.mQ[3], 8)); - } - - template<> template<> - void llquat_test_object_t::test<8>() - { - F32 value1 = 15.0f; - LLQuaternion quat1(1.0f, 2.0f, 4.0f, 1.0f); - LLQuaternion quat2(4.0f, 3.0f, 6.5f, 9.7f); - LLQuaternion res_lerp, res_slerp, res_nlerp; - - //test case for lerp(F32 t, const LLQuaternion &q) fn. - res_lerp = lerp(value1, quat1); - ensure("1. LLQuaternion lerp(F32 t, const LLQuaternion &q) failed", - is_approx_equal_fraction(0.181355f, res_lerp.mQ[0], 16) && - is_approx_equal_fraction(0.362711f, res_lerp.mQ[1], 16) && - is_approx_equal_fraction(0.725423f, res_lerp.mQ[2], 16) && - is_approx_equal_fraction(0.556158f, res_lerp.mQ[3], 16)); - - //test case for lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q) fn. - res_lerp = lerp(value1, quat1, quat2); - ensure("2. LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q) failed", - is_approx_equal_fraction(0.314306f, res_lerp.mQ[0], 16) && - is_approx_equal_fraction(0.116156f, res_lerp.mQ[1], 16) && - is_approx_equal_fraction(0.283559f, res_lerp.mQ[2], 16) && - is_approx_equal_fraction(0.898506f, res_lerp.mQ[3], 16)); - - //test case for slerp( F32 u, const LLQuaternion &a, const LLQuaternion &b ) fn. - res_slerp = slerp(value1, quat1, quat2); - ensure("3. LLQuaternion slerp( F32 u, const LLQuaternion &a, const LLQuaternion &b) failed", - is_approx_equal_fraction(46.000f, res_slerp.mQ[0], 16) && - is_approx_equal_fraction(17.00f, res_slerp.mQ[1], 16) && - is_approx_equal_fraction(41.5f, res_slerp.mQ[2], 16) && - is_approx_equal_fraction(131.5f, res_slerp.mQ[3], 16)); - - //test case for nlerp(F32 t, const LLQuaternion &a, const LLQuaternion &b) fn. - res_nlerp = nlerp(value1, quat1, quat2); - ensure("4. LLQuaternion nlerp(F32 t, const LLQuaternion &a, const LLQuaternion &b) failed", - is_approx_equal_fraction(0.314306f, res_nlerp.mQ[0], 16) && - is_approx_equal_fraction(0.116157f, res_nlerp.mQ[1], 16) && - is_approx_equal_fraction(0.283559f, res_nlerp.mQ[2], 16) && - is_approx_equal_fraction(0.898506f, res_nlerp.mQ[3], 16)); - - //test case for nlerp(F32 t, const LLQuaternion &q) fn. - res_slerp = slerp(value1, quat1); - ensure("5. LLQuaternion slerp(F32 t, const LLQuaternion &q) failed", - is_approx_equal_fraction(1.0f, res_slerp.mQ[0], 16) && - is_approx_equal_fraction(2.0f, res_slerp.mQ[1], 16) && - is_approx_equal_fraction(4.0000f, res_slerp.mQ[2], 16) && - is_approx_equal_fraction(1.000f, res_slerp.mQ[3], 16)); - - LLQuaternion quat3(2.0f, 1.0f, 5.5f, 10.5f); - LLQuaternion res_nlerp1; - value1 = 100.0f; - res_nlerp1 = nlerp(value1, quat3); - ensure("6. LLQuaternion nlerp(F32 t, const LLQuaternion &q) failed", - is_approx_equal_fraction(0.268245f, res_nlerp1.mQ[0], 16) && is_approx_equal_fraction(0.134122f, res_nlerp1.mQ[1], 2) && - is_approx_equal_fraction(0.737673f, res_nlerp1.mQ[2], 16) && - is_approx_equal_fraction(0.604892f, res_nlerp1.mQ[3], 16)); - - //test case for lerp(F32 t, const LLQuaternion &q) fn. - res_lerp = lerp(value1, quat2); - ensure("7. LLQuaternion lerp(F32 t, const LLQuaternion &q) failed", - is_approx_equal_fraction(0.404867f, res_lerp.mQ[0], 16) && - is_approx_equal_fraction(0.303650f, res_lerp.mQ[1], 16) && - is_approx_equal_fraction(0.657909f, res_lerp.mQ[2], 16) && - is_approx_equal_fraction(0.557704f, res_lerp.mQ[3], 16)); - - } - - template<> template<> - void llquat_test_object_t::test<9>() - { - //test case for LLQuaternion operator*(const LLQuaternion &a, const LLQuaternion &b) fn - LLQuaternion quat1(1.0f, 2.5f, 3.5f, 5.5f); - LLQuaternion quat2(4.0f, 3.0f, 5.0f, 1.0f); - LLQuaternion result = quat1 * quat2; - ensure("1. LLQuaternion Operator* failed", (21.0f == result.mQ[0]) && - (10.0f == result.mQ[1]) && - (38.0f == result.mQ[2]) && - (-23.5f == result.mQ[3])); - - LLQuaternion quat3(2341.340f, 2352.345f, 233.25f, 7645.5f); - LLQuaternion quat4(674.067f, 893.0897f, 578.0f, 231.0f); - result = quat3 * quat4; - ensure("2. LLQuaternion Operator* failed", (4543086.5f == result.mQ[0]) && - (8567578.0f == result.mQ[1]) && - (3967591.25f == result.mQ[2]) && - is_approx_equal(-2047783.25f, result.mQ[3])); - - //inline LLQuaternion operator+(const LLQuaternion &a, const LLQuaternion &b)fn. - result = quat1 + quat2; - ensure("3. LLQuaternion operator+ failed", (5.0f == result.mQ[0]) && - (5.5f == result.mQ[1]) && - (8.5f == result.mQ[2]) && - (6.5f == result.mQ[3])); - - result = quat3 + quat4; - ensure( - "4. LLQuaternion operator+ failed", - is_approx_equal(3015.407227f, result.mQ[0]) && - is_approx_equal(3245.434570f, result.mQ[1]) && - (811.25f == result.mQ[2]) && - (7876.5f == result.mQ[3])); - - //inline LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b) fn - result = quat1 - quat2; - ensure( - "5. LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b) failed", - (-3.0f == result.mQ[0]) && - (-0.5f == result.mQ[1]) && - (-1.5f == result.mQ[2]) && - (4.5f == result.mQ[3])); - - result = quat3 - quat4; - ensure( - "6. LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b) failed", - is_approx_equal(1667.273071f, result.mQ[0]) && - is_approx_equal(1459.255249f, result.mQ[1]) && - (-344.75f == result.mQ[2]) && - (7414.50f == result.mQ[3])); - } - - //test case for LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot) fn. - template<> template<> - void llquat_test_object_t::test<10>() - { - LLVector4 vect(12.0f, 5.0f, 60.0f, 75.1f); - LLQuaternion quat(2323.034f, 23.5f, 673.23f, 57667.5f); - LLVector4 result = vect * quat; - ensure( - "1. LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot) failed", - is_approx_equal(39928406016.0f, result.mV[0]) && - // gcc on x86 actually gives us more precision than we were expecting, verified with -ffloat-store - we forgive this - (1457802240.0f >= result.mV[1]) && // gcc+x86+linux - (1457800960.0f <= result.mV[1]) && // elsewhere - is_approx_equal(200580612096.0f, result.mV[2]) && - (75.099998f == result.mV[3])); - - LLVector4 vect1(22.0f, 45.0f, 40.0f, 78.1f); - LLQuaternion quat1(2.034f, 45.5f, 37.23f, 7.5f); - result = vect1 * quat1; - ensure( - "2. LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot) failed", - is_approx_equal(-58153.5390f, result.mV[0]) && - (183787.8125f == result.mV[1]) && - (116864.164063f == result.mV[2]) && - (78.099998f == result.mV[3])); - } - - //test case for LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot) fn. - template<> template<> - void llquat_test_object_t::test<11>() - { - LLVector3 vect(12.0f, 5.0f, 60.0f); - LLQuaternion quat(23.5f, 6.5f, 3.23f, 56.5f); - LLVector3 result = vect * quat; - ensure( - "1. LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot) failed", - is_approx_equal(97182.953125f,result.mV[0]) && - is_approx_equal(-135405.640625f, result.mV[1]) && - is_approx_equal(162986.140f, result.mV[2])); - - LLVector3 vect1(5.0f, 40.0f, 78.1f); - LLQuaternion quat1(2.034f, 45.5f, 37.23f, 7.5f); - result = vect1 * quat1; - ensure( - "2. LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot) failed", - is_approx_equal(33217.703f, result.mV[0]) && - is_approx_equal(295383.8125f, result.mV[1]) && - is_approx_equal(84718.140f, result.mV[2])); - } - - //test case for LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) fn. - template<> template<> - void llquat_test_object_t::test<12>() - { - LLVector3d vect(-2.0f, 5.0f, -6.0f); - LLQuaternion quat(-3.5f, 4.5f, 3.5f, 6.5f); - LLVector3d result = vect * quat; - ensure( - "1. LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) failed ", - (-633.0f == result.mdV[0]) && - (-300.0f == result.mdV[1]) && - (-36.0f == result.mdV[2])); - - LLVector3d vect1(5.0f, -4.5f, 8.21f); - LLQuaternion quat1(2.0f, 4.5f, -7.2f, 9.5f); - result = vect1 * quat1; - ensure( - "2. LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) failed", - is_approx_equal_fraction(-120.29f, (F32) result.mdV[0], 8) && - is_approx_equal_fraction(-1683.958f, (F32) result.mdV[1], 8) && - is_approx_equal_fraction(516.56f, (F32) result.mdV[2], 8)); - - LLVector3d vect2(2.0f, 3.5f, 1.1f); - LLQuaternion quat2(1.0f, 4.0f, 2.0f, 5.0f); - result = vect2 * quat2; - ensure( - "3. LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) failed", - is_approx_equal_fraction(18.400001f, (F32) result.mdV[0], 8) && - is_approx_equal_fraction(188.6f, (F32) result.mdV[1], 8) && - is_approx_equal_fraction(32.20f, (F32) result.mdV[2], 8)); - } - - //test case for inline LLQuaternion operator-(const LLQuaternion &a) fn. - template<> template<> - void llquat_test_object_t::test<13>() - { - LLQuaternion quat(23.5f, 34.5f, 16723.4f, 324.7f); - LLQuaternion result = -quat; - ensure( - "1. LLQuaternion operator-(const LLQuaternion &a) failed", - (-23.5f == result.mQ[0]) && - (-34.5f == result.mQ[1]) && - (-16723.4f == result.mQ[2]) && - (-324.7f == result.mQ[3])); - - LLQuaternion quat1(-3.5f, -34.5f, -16.4f, -154.7f); - result = -quat1; - ensure( - "2. LLQuaternion operator-(const LLQuaternion &a) failed.", - (3.5f == result.mQ[0]) && - (34.5f == result.mQ[1]) && - (16.4f == result.mQ[2]) && - (154.7f == result.mQ[3])); - } - - //test case for inline LLQuaternion operator*(F32 a, const LLQuaternion &q) and - //inline LLQuaternion operator*(F32 a, const LLQuaternion &q) fns. - template<> template<> - void llquat_test_object_t::test<14>() - { - LLQuaternion quat_value(9.0f, 8.0f, 7.0f, 6.0f); - F32 a =3.5f; - LLQuaternion result = a * quat_value; - LLQuaternion result1 = quat_value * a; - - ensure( - "1. LLQuaternion operator* failed", - (result.mQ[0] == result1.mQ[0]) && - (result.mQ[1] == result1.mQ[1]) && - (result.mQ[2] == result1.mQ[2]) && - (result.mQ[3] == result1.mQ[3])); - - - LLQuaternion quat_val(9454.0f, 43568.3450f, 456343247.0343f, 2346.03434f); - a =-3324.3445f; - result = a * quat_val; - result1 = quat_val * a; - - ensure( - "2. LLQuaternion operator* failed", - (result.mQ[0] == result1.mQ[0]) && - (result.mQ[1] == result1.mQ[1]) && - (result.mQ[2] == result1.mQ[2]) && - (result.mQ[3] == result1.mQ[3])); - } - - template<> template<> - void llquat_test_object_t::test<15>() - { - // test cases for inline LLQuaternion operator~(const LLQuaternion &a) - LLQuaternion quat_val(2323.634f, -43535.4f, 3455.88f, -32232.45f); - LLQuaternion result = ~quat_val; - ensure( - "1. LLQuaternion operator~(const LLQuaternion &a) failed ", - (-2323.634f == result.mQ[0]) && - (43535.4f == result.mQ[1]) && - (-3455.88f == result.mQ[2]) && - (-32232.45f == result.mQ[3])); - - //test case for inline bool LLQuaternion::operator==(const LLQuaternion &b) const - LLQuaternion quat_val1(2323.634f, -43535.4f, 3455.88f, -32232.45f); - LLQuaternion quat_val2(2323.634f, -43535.4f, 3455.88f, -32232.45f); - ensure( - "2. LLQuaternion::operator==(const LLQuaternion &b) failed", - quat_val1 == quat_val2); - } - - template<> template<> - void llquat_test_object_t::test<16>() - { - //test case for inline bool LLQuaternion::operator!=(const LLQuaternion &b) const - LLQuaternion quat_val1(2323.634f, -43535.4f, 3455.88f, -32232.45f); - LLQuaternion quat_val2(0, -43535.4f, 3455.88f, -32232.45f); - ensure("LLQuaternion::operator!=(const LLQuaternion &b) failed", quat_val1 != quat_val2); - } - - template<> template<> - void llquat_test_object_t::test<17>() - { - //test case for LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) - F32 x = 2.0f; - F32 y = 1.0f; - F32 z = 3.0f; - - LLQuaternion result = mayaQ(x, y, z, LLQuaternion::XYZ); - ensure( - "1. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for XYZ", - is_approx_equal_fraction(0.0172174f, result.mQ[0], 16) && - is_approx_equal_fraction(0.009179f, result.mQ[1], 16) && - is_approx_equal_fraction(0.026020f, result.mQ[2], 16) && - is_approx_equal_fraction(0.999471f, result.mQ[3], 16)); - - LLQuaternion result1 = mayaQ(x, y, z, LLQuaternion::YZX); - ensure( - "2. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for XYZ", - is_approx_equal_fraction(0.017217f, result1.mQ[0], 16) && - is_approx_equal_fraction(0.008265f, result1.mQ[1], 16) && - is_approx_equal_fraction(0.026324f, result1.mQ[2], 16) && - is_approx_equal_fraction(0.999471f, result1.mQ[3], 16)); - - LLQuaternion result2 = mayaQ(x, y, z, LLQuaternion::ZXY); - ensure( - "3. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for ZXY", - is_approx_equal_fraction(0.017674f, result2.mQ[0], 16) && - is_approx_equal_fraction(0.008265f, result2.mQ[1], 16) && - is_approx_equal_fraction(0.026020f, result2.mQ[2], 16) && - is_approx_equal_fraction(0.999471f, result2.mQ[3], 16)); - - LLQuaternion result3 = mayaQ(x, y, z, LLQuaternion::XZY); - ensure( - "4. TLLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for XZY", - is_approx_equal_fraction(0.017674f, result3.mQ[0], 16) && - is_approx_equal_fraction(0.009179f, result3.mQ[1], 16) && - is_approx_equal_fraction(0.026020f, result3.mQ[2], 16) && - is_approx_equal_fraction(0.999463f, result3.mQ[3], 16)); - - LLQuaternion result4 = mayaQ(x, y, z, LLQuaternion::YXZ); - ensure( - "5. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for YXZ", - is_approx_equal_fraction(0.017217f, result4.mQ[0], 16) && - is_approx_equal_fraction(0.009179f, result4.mQ[1], 16) && - is_approx_equal_fraction(0.026324f, result4.mQ[2], 16) && - is_approx_equal_fraction(0.999463f, result4.mQ[3], 16)); - - LLQuaternion result5 = mayaQ(x, y, z, LLQuaternion::ZYX); - ensure( - "6. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for ZYX", - is_approx_equal_fraction(0.017674f, result5.mQ[0], 16) && - is_approx_equal_fraction(0.008265f, result5.mQ[1], 16) && - is_approx_equal_fraction(0.026324f, result5.mQ[2], 16) && - is_approx_equal_fraction(0.999463f, result5.mQ[3], 16)); - } - - template<> template<> - void llquat_test_object_t::test<18>() - { - // test case for friend std::ostream& operator<<(std::ostream &s, const LLQuaternion &a) fn - LLQuaternion a(1.0f, 1.0f, 1.0f, 1.0f); - std::ostringstream result_value; - result_value << a; - ensure_equals("1. Operator << failed", result_value.str(), "{ 1, 1, 1, 1 }"); - - LLQuaternion b(-31.034f, 231.2340f, 3451.344320f, -341.0f); - std::ostringstream result_value1; - result_value1 << b; - ensure_equals("2. Operator << failed", result_value1.str(), "{ -31.034, 231.234, 3451.34, -341 }"); - - LLQuaternion c(1.0f, 2.2f, 3.3f, 4.4f); - result_value << c; - ensure_equals("3. Operator << failed", result_value.str(), "{ 1, 1, 1, 1 }{ 1, 2.2, 3.3, 4.4 }"); - - } - - template<> template<> - void llquat_test_object_t::test<19>() - { - //test case for const char *OrderToString( const LLQuaternion::Order order ) fn - const char* result = OrderToString(LLQuaternion::XYZ); - ensure("1. OrderToString failed for XYZ", (0 == strcmp("XYZ", result))); - - result = OrderToString(LLQuaternion::YZX); - ensure("2. OrderToString failed for YZX", (0 == strcmp("YZX", result))); - - result = OrderToString(LLQuaternion::ZXY); - ensure( - "3. OrderToString failed for ZXY", - (0 == strcmp("ZXY", result)) && - (0 != strcmp("XYZ", result)) && - (0 != strcmp("YXZ", result)) && - (0 != strcmp("ZYX", result)) && - (0 != strcmp("XYZ", result))); - - result = OrderToString(LLQuaternion::XZY); - ensure("4. OrderToString failed for XZY", (0 == strcmp("XZY", result))); - - result = OrderToString(LLQuaternion::ZYX); - ensure("5. OrderToString failed for ZYX", (0 == strcmp("ZYX", result))); - - result = OrderToString(LLQuaternion::YXZ); - ensure("6.OrderToString failed for YXZ", (0 == strcmp("YXZ", result))); - } - - template<> template<> - void llquat_test_object_t::test<20>() - { - //test case for LLQuaternion::Order StringToOrder( const char *str ) fn - int result = StringToOrder("XYZ"); - ensure("1. LLQuaternion::Order StringToOrder(const char *str ) failed for XYZ", 0 == result); - - result = StringToOrder("YZX"); - ensure("2. LLQuaternion::Order StringToOrder(const char *str) failed for YZX", 1 == result); - - result = StringToOrder("ZXY"); - ensure("3. LLQuaternion::Order StringToOrder(const char *str) failed for ZXY", 2 == result); - - result = StringToOrder("XZY"); - ensure("4. LLQuaternion::Order StringToOrder(const char *str) failed for XZY", 3 == result); - - result = StringToOrder("YXZ"); - ensure("5. LLQuaternion::Order StringToOrder(const char *str) failed for YXZ", 4 == result); - - result = StringToOrder("ZYX"); - ensure("6. LLQuaternion::Order StringToOrder(const char *str) failed for ZYX", 5 == result); - - } - - template<> template<> - void llquat_test_object_t::test<21>() - { - //void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const fn - F32 angle_value = 90.0f; - LLVector3 vect(12.0f, 4.0f, 1.0f); - LLQuaternion llquat(angle_value, vect); - llquat.getAngleAxis(&angle_value, vect); - ensure( - "LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) failed", - is_approx_equal_fraction(2.035406f, angle_value, 16) && - is_approx_equal_fraction(0.315244f, vect.mV[1], 16) && - is_approx_equal_fraction(0.078811f, vect.mV[2], 16) && - is_approx_equal_fraction(0.945733f, vect.mV[0], 16)); - } - - template<> template<> - void llquat_test_object_t::test<22>() - { - //test case for void LLQuaternion::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const fn - F32 roll = -12.0f; - F32 pitch = -22.43f; - F32 yaw = 11.0f; - - LLQuaternion llquat; - llquat.getEulerAngles(&roll, &pitch, &yaw); - ensure( - "LLQuaternion::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) failed", - is_approx_equal(0.000f, llquat.mQ[0]) && - is_approx_equal(0.000f, llquat.mQ[1]) && - is_approx_equal(0.000f, llquat.mQ[2]) && - is_approx_equal(1.000f, llquat.mQ[3])); - } + struct llquat_test + { + }; + typedef test_group<llquat_test> llquat_test_t; + typedef llquat_test_t::object llquat_test_object_t; + tut::llquat_test_t tut_llquat_test("LLQuaternion"); + + //test case for LLQuaternion::LLQuaternion(void) fn. + template<> template<> + void llquat_test_object_t::test<1>() + { + LLQuaternion llquat; + ensure("LLQuaternion::LLQuaternion() failed", 0.f == llquat.mQ[0] && + 0.f == llquat.mQ[1] && + 0.f == llquat.mQ[2] && + 1.f == llquat.mQ[3]); + } + + //test case for explicit LLQuaternion(const LLMatrix4 &mat) fn. + template<> template<> + void llquat_test_object_t::test<2>() + { + LLMatrix4 llmat; + LLVector4 vector1(2.0f, 1.0f, 3.0f, 6.0f); + LLVector4 vector2(5.0f, 6.0f, 0.0f, 1.0f); + LLVector4 vector3(2.0f, 1.0f, 2.0f, 9.0f); + LLVector4 vector4(3.0f, 8.0f, 1.0f, 5.0f); + + llmat.initRows(vector1, vector2, vector3, vector4); + ensure("explicit LLQuaternion(const LLMatrix4 &mat) failed", 2.0f == llmat.mMatrix[0][0] && + 1.0f == llmat.mMatrix[0][1] && + 3.0f == llmat.mMatrix[0][2] && + 6.0f == llmat.mMatrix[0][3] && + 5.0f == llmat.mMatrix[1][0] && + 6.0f == llmat.mMatrix[1][1] && + 0.0f == llmat.mMatrix[1][2] && + 1.0f == llmat.mMatrix[1][3] && + 2.0f == llmat.mMatrix[2][0] && + 1.0f == llmat.mMatrix[2][1] && + 2.0f == llmat.mMatrix[2][2] && + 9.0f == llmat.mMatrix[2][3] && + 3.0f == llmat.mMatrix[3][0] && + 8.0f == llmat.mMatrix[3][1] && + 1.0f == llmat.mMatrix[3][2] && + 5.0f == llmat.mMatrix[3][3]); + } + + template<> template<> + void llquat_test_object_t::test<3>() + { + LLMatrix3 llmat; + + LLVector3 vect1(3.4028234660000000f , 234.56f, 4234.442234f); + LLVector3 vect2(741.434f, 23.00034f, 6567.223423f); + LLVector3 vect3(566.003034f, 12.98705f, 234.764423f); + llmat.setRows(vect1, vect2, vect3); + + ensure("LLMatrix3::setRows fn failed.", 3.4028234660000000f == llmat.mMatrix[0][0] && + 234.56f == llmat.mMatrix[0][1] && + 4234.442234f == llmat.mMatrix[0][2] && + 741.434f == llmat.mMatrix[1][0] && + 23.00034f == llmat.mMatrix[1][1] && + 6567.223423f == llmat.mMatrix[1][2] && + 566.003034f == llmat.mMatrix[2][0] && + 12.98705f == llmat.mMatrix[2][1] && + 234.764423f == llmat.mMatrix[2][2]); + } + + //test case for LLQuaternion(F32 x, F32 y, F32 z, F32 w), setQuatInit() and normQuat() fns. + template<> template<> + void llquat_test_object_t::test<4>() + { + F32 x_val = 3.0f; + F32 y_val = 2.0f; + F32 z_val = 6.0f; + F32 w_val = 1.0f; + + LLQuaternion res_quat; + res_quat.setQuatInit(x_val, y_val, z_val, w_val); + res_quat.normQuat(); + + ensure("LLQuaternion::normQuat() fn failed", + is_approx_equal(0.42426407f, res_quat.mQ[0]) && + is_approx_equal(0.28284273f, res_quat.mQ[1]) && + is_approx_equal(0.84852815f, res_quat.mQ[2]) && + is_approx_equal(0.14142136f, res_quat.mQ[3])); + + x_val = 0.0f; + y_val = 0.0f; + z_val = 0.0f; + w_val = 0.0f; + + res_quat.setQuatInit(x_val, y_val, z_val, w_val); + res_quat.normQuat(); + + ensure("LLQuaternion::normQuat() fn. failed.", + is_approx_equal(0.0f, res_quat.mQ[0]) && + is_approx_equal(0.0f, res_quat.mQ[1]) && + is_approx_equal(0.0f, res_quat.mQ[2]) && + is_approx_equal(1.0f, res_quat.mQ[3])); + + + ensure("LLQuaternion::normQuat() fn. failed.", + is_approx_equal(0.0f, res_quat.mQ[0]) && + is_approx_equal(0.0f, res_quat.mQ[1]) && + is_approx_equal(0.0f, res_quat.mQ[2]) && + is_approx_equal(1.0f, res_quat.mQ[3])); + } + + //test case for conjQuat() and transQuat() fns. + template<> template<> + void llquat_test_object_t::test<5>() + { + F32 x_val = 3.0f; + F32 y_val = 2.0f; + F32 z_val = 6.0f; + F32 w_val = 1.0f; + + LLQuaternion res_quat; + LLQuaternion result, result1; + result1 = result = res_quat.setQuatInit(x_val, y_val, z_val, w_val); + + result.conjQuat(); + result1.transQuat(); + + ensure("LLQuaternion::conjQuat and LLQuaternion::transQuat failed ", + is_approx_equal(result1.mQ[0], result.mQ[0]) && + is_approx_equal(result1.mQ[1], result.mQ[1]) && + is_approx_equal(result1.mQ[2], result.mQ[2])); + + } + + //test case for dot(const LLQuaternion &a, const LLQuaternion &b) fn. + template<> template<> + void llquat_test_object_t::test<6>() + { + LLQuaternion quat1(3.0f, 2.0f, 6.0f, 0.0f), quat2(1.0f, 1.0f, 1.0f, 1.0f); + ensure("1. The two values are different", ll_round(12.000000f, 2) == ll_round(dot(quat1, quat2), 2)); + + LLQuaternion quat0(3.0f, 9.334f, 34.5f, 23.0f), quat(34.5f, 23.23f, 2.0f, 45.5f); + ensure("2. The two values are different", ll_round(1435.828807f, 2) == ll_round(dot(quat0, quat), 2)); + } + + //test case for LLQuaternion &LLQuaternion::constrain(F32 radians) fn. + template<> template<> + void llquat_test_object_t::test<7>() + { + F32 radian = 60.0f; + LLQuaternion quat(3.0f, 2.0f, 6.0f, 0.0f); + LLQuaternion quat1; + quat1 = quat.constrain(radian); + ensure("1. LLQuaternion::constrain(F32 radians) failed", + is_approx_equal_fraction(-0.423442f, quat1.mQ[0], 8) && + is_approx_equal_fraction(-0.282295f, quat1.mQ[1], 8) && + is_approx_equal_fraction(-0.846884f, quat1.mQ[2], 8) && + is_approx_equal_fraction(0.154251f, quat1.mQ[3], 8)); + + + radian = 30.0f; + LLQuaternion quat0(37.50f, 12.0f, 86.023f, 40.32f); + quat1 = quat0.constrain(radian); + + ensure("2. LLQuaternion::constrain(F32 radians) failed", + is_approx_equal_fraction(37.500000f, quat1.mQ[0], 8) && + is_approx_equal_fraction(12.0000f, quat1.mQ[1], 8) && + is_approx_equal_fraction(86.0230f, quat1.mQ[2], 8) && + is_approx_equal_fraction(40.320000f, quat1.mQ[3], 8)); + } + + template<> template<> + void llquat_test_object_t::test<8>() + { + F32 value1 = 15.0f; + LLQuaternion quat1(1.0f, 2.0f, 4.0f, 1.0f); + LLQuaternion quat2(4.0f, 3.0f, 6.5f, 9.7f); + LLQuaternion res_lerp, res_slerp, res_nlerp; + + //test case for lerp(F32 t, const LLQuaternion &q) fn. + res_lerp = lerp(value1, quat1); + ensure("1. LLQuaternion lerp(F32 t, const LLQuaternion &q) failed", + is_approx_equal_fraction(0.181355f, res_lerp.mQ[0], 16) && + is_approx_equal_fraction(0.362711f, res_lerp.mQ[1], 16) && + is_approx_equal_fraction(0.725423f, res_lerp.mQ[2], 16) && + is_approx_equal_fraction(0.556158f, res_lerp.mQ[3], 16)); + + //test case for lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q) fn. + res_lerp = lerp(value1, quat1, quat2); + ensure("2. LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q) failed", + is_approx_equal_fraction(0.314306f, res_lerp.mQ[0], 16) && + is_approx_equal_fraction(0.116156f, res_lerp.mQ[1], 16) && + is_approx_equal_fraction(0.283559f, res_lerp.mQ[2], 16) && + is_approx_equal_fraction(0.898506f, res_lerp.mQ[3], 16)); + + //test case for slerp( F32 u, const LLQuaternion &a, const LLQuaternion &b ) fn. + res_slerp = slerp(value1, quat1, quat2); + ensure("3. LLQuaternion slerp( F32 u, const LLQuaternion &a, const LLQuaternion &b) failed", + is_approx_equal_fraction(46.000f, res_slerp.mQ[0], 16) && + is_approx_equal_fraction(17.00f, res_slerp.mQ[1], 16) && + is_approx_equal_fraction(41.5f, res_slerp.mQ[2], 16) && + is_approx_equal_fraction(131.5f, res_slerp.mQ[3], 16)); + + //test case for nlerp(F32 t, const LLQuaternion &a, const LLQuaternion &b) fn. + res_nlerp = nlerp(value1, quat1, quat2); + ensure("4. LLQuaternion nlerp(F32 t, const LLQuaternion &a, const LLQuaternion &b) failed", + is_approx_equal_fraction(0.314306f, res_nlerp.mQ[0], 16) && + is_approx_equal_fraction(0.116157f, res_nlerp.mQ[1], 16) && + is_approx_equal_fraction(0.283559f, res_nlerp.mQ[2], 16) && + is_approx_equal_fraction(0.898506f, res_nlerp.mQ[3], 16)); + + //test case for nlerp(F32 t, const LLQuaternion &q) fn. + res_slerp = slerp(value1, quat1); + ensure("5. LLQuaternion slerp(F32 t, const LLQuaternion &q) failed", + is_approx_equal_fraction(1.0f, res_slerp.mQ[0], 16) && + is_approx_equal_fraction(2.0f, res_slerp.mQ[1], 16) && + is_approx_equal_fraction(4.0000f, res_slerp.mQ[2], 16) && + is_approx_equal_fraction(1.000f, res_slerp.mQ[3], 16)); + + LLQuaternion quat3(2.0f, 1.0f, 5.5f, 10.5f); + LLQuaternion res_nlerp1; + value1 = 100.0f; + res_nlerp1 = nlerp(value1, quat3); + ensure("6. LLQuaternion nlerp(F32 t, const LLQuaternion &q) failed", + is_approx_equal_fraction(0.268245f, res_nlerp1.mQ[0], 16) && is_approx_equal_fraction(0.134122f, res_nlerp1.mQ[1], 2) && + is_approx_equal_fraction(0.737673f, res_nlerp1.mQ[2], 16) && + is_approx_equal_fraction(0.604892f, res_nlerp1.mQ[3], 16)); + + //test case for lerp(F32 t, const LLQuaternion &q) fn. + res_lerp = lerp(value1, quat2); + ensure("7. LLQuaternion lerp(F32 t, const LLQuaternion &q) failed", + is_approx_equal_fraction(0.404867f, res_lerp.mQ[0], 16) && + is_approx_equal_fraction(0.303650f, res_lerp.mQ[1], 16) && + is_approx_equal_fraction(0.657909f, res_lerp.mQ[2], 16) && + is_approx_equal_fraction(0.557704f, res_lerp.mQ[3], 16)); + + } + + template<> template<> + void llquat_test_object_t::test<9>() + { + //test case for LLQuaternion operator*(const LLQuaternion &a, const LLQuaternion &b) fn + LLQuaternion quat1(1.0f, 2.5f, 3.5f, 5.5f); + LLQuaternion quat2(4.0f, 3.0f, 5.0f, 1.0f); + LLQuaternion result = quat1 * quat2; + ensure("1. LLQuaternion Operator* failed", (21.0f == result.mQ[0]) && + (10.0f == result.mQ[1]) && + (38.0f == result.mQ[2]) && + (-23.5f == result.mQ[3])); + + LLQuaternion quat3(2341.340f, 2352.345f, 233.25f, 7645.5f); + LLQuaternion quat4(674.067f, 893.0897f, 578.0f, 231.0f); + result = quat3 * quat4; + ensure("2. LLQuaternion Operator* failed", (4543086.5f == result.mQ[0]) && + (8567578.0f == result.mQ[1]) && + (3967591.25f == result.mQ[2]) && + is_approx_equal(-2047783.25f, result.mQ[3])); + + //inline LLQuaternion operator+(const LLQuaternion &a, const LLQuaternion &b)fn. + result = quat1 + quat2; + ensure("3. LLQuaternion operator+ failed", (5.0f == result.mQ[0]) && + (5.5f == result.mQ[1]) && + (8.5f == result.mQ[2]) && + (6.5f == result.mQ[3])); + + result = quat3 + quat4; + ensure( + "4. LLQuaternion operator+ failed", + is_approx_equal(3015.407227f, result.mQ[0]) && + is_approx_equal(3245.434570f, result.mQ[1]) && + (811.25f == result.mQ[2]) && + (7876.5f == result.mQ[3])); + + //inline LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b) fn + result = quat1 - quat2; + ensure( + "5. LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b) failed", + (-3.0f == result.mQ[0]) && + (-0.5f == result.mQ[1]) && + (-1.5f == result.mQ[2]) && + (4.5f == result.mQ[3])); + + result = quat3 - quat4; + ensure( + "6. LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b) failed", + is_approx_equal(1667.273071f, result.mQ[0]) && + is_approx_equal(1459.255249f, result.mQ[1]) && + (-344.75f == result.mQ[2]) && + (7414.50f == result.mQ[3])); + } + + //test case for LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot) fn. + template<> template<> + void llquat_test_object_t::test<10>() + { + LLVector4 vect(12.0f, 5.0f, 60.0f, 75.1f); + LLQuaternion quat(2323.034f, 23.5f, 673.23f, 57667.5f); + LLVector4 result = vect * quat; + ensure( + "1. LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot) failed", + is_approx_equal(39928406016.0f, result.mV[0]) && + // gcc on x86 actually gives us more precision than we were expecting, verified with -ffloat-store - we forgive this + (1457802240.0f >= result.mV[1]) && // gcc+x86+linux + (1457800960.0f <= result.mV[1]) && // elsewhere + is_approx_equal(200580612096.0f, result.mV[2]) && + (75.099998f == result.mV[3])); + + LLVector4 vect1(22.0f, 45.0f, 40.0f, 78.1f); + LLQuaternion quat1(2.034f, 45.5f, 37.23f, 7.5f); + result = vect1 * quat1; + ensure( + "2. LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot) failed", + is_approx_equal(-58153.5390f, result.mV[0]) && + (183787.8125f == result.mV[1]) && + (116864.164063f == result.mV[2]) && + (78.099998f == result.mV[3])); + } + + //test case for LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot) fn. + template<> template<> + void llquat_test_object_t::test<11>() + { + LLVector3 vect(12.0f, 5.0f, 60.0f); + LLQuaternion quat(23.5f, 6.5f, 3.23f, 56.5f); + LLVector3 result = vect * quat; + ensure( + "1. LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot) failed", + is_approx_equal(97182.953125f,result.mV[0]) && + is_approx_equal(-135405.640625f, result.mV[1]) && + is_approx_equal(162986.140f, result.mV[2])); + + LLVector3 vect1(5.0f, 40.0f, 78.1f); + LLQuaternion quat1(2.034f, 45.5f, 37.23f, 7.5f); + result = vect1 * quat1; + ensure( + "2. LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot) failed", + is_approx_equal(33217.703f, result.mV[0]) && + is_approx_equal(295383.8125f, result.mV[1]) && + is_approx_equal(84718.140f, result.mV[2])); + } + + //test case for LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) fn. + template<> template<> + void llquat_test_object_t::test<12>() + { + LLVector3d vect(-2.0f, 5.0f, -6.0f); + LLQuaternion quat(-3.5f, 4.5f, 3.5f, 6.5f); + LLVector3d result = vect * quat; + ensure( + "1. LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) failed ", + (-633.0f == result.mdV[0]) && + (-300.0f == result.mdV[1]) && + (-36.0f == result.mdV[2])); + + LLVector3d vect1(5.0f, -4.5f, 8.21f); + LLQuaternion quat1(2.0f, 4.5f, -7.2f, 9.5f); + result = vect1 * quat1; + ensure( + "2. LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) failed", + is_approx_equal_fraction(-120.29f, (F32) result.mdV[0], 8) && + is_approx_equal_fraction(-1683.958f, (F32) result.mdV[1], 8) && + is_approx_equal_fraction(516.56f, (F32) result.mdV[2], 8)); + + LLVector3d vect2(2.0f, 3.5f, 1.1f); + LLQuaternion quat2(1.0f, 4.0f, 2.0f, 5.0f); + result = vect2 * quat2; + ensure( + "3. LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) failed", + is_approx_equal_fraction(18.400001f, (F32) result.mdV[0], 8) && + is_approx_equal_fraction(188.6f, (F32) result.mdV[1], 8) && + is_approx_equal_fraction(32.20f, (F32) result.mdV[2], 8)); + } + + //test case for inline LLQuaternion operator-(const LLQuaternion &a) fn. + template<> template<> + void llquat_test_object_t::test<13>() + { + LLQuaternion quat(23.5f, 34.5f, 16723.4f, 324.7f); + LLQuaternion result = -quat; + ensure( + "1. LLQuaternion operator-(const LLQuaternion &a) failed", + (-23.5f == result.mQ[0]) && + (-34.5f == result.mQ[1]) && + (-16723.4f == result.mQ[2]) && + (-324.7f == result.mQ[3])); + + LLQuaternion quat1(-3.5f, -34.5f, -16.4f, -154.7f); + result = -quat1; + ensure( + "2. LLQuaternion operator-(const LLQuaternion &a) failed.", + (3.5f == result.mQ[0]) && + (34.5f == result.mQ[1]) && + (16.4f == result.mQ[2]) && + (154.7f == result.mQ[3])); + } + + //test case for inline LLQuaternion operator*(F32 a, const LLQuaternion &q) and + //inline LLQuaternion operator*(F32 a, const LLQuaternion &q) fns. + template<> template<> + void llquat_test_object_t::test<14>() + { + LLQuaternion quat_value(9.0f, 8.0f, 7.0f, 6.0f); + F32 a =3.5f; + LLQuaternion result = a * quat_value; + LLQuaternion result1 = quat_value * a; + + ensure( + "1. LLQuaternion operator* failed", + (result.mQ[0] == result1.mQ[0]) && + (result.mQ[1] == result1.mQ[1]) && + (result.mQ[2] == result1.mQ[2]) && + (result.mQ[3] == result1.mQ[3])); + + + LLQuaternion quat_val(9454.0f, 43568.3450f, 456343247.0343f, 2346.03434f); + a =-3324.3445f; + result = a * quat_val; + result1 = quat_val * a; + + ensure( + "2. LLQuaternion operator* failed", + (result.mQ[0] == result1.mQ[0]) && + (result.mQ[1] == result1.mQ[1]) && + (result.mQ[2] == result1.mQ[2]) && + (result.mQ[3] == result1.mQ[3])); + } + + template<> template<> + void llquat_test_object_t::test<15>() + { + // test cases for inline LLQuaternion operator~(const LLQuaternion &a) + LLQuaternion quat_val(2323.634f, -43535.4f, 3455.88f, -32232.45f); + LLQuaternion result = ~quat_val; + ensure( + "1. LLQuaternion operator~(const LLQuaternion &a) failed ", + (-2323.634f == result.mQ[0]) && + (43535.4f == result.mQ[1]) && + (-3455.88f == result.mQ[2]) && + (-32232.45f == result.mQ[3])); + + //test case for inline bool LLQuaternion::operator==(const LLQuaternion &b) const + LLQuaternion quat_val1(2323.634f, -43535.4f, 3455.88f, -32232.45f); + LLQuaternion quat_val2(2323.634f, -43535.4f, 3455.88f, -32232.45f); + ensure( + "2. LLQuaternion::operator==(const LLQuaternion &b) failed", + quat_val1 == quat_val2); + } + + template<> template<> + void llquat_test_object_t::test<16>() + { + //test case for inline bool LLQuaternion::operator!=(const LLQuaternion &b) const + LLQuaternion quat_val1(2323.634f, -43535.4f, 3455.88f, -32232.45f); + LLQuaternion quat_val2(0, -43535.4f, 3455.88f, -32232.45f); + ensure("LLQuaternion::operator!=(const LLQuaternion &b) failed", quat_val1 != quat_val2); + } + + template<> template<> + void llquat_test_object_t::test<17>() + { + //test case for LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) + F32 x = 2.0f; + F32 y = 1.0f; + F32 z = 3.0f; + + LLQuaternion result = mayaQ(x, y, z, LLQuaternion::XYZ); + ensure( + "1. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for XYZ", + is_approx_equal_fraction(0.0172174f, result.mQ[0], 16) && + is_approx_equal_fraction(0.009179f, result.mQ[1], 16) && + is_approx_equal_fraction(0.026020f, result.mQ[2], 16) && + is_approx_equal_fraction(0.999471f, result.mQ[3], 16)); + + LLQuaternion result1 = mayaQ(x, y, z, LLQuaternion::YZX); + ensure( + "2. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for XYZ", + is_approx_equal_fraction(0.017217f, result1.mQ[0], 16) && + is_approx_equal_fraction(0.008265f, result1.mQ[1], 16) && + is_approx_equal_fraction(0.026324f, result1.mQ[2], 16) && + is_approx_equal_fraction(0.999471f, result1.mQ[3], 16)); + + LLQuaternion result2 = mayaQ(x, y, z, LLQuaternion::ZXY); + ensure( + "3. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for ZXY", + is_approx_equal_fraction(0.017674f, result2.mQ[0], 16) && + is_approx_equal_fraction(0.008265f, result2.mQ[1], 16) && + is_approx_equal_fraction(0.026020f, result2.mQ[2], 16) && + is_approx_equal_fraction(0.999471f, result2.mQ[3], 16)); + + LLQuaternion result3 = mayaQ(x, y, z, LLQuaternion::XZY); + ensure( + "4. TLLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for XZY", + is_approx_equal_fraction(0.017674f, result3.mQ[0], 16) && + is_approx_equal_fraction(0.009179f, result3.mQ[1], 16) && + is_approx_equal_fraction(0.026020f, result3.mQ[2], 16) && + is_approx_equal_fraction(0.999463f, result3.mQ[3], 16)); + + LLQuaternion result4 = mayaQ(x, y, z, LLQuaternion::YXZ); + ensure( + "5. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for YXZ", + is_approx_equal_fraction(0.017217f, result4.mQ[0], 16) && + is_approx_equal_fraction(0.009179f, result4.mQ[1], 16) && + is_approx_equal_fraction(0.026324f, result4.mQ[2], 16) && + is_approx_equal_fraction(0.999463f, result4.mQ[3], 16)); + + LLQuaternion result5 = mayaQ(x, y, z, LLQuaternion::ZYX); + ensure( + "6. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for ZYX", + is_approx_equal_fraction(0.017674f, result5.mQ[0], 16) && + is_approx_equal_fraction(0.008265f, result5.mQ[1], 16) && + is_approx_equal_fraction(0.026324f, result5.mQ[2], 16) && + is_approx_equal_fraction(0.999463f, result5.mQ[3], 16)); + } + + template<> template<> + void llquat_test_object_t::test<18>() + { + // test case for friend std::ostream& operator<<(std::ostream &s, const LLQuaternion &a) fn + LLQuaternion a(1.0f, 1.0f, 1.0f, 1.0f); + std::ostringstream result_value; + result_value << a; + ensure_equals("1. Operator << failed", result_value.str(), "{ 1, 1, 1, 1 }"); + + LLQuaternion b(-31.034f, 231.2340f, 3451.344320f, -341.0f); + std::ostringstream result_value1; + result_value1 << b; + ensure_equals("2. Operator << failed", result_value1.str(), "{ -31.034, 231.234, 3451.34, -341 }"); + + LLQuaternion c(1.0f, 2.2f, 3.3f, 4.4f); + result_value << c; + ensure_equals("3. Operator << failed", result_value.str(), "{ 1, 1, 1, 1 }{ 1, 2.2, 3.3, 4.4 }"); + + } + + template<> template<> + void llquat_test_object_t::test<19>() + { + //test case for const char *OrderToString( const LLQuaternion::Order order ) fn + const char* result = OrderToString(LLQuaternion::XYZ); + ensure("1. OrderToString failed for XYZ", (0 == strcmp("XYZ", result))); + + result = OrderToString(LLQuaternion::YZX); + ensure("2. OrderToString failed for YZX", (0 == strcmp("YZX", result))); + + result = OrderToString(LLQuaternion::ZXY); + ensure( + "3. OrderToString failed for ZXY", + (0 == strcmp("ZXY", result)) && + (0 != strcmp("XYZ", result)) && + (0 != strcmp("YXZ", result)) && + (0 != strcmp("ZYX", result)) && + (0 != strcmp("XYZ", result))); + + result = OrderToString(LLQuaternion::XZY); + ensure("4. OrderToString failed for XZY", (0 == strcmp("XZY", result))); + + result = OrderToString(LLQuaternion::ZYX); + ensure("5. OrderToString failed for ZYX", (0 == strcmp("ZYX", result))); + + result = OrderToString(LLQuaternion::YXZ); + ensure("6.OrderToString failed for YXZ", (0 == strcmp("YXZ", result))); + } + + template<> template<> + void llquat_test_object_t::test<20>() + { + //test case for LLQuaternion::Order StringToOrder( const char *str ) fn + int result = StringToOrder("XYZ"); + ensure("1. LLQuaternion::Order StringToOrder(const char *str ) failed for XYZ", 0 == result); + + result = StringToOrder("YZX"); + ensure("2. LLQuaternion::Order StringToOrder(const char *str) failed for YZX", 1 == result); + + result = StringToOrder("ZXY"); + ensure("3. LLQuaternion::Order StringToOrder(const char *str) failed for ZXY", 2 == result); + + result = StringToOrder("XZY"); + ensure("4. LLQuaternion::Order StringToOrder(const char *str) failed for XZY", 3 == result); + + result = StringToOrder("YXZ"); + ensure("5. LLQuaternion::Order StringToOrder(const char *str) failed for YXZ", 4 == result); + + result = StringToOrder("ZYX"); + ensure("6. LLQuaternion::Order StringToOrder(const char *str) failed for ZYX", 5 == result); + + } + + template<> template<> + void llquat_test_object_t::test<21>() + { + //void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const fn + F32 angle_value = 90.0f; + LLVector3 vect(12.0f, 4.0f, 1.0f); + LLQuaternion llquat(angle_value, vect); + llquat.getAngleAxis(&angle_value, vect); + ensure( + "LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) failed", + is_approx_equal_fraction(2.035406f, angle_value, 16) && + is_approx_equal_fraction(0.315244f, vect.mV[1], 16) && + is_approx_equal_fraction(0.078811f, vect.mV[2], 16) && + is_approx_equal_fraction(0.945733f, vect.mV[0], 16)); + } + + template<> template<> + void llquat_test_object_t::test<22>() + { + //test case for void LLQuaternion::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const fn + F32 roll = -12.0f; + F32 pitch = -22.43f; + F32 yaw = 11.0f; + + LLQuaternion llquat; + llquat.getEulerAngles(&roll, &pitch, &yaw); + ensure( + "LLQuaternion::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) failed", + is_approx_equal(0.000f, llquat.mQ[0]) && + is_approx_equal(0.000f, llquat.mQ[1]) && + is_approx_equal(0.000f, llquat.mQ[2]) && + is_approx_equal(1.000f, llquat.mQ[3])); + } } diff --git a/indra/llmath/tests/llrect_test.cpp b/indra/llmath/tests/llrect_test.cpp index 365f298636..0fd5602d4a 100644 --- a/indra/llmath/tests/llrect_test.cpp +++ b/indra/llmath/tests/llrect_test.cpp @@ -3,25 +3,25 @@ * @author Martin Reddy * @date 2009-06-25 * @brief Test for llrect.cpp. - * + * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -32,495 +32,495 @@ namespace tut { - struct LLRectData - { - }; + struct LLRectData + { + }; - typedef test_group<LLRectData> factory; - typedef factory::object object; + typedef test_group<LLRectData> factory; + typedef factory::object object; } namespace { - tut::factory llrect_test_factory("LLRect"); + tut::factory llrect_test_factory("LLRect"); } namespace tut { - template<> template<> - void object::test<1>() - { - // - // test the LLRect default constructor - // - - LLSD zero; - zero.append(0); zero.append(0); zero.append(0); zero.append(0); - - // default constructor - LLRect rect1; - ensure_equals("Empty rect", rect1.getValue(), zero); - ensure_equals("Empty rect left", rect1.mLeft, 0); - ensure_equals("Empty rect top", rect1.mTop, 0); - ensure_equals("Empty rect right", rect1.mRight, 0); - ensure_equals("Empty rect bottom", rect1.mBottom, 0); - ensure_equals("Empty rect width", rect1.getWidth(), 0); - ensure_equals("Empty rect height", rect1.getHeight(), 0); - ensure_equals("Empty rect centerx", rect1.getCenterX(), 0); - ensure_equals("Empty rect centery", rect1.getCenterY(), 0); - } - - template<> template<> - void object::test<2>() - { - // - // test the LLRectf default constructor - // - - LLSD zerof; - zerof.append(0.0f); zerof.append(0.0f); zerof.append(0.0f); zerof.append(0.0f); - - LLRectf rect2; - ensure_equals("Empty rectf", rect2.getValue(), zerof); - ensure_equals("Empty rectf left", rect2.mLeft, 0.0f); - ensure_equals("Empty rectf top", rect2.mTop, 0.0f); - ensure_equals("Empty rectf right", rect2.mRight, 0.0f); - ensure_equals("Empty rectf bottom", rect2.mBottom, 0.0f); - ensure_equals("Empty rectf width", rect2.getWidth(), 0.0f); - ensure_equals("Empty rectf height", rect2.getHeight(), 0.0f); - ensure_equals("Empty rectf centerx", rect2.getCenterX(), 0.0f); - ensure_equals("Empty rectf centery", rect2.getCenterY(), 0.0f); - } - - template<> template<> - void object::test<3>() - { - // - // test the LLRect constructor from another LLRect - // - - LLRect rect3(LLRect(1, 6, 7, 2)); - ensure_equals("Default rect left", rect3.mLeft, 1); - ensure_equals("Default rect top", rect3.mTop, 6); - ensure_equals("Default rect right", rect3.mRight, 7); - ensure_equals("Default rect bottom", rect3.mBottom, 2); - ensure_equals("Default rect width", rect3.getWidth(), 6); - ensure_equals("Default rect height", rect3.getHeight(), 4); - ensure_equals("Default rect centerx", rect3.getCenterX(), 4); - ensure_equals("Default rect centery", rect3.getCenterY(), 4); - } - - template<> template<> - void object::test<4>() - { - // - // test the LLRectf four-float constructor - // - - LLRectf rect4(1.0f, 5.0f, 6.0f, 2.0f); - ensure_equals("Default rectf left", rect4.mLeft, 1.0f); - ensure_equals("Default rectf top", rect4.mTop, 5.0f); - ensure_equals("Default rectf right", rect4.mRight, 6.0f); - ensure_equals("Default rectf bottom", rect4.mBottom, 2.0f); - ensure_equals("Default rectf width", rect4.getWidth(), 5.0f); - ensure_equals("Default rectf height", rect4.getHeight(), 3.0f); - ensure_equals("Default rectf centerx", rect4.getCenterX(), 3.5f); - ensure_equals("Default rectf centery", rect4.getCenterY(), 3.5f); - } - - template<> template<> - void object::test<5>() - { - // - // test the LLRectf LLSD constructor - // - - LLSD array; - array.append(-1.0f); array.append(0.0f); array.append(0.0f); array.append(-1.0f); - LLRectf rect5(array); - ensure_equals("LLSD rectf left", rect5.mLeft, -1.0f); - ensure_equals("LLSD rectf top", rect5.mTop, 0.0f); - ensure_equals("LLSD rectf right", rect5.mRight, 0.0f); - ensure_equals("LLSD rectf bottom", rect5.mBottom, -1.0f); - ensure_equals("LLSD rectf width", rect5.getWidth(), 1.0f); - ensure_equals("LLSD rectf height", rect5.getHeight(), 1.0f); - ensure_equals("LLSD rectf centerx", rect5.getCenterX(), -0.5f); - ensure_equals("LLSD rectf centery", rect5.getCenterY(), -0.5f); - } - - template<> template<> - void object::test<6>() - { - // - // test directly setting the member variables for dimensions - // - - LLRectf rectf; - - rectf.mLeft = -1.0f; - rectf.mTop = 1.0f; - rectf.mRight = 1.0f; - rectf.mBottom = -1.0f; - ensure_equals("Member-set rectf left", rectf.mLeft, -1.0f); - ensure_equals("Member-set rectf top", rectf.mTop, 1.0f); - ensure_equals("Member-set rectf right", rectf.mRight, 1.0f); - ensure_equals("Member-set rectf bottom", rectf.mBottom, -1.0f); - ensure_equals("Member-set rectf width", rectf.getWidth(), 2.0f); - ensure_equals("Member-set rectf height", rectf.getHeight(), 2.0f); - ensure_equals("Member-set rectf centerx", rectf.getCenterX(), 0.0f); - ensure_equals("Member-set rectf centery", rectf.getCenterY(), 0.0f); - } - - template<> template<> - void object::test<7>() - { - // - // test the setValue() method - // - - LLRectf rectf; - - LLSD array; - array.append(-1.0f); array.append(0.0f); array.append(0.0f); array.append(-1.0f); - rectf.setValue(array); - ensure_equals("setValue() rectf left", rectf.mLeft, -1.0f); - ensure_equals("setValue() rectf top", rectf.mTop, 0.0f); - ensure_equals("setValue() rectf right", rectf.mRight, 0.0f); - ensure_equals("setValue() rectf bottom", rectf.mBottom, -1.0f); - ensure_equals("setValue() rectf width", rectf.getWidth(), 1.0f); - ensure_equals("setValue() rectf height", rectf.getHeight(), 1.0f); - ensure_equals("setValue() rectf centerx", rectf.getCenterX(), -0.5f); - ensure_equals("setValue() rectf centery", rectf.getCenterY(), -0.5f); - } - - template<> template<> - void object::test<8>() - { - // - // test the set() method - // - - LLRect rect; - - rect.set(10, 90, 70, 10); - ensure_equals("set() rectf left", rect.mLeft, 10); - ensure_equals("set() rectf top", rect.mTop, 90); - ensure_equals("set() rectf right", rect.mRight, 70); - ensure_equals("set() rectf bottom", rect.mBottom, 10); - ensure_equals("set() rectf width", rect.getWidth(), 60); - ensure_equals("set() rectf height", rect.getHeight(), 80); - ensure_equals("set() rectf centerx", rect.getCenterX(), 40); - ensure_equals("set() rectf centery", rect.getCenterY(), 50); - } - - template<> template<> - void object::test<9>() - { - // - // test the setOriginAndSize() method - // - - LLRectf rectf; - - rectf.setOriginAndSize(0.0f, 0.0f, 2.0f, 1.0f); - ensure_equals("setOriginAndSize() rectf left", rectf.mLeft, 0.0f); - ensure_equals("setOriginAndSize() rectf top", rectf.mTop, 1.0f); - ensure_equals("setOriginAndSize() rectf right", rectf.mRight, 2.0f); - ensure_equals("setOriginAndSize() rectf bottom", rectf.mBottom, 0.0f); - ensure_equals("setOriginAndSize() rectf width", rectf.getWidth(), 2.0f); - ensure_equals("setOriginAndSize() rectf height", rectf.getHeight(), 1.0f); - ensure_equals("setOriginAndSize() rectf centerx", rectf.getCenterX(), 1.0f); - ensure_equals("setOriginAndSize() rectf centery", rectf.getCenterY(), 0.5f); - } - - template<> template<> - void object::test<10>() - { - // - // test the setLeftTopAndSize() method - // - - LLRectf rectf; - - rectf.setLeftTopAndSize(0.0f, 0.0f, 2.0f, 1.0f); - ensure_equals("setLeftTopAndSize() rectf left", rectf.mLeft, 0.0f); - ensure_equals("setLeftTopAndSize() rectf top", rectf.mTop, 0.0f); - ensure_equals("setLeftTopAndSize() rectf right", rectf.mRight, 2.0f); - ensure_equals("setLeftTopAndSize() rectf bottom", rectf.mBottom, -1.0f); - ensure_equals("setLeftTopAndSize() rectf width", rectf.getWidth(), 2.0f); - ensure_equals("setLeftTopAndSize() rectf height", rectf.getHeight(), 1.0f); - ensure_equals("setLeftTopAndSize() rectf centerx", rectf.getCenterX(), 1.0f); - ensure_equals("setLeftTopAndSize() rectf centery", rectf.getCenterY(), -0.5f); - } - - template<> template<> - void object::test<11>() - { - // - // test the setCenterAndSize() method - // - - LLRectf rectf; - - rectf.setCenterAndSize(0.0f, 0.0f, 2.0f, 1.0f); - ensure_equals("setCenterAndSize() rectf left", rectf.mLeft, -1.0f); - ensure_equals("setCenterAndSize() rectf top", rectf.mTop, 0.5f); - ensure_equals("setCenterAndSize() rectf right", rectf.mRight, 1.0f); - ensure_equals("setCenterAndSize() rectf bottom", rectf.mBottom, -0.5f); - ensure_equals("setCenterAndSize() rectf width", rectf.getWidth(), 2.0f); - ensure_equals("setCenterAndSize() rectf height", rectf.getHeight(), 1.0f); - ensure_equals("setCenterAndSize() rectf centerx", rectf.getCenterX(), 0.0f); - ensure_equals("setCenterAndSize() rectf centery", rectf.getCenterY(), 0.0f); - } - - template<> template<> - void object::test<12>() - { - // - // test the validity checking method - // - - LLRectf rectf; - - rectf.set(-1.0f, 1.0f, 1.0f, -1.0f); - ensure("BBox is valid", rectf.isValid()); - - rectf.mLeft = 2.0f; - ensure("BBox is not valid", ! rectf.isValid()); - - rectf.makeValid(); - ensure("BBox forced valid", rectf.isValid()); - - rectf.set(-1.0f, -1.0f, -1.0f, -1.0f); - ensure("BBox(0,0,0,0) is valid", rectf.isValid()); - } - - template<> template<> - void object::test<13>() - { - // - // test the null checking methods - // - - LLRectf rectf; - - rectf.set(-1.0f, 1.0f, 1.0f, -1.0f); - ensure("BBox is not Null", ! rectf.isEmpty()); - ensure("BBox notNull", rectf.notEmpty()); - - rectf.mLeft = 2.0f; - rectf.makeValid(); - ensure("BBox is now Null", rectf.isEmpty()); - - rectf.set(-1.0f, -1.0f, -1.0f, -1.0f); - ensure("BBox(0,0,0,0) is Null", rectf.isEmpty()); - } - - template<> template<> - void object::test<14>() - { - // - // test the (in)equality operators - // - - LLRectf rect1, rect2; - - rect1.set(-1.0f, 1.0f, 1.0f, -1.0f); - rect2.set(-1.0f, 0.9f, 1.0f, -1.0f); - - ensure("rect1 == rect2 (false)", ! (rect1 == rect2)); - ensure("rect1 != rect2 (true)", rect1 != rect2); - - ensure("rect1 == rect1 (true)", rect1 == rect1); - ensure("rect1 != rect1 (false)", ! (rect1 != rect1)); - } - - template<> template<> - void object::test<15>() - { - // - // test the copy constructor - // - - LLRectf rect1, rect2(rect1); - - ensure("rect1 == rect2 (true)", rect1 == rect2); - ensure("rect1 != rect2 (false)", ! (rect1 != rect2)); - } - - template<> template<> - void object::test<16>() - { - // - // test the translate() method - // - - LLRectf rect1(-1.0f, 1.0f, 1.0f, -1.0f); - LLRectf rect2(rect1); - - rect1.translate(0.0f, 0.0f); - - ensure("translate(0, 0)", rect1 == rect2); - - rect1.translate(100.0f, 100.0f); - rect1.translate(-100.0f, -100.0f); - - ensure("translate(100, 100) + translate(-100, -100)", rect1 == rect2); - - rect1.translate(10.0f, 0.0f); - rect2.set(9.0f, 1.0f, 11.0f, -1.0f); - ensure("translate(10, 0)", rect1 == rect2); - - rect1.translate(0.0f, 10.0f); - rect2.set(9.0f, 11.0f, 11.0f, 9.0f); - ensure("translate(0, 10)", rect1 == rect2); - - rect1.translate(-10.0f, -10.0f); - rect2.set(-1.0f, 1.0f, 1.0f, -1.0f); - ensure("translate(-10, -10)", rect1 == rect2); - } - - template<> template<> - void object::test<17>() - { - // - // test the stretch() method - // - - LLRectf rect1(-1.0f, 1.0f, 1.0f, -1.0f); - LLRectf rect2(rect1); - - rect1.stretch(0.0f); - ensure("stretch(0)", rect1 == rect2); - - rect1.stretch(0.0f, 0.0f); - ensure("stretch(0, 0)", rect1 == rect2); - - rect1.stretch(10.0f); - rect1.stretch(-10.0f); - ensure("stretch(10) + stretch(-10)", rect1 == rect2); - - rect1.stretch(2.0f, 1.0f); - rect2.set(-3.0f, 2.0f, 3.0f, -2.0f); - ensure("stretch(2, 1)", rect1 == rect2); - } - - - template<> template<> - void object::test<18>() - { - // - // test the unionWith() method - // - - LLRectf rect1, rect2, rect3; - - rect1.set(-1.0f, 1.0f, 1.0f, -1.0f); - rect2.set(-1.0f, 1.0f, 1.0f, -1.0f); - rect3 = rect1; - rect3.unionWith(rect2); - ensure_equals("union with self", rect3, rect1); - - rect1.set(-1.0f, 1.0f, 1.0f, -1.0f); - rect2.set(-2.0f, 2.0f, 0.0f, 0.0f); - rect3 = rect1; - rect3.unionWith(rect2); - ensure_equals("union - overlap", rect3, LLRectf(-2.0f, 2.0f, 1.0f, -1.0f)); - - rect1.set(-1.0f, 1.0f, 1.0f, -1.0f); - rect2.set(5.0f, 10.0f, 10.0f, 5.0f); - rect3 = rect1; - rect3.unionWith(rect2); - ensure_equals("union - no overlap", rect3, LLRectf(-1.0f, 10.0f, 10.0f, -1.0f)); - } - - template<> template<> - void object::test<19>() - { - // - // test the intersectWith() methods - // - - LLRectf rect1, rect2, rect3; - - rect1.set(-1.0f, 1.0f, 1.0f, -1.0f); - rect2.set(-1.0f, 1.0f, 1.0f, -1.0f); - rect3 = rect1; - rect3.intersectWith(rect2); - ensure_equals("intersect with self", rect3, rect1); - - rect1.set(-1.0f, 1.0f, 1.0f, -1.0f); - rect2.set(-2.0f, 2.0f, 0.0f, 0.0f); - rect3 = rect1; - rect3.intersectWith(rect2); - ensure_equals("intersect - overlap", rect3, LLRectf(-1.0f, 1.0f, 0.0f, 0.0f)); - - rect1.set(-1.0f, 1.0f, 1.0f, -1.0f); - rect2.set(5.0f, 10.0f, 10.0f, 5.0f); - rect3 = rect1; - rect3.intersectWith(rect2); - ensure("intersect - no overlap", rect3.isEmpty()); - } - - template<> template<> - void object::test<20>() - { - // - // test the pointInRect() method - // - - LLRectf rect(1.0f, 3.0f, 3.0f, 1.0f); - - ensure("(0,0) not in rect", rect.pointInRect(0.0f, 0.0f) == false); - ensure("(2,2) in rect", rect.pointInRect(2.0f, 2.0f) == true); - ensure("(1,1) in rect", rect.pointInRect(1.0f, 1.0f) == true); - ensure("(3,3) not in rect", rect.pointInRect(3.0f, 3.0f) == false); - ensure("(2.999,2.999) in rect", rect.pointInRect(2.999f, 2.999f) == true); - ensure("(2.999,3.0) not in rect", rect.pointInRect(2.999f, 3.0f) == false); - ensure("(3.0,2.999) not in rect", rect.pointInRect(3.0f, 2.999f) == false); - } - - template<> template<> - void object::test<21>() - { - // - // test the localPointInRect() method - // - - LLRectf rect(1.0f, 3.0f, 3.0f, 1.0f); - - ensure("(0,0) in local rect", rect.localPointInRect(0.0f, 0.0f) == true); - ensure("(-0.0001,-0.0001) not in local rect", rect.localPointInRect(-0.0001f, -0.001f) == false); - ensure("(1,1) in local rect", rect.localPointInRect(1.0f, 1.0f) == true); - ensure("(2,2) not in local rect", rect.localPointInRect(2.0f, 2.0f) == false); - ensure("(1.999,1.999) in local rect", rect.localPointInRect(1.999f, 1.999f) == true); - ensure("(1.999,2.0) not in local rect", rect.localPointInRect(1.999f, 2.0f) == false); - ensure("(2.0,1.999) not in local rect", rect.localPointInRect(2.0f, 1.999f) == false); - } - - template<> template<> - void object::test<22>() - { - // - // test the clampPointToRect() method - // - - LLRectf rect(1.0f, 3.0f, 3.0f, 1.0f); - F32 x, y; - - x = 2.0f; y = 2.0f; - rect.clampPointToRect(x, y); - ensure_equals("clamp x-coord within rect", x, 2.0f); - ensure_equals("clamp y-coord within rect", y, 2.0f); - - x = -100.0f; y = 100.0f; - rect.clampPointToRect(x, y); - ensure_equals("clamp x-coord outside rect", x, 1.0f); - ensure_equals("clamp y-coord outside rect", y, 3.0f); - - x = 3.0f; y = 1.0f; - rect.clampPointToRect(x, y); - ensure_equals("clamp x-coord edge rect", x, 3.0f); - ensure_equals("clamp y-coord edge rect", y, 1.0f); - } + template<> template<> + void object::test<1>() + { + // + // test the LLRect default constructor + // + + LLSD zero; + zero.append(0); zero.append(0); zero.append(0); zero.append(0); + + // default constructor + LLRect rect1; + ensure_equals("Empty rect", rect1.getValue(), zero); + ensure_equals("Empty rect left", rect1.mLeft, 0); + ensure_equals("Empty rect top", rect1.mTop, 0); + ensure_equals("Empty rect right", rect1.mRight, 0); + ensure_equals("Empty rect bottom", rect1.mBottom, 0); + ensure_equals("Empty rect width", rect1.getWidth(), 0); + ensure_equals("Empty rect height", rect1.getHeight(), 0); + ensure_equals("Empty rect centerx", rect1.getCenterX(), 0); + ensure_equals("Empty rect centery", rect1.getCenterY(), 0); + } + + template<> template<> + void object::test<2>() + { + // + // test the LLRectf default constructor + // + + LLSD zerof; + zerof.append(0.0f); zerof.append(0.0f); zerof.append(0.0f); zerof.append(0.0f); + + LLRectf rect2; + ensure_equals("Empty rectf", rect2.getValue(), zerof); + ensure_equals("Empty rectf left", rect2.mLeft, 0.0f); + ensure_equals("Empty rectf top", rect2.mTop, 0.0f); + ensure_equals("Empty rectf right", rect2.mRight, 0.0f); + ensure_equals("Empty rectf bottom", rect2.mBottom, 0.0f); + ensure_equals("Empty rectf width", rect2.getWidth(), 0.0f); + ensure_equals("Empty rectf height", rect2.getHeight(), 0.0f); + ensure_equals("Empty rectf centerx", rect2.getCenterX(), 0.0f); + ensure_equals("Empty rectf centery", rect2.getCenterY(), 0.0f); + } + + template<> template<> + void object::test<3>() + { + // + // test the LLRect constructor from another LLRect + // + + LLRect rect3(LLRect(1, 6, 7, 2)); + ensure_equals("Default rect left", rect3.mLeft, 1); + ensure_equals("Default rect top", rect3.mTop, 6); + ensure_equals("Default rect right", rect3.mRight, 7); + ensure_equals("Default rect bottom", rect3.mBottom, 2); + ensure_equals("Default rect width", rect3.getWidth(), 6); + ensure_equals("Default rect height", rect3.getHeight(), 4); + ensure_equals("Default rect centerx", rect3.getCenterX(), 4); + ensure_equals("Default rect centery", rect3.getCenterY(), 4); + } + + template<> template<> + void object::test<4>() + { + // + // test the LLRectf four-float constructor + // + + LLRectf rect4(1.0f, 5.0f, 6.0f, 2.0f); + ensure_equals("Default rectf left", rect4.mLeft, 1.0f); + ensure_equals("Default rectf top", rect4.mTop, 5.0f); + ensure_equals("Default rectf right", rect4.mRight, 6.0f); + ensure_equals("Default rectf bottom", rect4.mBottom, 2.0f); + ensure_equals("Default rectf width", rect4.getWidth(), 5.0f); + ensure_equals("Default rectf height", rect4.getHeight(), 3.0f); + ensure_equals("Default rectf centerx", rect4.getCenterX(), 3.5f); + ensure_equals("Default rectf centery", rect4.getCenterY(), 3.5f); + } + + template<> template<> + void object::test<5>() + { + // + // test the LLRectf LLSD constructor + // + + LLSD array; + array.append(-1.0f); array.append(0.0f); array.append(0.0f); array.append(-1.0f); + LLRectf rect5(array); + ensure_equals("LLSD rectf left", rect5.mLeft, -1.0f); + ensure_equals("LLSD rectf top", rect5.mTop, 0.0f); + ensure_equals("LLSD rectf right", rect5.mRight, 0.0f); + ensure_equals("LLSD rectf bottom", rect5.mBottom, -1.0f); + ensure_equals("LLSD rectf width", rect5.getWidth(), 1.0f); + ensure_equals("LLSD rectf height", rect5.getHeight(), 1.0f); + ensure_equals("LLSD rectf centerx", rect5.getCenterX(), -0.5f); + ensure_equals("LLSD rectf centery", rect5.getCenterY(), -0.5f); + } + + template<> template<> + void object::test<6>() + { + // + // test directly setting the member variables for dimensions + // + + LLRectf rectf; + + rectf.mLeft = -1.0f; + rectf.mTop = 1.0f; + rectf.mRight = 1.0f; + rectf.mBottom = -1.0f; + ensure_equals("Member-set rectf left", rectf.mLeft, -1.0f); + ensure_equals("Member-set rectf top", rectf.mTop, 1.0f); + ensure_equals("Member-set rectf right", rectf.mRight, 1.0f); + ensure_equals("Member-set rectf bottom", rectf.mBottom, -1.0f); + ensure_equals("Member-set rectf width", rectf.getWidth(), 2.0f); + ensure_equals("Member-set rectf height", rectf.getHeight(), 2.0f); + ensure_equals("Member-set rectf centerx", rectf.getCenterX(), 0.0f); + ensure_equals("Member-set rectf centery", rectf.getCenterY(), 0.0f); + } + + template<> template<> + void object::test<7>() + { + // + // test the setValue() method + // + + LLRectf rectf; + + LLSD array; + array.append(-1.0f); array.append(0.0f); array.append(0.0f); array.append(-1.0f); + rectf.setValue(array); + ensure_equals("setValue() rectf left", rectf.mLeft, -1.0f); + ensure_equals("setValue() rectf top", rectf.mTop, 0.0f); + ensure_equals("setValue() rectf right", rectf.mRight, 0.0f); + ensure_equals("setValue() rectf bottom", rectf.mBottom, -1.0f); + ensure_equals("setValue() rectf width", rectf.getWidth(), 1.0f); + ensure_equals("setValue() rectf height", rectf.getHeight(), 1.0f); + ensure_equals("setValue() rectf centerx", rectf.getCenterX(), -0.5f); + ensure_equals("setValue() rectf centery", rectf.getCenterY(), -0.5f); + } + + template<> template<> + void object::test<8>() + { + // + // test the set() method + // + + LLRect rect; + + rect.set(10, 90, 70, 10); + ensure_equals("set() rectf left", rect.mLeft, 10); + ensure_equals("set() rectf top", rect.mTop, 90); + ensure_equals("set() rectf right", rect.mRight, 70); + ensure_equals("set() rectf bottom", rect.mBottom, 10); + ensure_equals("set() rectf width", rect.getWidth(), 60); + ensure_equals("set() rectf height", rect.getHeight(), 80); + ensure_equals("set() rectf centerx", rect.getCenterX(), 40); + ensure_equals("set() rectf centery", rect.getCenterY(), 50); + } + + template<> template<> + void object::test<9>() + { + // + // test the setOriginAndSize() method + // + + LLRectf rectf; + + rectf.setOriginAndSize(0.0f, 0.0f, 2.0f, 1.0f); + ensure_equals("setOriginAndSize() rectf left", rectf.mLeft, 0.0f); + ensure_equals("setOriginAndSize() rectf top", rectf.mTop, 1.0f); + ensure_equals("setOriginAndSize() rectf right", rectf.mRight, 2.0f); + ensure_equals("setOriginAndSize() rectf bottom", rectf.mBottom, 0.0f); + ensure_equals("setOriginAndSize() rectf width", rectf.getWidth(), 2.0f); + ensure_equals("setOriginAndSize() rectf height", rectf.getHeight(), 1.0f); + ensure_equals("setOriginAndSize() rectf centerx", rectf.getCenterX(), 1.0f); + ensure_equals("setOriginAndSize() rectf centery", rectf.getCenterY(), 0.5f); + } + + template<> template<> + void object::test<10>() + { + // + // test the setLeftTopAndSize() method + // + + LLRectf rectf; + + rectf.setLeftTopAndSize(0.0f, 0.0f, 2.0f, 1.0f); + ensure_equals("setLeftTopAndSize() rectf left", rectf.mLeft, 0.0f); + ensure_equals("setLeftTopAndSize() rectf top", rectf.mTop, 0.0f); + ensure_equals("setLeftTopAndSize() rectf right", rectf.mRight, 2.0f); + ensure_equals("setLeftTopAndSize() rectf bottom", rectf.mBottom, -1.0f); + ensure_equals("setLeftTopAndSize() rectf width", rectf.getWidth(), 2.0f); + ensure_equals("setLeftTopAndSize() rectf height", rectf.getHeight(), 1.0f); + ensure_equals("setLeftTopAndSize() rectf centerx", rectf.getCenterX(), 1.0f); + ensure_equals("setLeftTopAndSize() rectf centery", rectf.getCenterY(), -0.5f); + } + + template<> template<> + void object::test<11>() + { + // + // test the setCenterAndSize() method + // + + LLRectf rectf; + + rectf.setCenterAndSize(0.0f, 0.0f, 2.0f, 1.0f); + ensure_equals("setCenterAndSize() rectf left", rectf.mLeft, -1.0f); + ensure_equals("setCenterAndSize() rectf top", rectf.mTop, 0.5f); + ensure_equals("setCenterAndSize() rectf right", rectf.mRight, 1.0f); + ensure_equals("setCenterAndSize() rectf bottom", rectf.mBottom, -0.5f); + ensure_equals("setCenterAndSize() rectf width", rectf.getWidth(), 2.0f); + ensure_equals("setCenterAndSize() rectf height", rectf.getHeight(), 1.0f); + ensure_equals("setCenterAndSize() rectf centerx", rectf.getCenterX(), 0.0f); + ensure_equals("setCenterAndSize() rectf centery", rectf.getCenterY(), 0.0f); + } + + template<> template<> + void object::test<12>() + { + // + // test the validity checking method + // + + LLRectf rectf; + + rectf.set(-1.0f, 1.0f, 1.0f, -1.0f); + ensure("BBox is valid", rectf.isValid()); + + rectf.mLeft = 2.0f; + ensure("BBox is not valid", ! rectf.isValid()); + + rectf.makeValid(); + ensure("BBox forced valid", rectf.isValid()); + + rectf.set(-1.0f, -1.0f, -1.0f, -1.0f); + ensure("BBox(0,0,0,0) is valid", rectf.isValid()); + } + + template<> template<> + void object::test<13>() + { + // + // test the null checking methods + // + + LLRectf rectf; + + rectf.set(-1.0f, 1.0f, 1.0f, -1.0f); + ensure("BBox is not Null", ! rectf.isEmpty()); + ensure("BBox notNull", rectf.notEmpty()); + + rectf.mLeft = 2.0f; + rectf.makeValid(); + ensure("BBox is now Null", rectf.isEmpty()); + + rectf.set(-1.0f, -1.0f, -1.0f, -1.0f); + ensure("BBox(0,0,0,0) is Null", rectf.isEmpty()); + } + + template<> template<> + void object::test<14>() + { + // + // test the (in)equality operators + // + + LLRectf rect1, rect2; + + rect1.set(-1.0f, 1.0f, 1.0f, -1.0f); + rect2.set(-1.0f, 0.9f, 1.0f, -1.0f); + + ensure("rect1 == rect2 (false)", ! (rect1 == rect2)); + ensure("rect1 != rect2 (true)", rect1 != rect2); + + ensure("rect1 == rect1 (true)", rect1 == rect1); + ensure("rect1 != rect1 (false)", ! (rect1 != rect1)); + } + + template<> template<> + void object::test<15>() + { + // + // test the copy constructor + // + + LLRectf rect1, rect2(rect1); + + ensure("rect1 == rect2 (true)", rect1 == rect2); + ensure("rect1 != rect2 (false)", ! (rect1 != rect2)); + } + + template<> template<> + void object::test<16>() + { + // + // test the translate() method + // + + LLRectf rect1(-1.0f, 1.0f, 1.0f, -1.0f); + LLRectf rect2(rect1); + + rect1.translate(0.0f, 0.0f); + + ensure("translate(0, 0)", rect1 == rect2); + + rect1.translate(100.0f, 100.0f); + rect1.translate(-100.0f, -100.0f); + + ensure("translate(100, 100) + translate(-100, -100)", rect1 == rect2); + + rect1.translate(10.0f, 0.0f); + rect2.set(9.0f, 1.0f, 11.0f, -1.0f); + ensure("translate(10, 0)", rect1 == rect2); + + rect1.translate(0.0f, 10.0f); + rect2.set(9.0f, 11.0f, 11.0f, 9.0f); + ensure("translate(0, 10)", rect1 == rect2); + + rect1.translate(-10.0f, -10.0f); + rect2.set(-1.0f, 1.0f, 1.0f, -1.0f); + ensure("translate(-10, -10)", rect1 == rect2); + } + + template<> template<> + void object::test<17>() + { + // + // test the stretch() method + // + + LLRectf rect1(-1.0f, 1.0f, 1.0f, -1.0f); + LLRectf rect2(rect1); + + rect1.stretch(0.0f); + ensure("stretch(0)", rect1 == rect2); + + rect1.stretch(0.0f, 0.0f); + ensure("stretch(0, 0)", rect1 == rect2); + + rect1.stretch(10.0f); + rect1.stretch(-10.0f); + ensure("stretch(10) + stretch(-10)", rect1 == rect2); + + rect1.stretch(2.0f, 1.0f); + rect2.set(-3.0f, 2.0f, 3.0f, -2.0f); + ensure("stretch(2, 1)", rect1 == rect2); + } + + + template<> template<> + void object::test<18>() + { + // + // test the unionWith() method + // + + LLRectf rect1, rect2, rect3; + + rect1.set(-1.0f, 1.0f, 1.0f, -1.0f); + rect2.set(-1.0f, 1.0f, 1.0f, -1.0f); + rect3 = rect1; + rect3.unionWith(rect2); + ensure_equals("union with self", rect3, rect1); + + rect1.set(-1.0f, 1.0f, 1.0f, -1.0f); + rect2.set(-2.0f, 2.0f, 0.0f, 0.0f); + rect3 = rect1; + rect3.unionWith(rect2); + ensure_equals("union - overlap", rect3, LLRectf(-2.0f, 2.0f, 1.0f, -1.0f)); + + rect1.set(-1.0f, 1.0f, 1.0f, -1.0f); + rect2.set(5.0f, 10.0f, 10.0f, 5.0f); + rect3 = rect1; + rect3.unionWith(rect2); + ensure_equals("union - no overlap", rect3, LLRectf(-1.0f, 10.0f, 10.0f, -1.0f)); + } + + template<> template<> + void object::test<19>() + { + // + // test the intersectWith() methods + // + + LLRectf rect1, rect2, rect3; + + rect1.set(-1.0f, 1.0f, 1.0f, -1.0f); + rect2.set(-1.0f, 1.0f, 1.0f, -1.0f); + rect3 = rect1; + rect3.intersectWith(rect2); + ensure_equals("intersect with self", rect3, rect1); + + rect1.set(-1.0f, 1.0f, 1.0f, -1.0f); + rect2.set(-2.0f, 2.0f, 0.0f, 0.0f); + rect3 = rect1; + rect3.intersectWith(rect2); + ensure_equals("intersect - overlap", rect3, LLRectf(-1.0f, 1.0f, 0.0f, 0.0f)); + + rect1.set(-1.0f, 1.0f, 1.0f, -1.0f); + rect2.set(5.0f, 10.0f, 10.0f, 5.0f); + rect3 = rect1; + rect3.intersectWith(rect2); + ensure("intersect - no overlap", rect3.isEmpty()); + } + + template<> template<> + void object::test<20>() + { + // + // test the pointInRect() method + // + + LLRectf rect(1.0f, 3.0f, 3.0f, 1.0f); + + ensure("(0,0) not in rect", rect.pointInRect(0.0f, 0.0f) == false); + ensure("(2,2) in rect", rect.pointInRect(2.0f, 2.0f) == true); + ensure("(1,1) in rect", rect.pointInRect(1.0f, 1.0f) == true); + ensure("(3,3) not in rect", rect.pointInRect(3.0f, 3.0f) == false); + ensure("(2.999,2.999) in rect", rect.pointInRect(2.999f, 2.999f) == true); + ensure("(2.999,3.0) not in rect", rect.pointInRect(2.999f, 3.0f) == false); + ensure("(3.0,2.999) not in rect", rect.pointInRect(3.0f, 2.999f) == false); + } + + template<> template<> + void object::test<21>() + { + // + // test the localPointInRect() method + // + + LLRectf rect(1.0f, 3.0f, 3.0f, 1.0f); + + ensure("(0,0) in local rect", rect.localPointInRect(0.0f, 0.0f) == true); + ensure("(-0.0001,-0.0001) not in local rect", rect.localPointInRect(-0.0001f, -0.001f) == false); + ensure("(1,1) in local rect", rect.localPointInRect(1.0f, 1.0f) == true); + ensure("(2,2) not in local rect", rect.localPointInRect(2.0f, 2.0f) == false); + ensure("(1.999,1.999) in local rect", rect.localPointInRect(1.999f, 1.999f) == true); + ensure("(1.999,2.0) not in local rect", rect.localPointInRect(1.999f, 2.0f) == false); + ensure("(2.0,1.999) not in local rect", rect.localPointInRect(2.0f, 1.999f) == false); + } + + template<> template<> + void object::test<22>() + { + // + // test the clampPointToRect() method + // + + LLRectf rect(1.0f, 3.0f, 3.0f, 1.0f); + F32 x, y; + + x = 2.0f; y = 2.0f; + rect.clampPointToRect(x, y); + ensure_equals("clamp x-coord within rect", x, 2.0f); + ensure_equals("clamp y-coord within rect", y, 2.0f); + + x = -100.0f; y = 100.0f; + rect.clampPointToRect(x, y); + ensure_equals("clamp x-coord outside rect", x, 1.0f); + ensure_equals("clamp y-coord outside rect", y, 3.0f); + + x = 3.0f; y = 1.0f; + rect.clampPointToRect(x, y); + ensure_equals("clamp x-coord edge rect", x, 3.0f); + ensure_equals("clamp y-coord edge rect", y, 1.0f); + } } diff --git a/indra/llmath/tests/m3math_test.cpp b/indra/llmath/tests/m3math_test.cpp index 2a0fe76aa7..b023c85ffd 100644 --- a/indra/llmath/tests/m3math_test.cpp +++ b/indra/llmath/tests/m3math_test.cpp @@ -1,4 +1,4 @@ -/** +/** * @file m3math_test.cpp * @author Adroit * @date 2007-03 @@ -7,21 +7,21 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -49,284 +49,284 @@ namespace tut { - struct m3math_test - { - }; - typedef test_group<m3math_test> m3math_test_t; - typedef m3math_test_t::object m3math_test_object_t; - tut::m3math_test_t tut_m3math_test("m3math_h"); - - //test case for setIdentity() fn. - template<> template<> - void m3math_test_object_t::test<1>() - { - LLMatrix3 llmat3_obj; - llmat3_obj.setIdentity(); - ensure("LLMatrix3::setIdentity failed", 1.f == llmat3_obj.mMatrix[0][0] && - 0.f == llmat3_obj.mMatrix[0][1] && - 0.f == llmat3_obj.mMatrix[0][2] && - 0.f == llmat3_obj.mMatrix[1][0] && - 1.f == llmat3_obj.mMatrix[1][1] && - 0.f == llmat3_obj.mMatrix[1][2] && - 0.f == llmat3_obj.mMatrix[2][0] && - 0.f == llmat3_obj.mMatrix[2][1] && - 1.f == llmat3_obj.mMatrix[2][2]); - } - - //test case for LLMatrix3& setZero() fn. - template<> template<> - void m3math_test_object_t::test<2>() - { - LLMatrix3 llmat3_obj; - llmat3_obj.setZero(); - - ensure("LLMatrix3::setZero failed", 0.f == llmat3_obj.setZero().mMatrix[0][0] && - 0.f == llmat3_obj.setZero().mMatrix[0][1] && - 0.f == llmat3_obj.setZero().mMatrix[0][2] && - 0.f == llmat3_obj.setZero().mMatrix[1][0] && - 0.f == llmat3_obj.setZero().mMatrix[1][1] && - 0.f == llmat3_obj.setZero().mMatrix[1][2] && - 0.f == llmat3_obj.setZero().mMatrix[2][0] && - 0.f == llmat3_obj.setZero().mMatrix[2][1] && - 0.f == llmat3_obj.setZero().mMatrix[2][2]); - } - - //test case for setRows(const LLVector3 &x_axis, const LLVector3 &y_axis, const LLVector3 &z_axis) fns. - template<> template<> - void m3math_test_object_t::test<3>() - { - LLMatrix3 llmat3_obj; - LLVector3 vect1(2, 1, 4); - LLVector3 vect2(3, 5, 7); - LLVector3 vect3(6, 9, 7); - llmat3_obj.setRows(vect1, vect2, vect3); - ensure("LLVector3::setRows failed ", 2 == llmat3_obj.mMatrix[0][0] && - 1 == llmat3_obj.mMatrix[0][1] && - 4 == llmat3_obj.mMatrix[0][2] && - 3 == llmat3_obj.mMatrix[1][0] && - 5 == llmat3_obj.mMatrix[1][1] && - 7 == llmat3_obj.mMatrix[1][2] && - 6 == llmat3_obj.mMatrix[2][0] && - 9 == llmat3_obj.mMatrix[2][1] && - 7 == llmat3_obj.mMatrix[2][2]); - } - - //test case for getFwdRow(), getLeftRow(), getUpRow() fns. - template<> template<> - void m3math_test_object_t::test<4>() - { - LLMatrix3 llmat3_obj; - LLVector3 vect1(2, 1, 4); - LLVector3 vect2(3, 5, 7); - LLVector3 vect3(6, 9, 7); - llmat3_obj.setRows(vect1, vect2, vect3); - - ensure("LLVector3::getFwdRow failed ", vect1 == llmat3_obj.getFwdRow()); - ensure("LLVector3::getLeftRow failed ", vect2 == llmat3_obj.getLeftRow()); - ensure("LLVector3::getUpRow failed ", vect3 == llmat3_obj.getUpRow()); - } - - //test case for operator*(const LLMatrix3 &a, const LLMatrix3 &b) - template<> template<> - void m3math_test_object_t::test<5>() - { - LLMatrix3 llmat_obj1; - LLMatrix3 llmat_obj2; - LLMatrix3 llmat_obj3; - - LLVector3 llvec1(1, 3, 5); - LLVector3 llvec2(3, 6, 1); - LLVector3 llvec3(4, 6, 9); - - LLVector3 llvec4(1, 1, 5); - LLVector3 llvec5(3, 6, 8); - LLVector3 llvec6(8, 6, 2); - - LLVector3 llvec7(0, 0, 0); - LLVector3 llvec8(0, 0, 0); - LLVector3 llvec9(0, 0, 0); - - llmat_obj1.setRows(llvec1, llvec2, llvec3); - llmat_obj2.setRows(llvec4, llvec5, llvec6); - llmat_obj3.setRows(llvec7, llvec8, llvec9); - llmat_obj3 = llmat_obj1 * llmat_obj2; - ensure("LLMatrix3::operator*(const LLMatrix3 &a, const LLMatrix3 &b) failed", - 50 == llmat_obj3.mMatrix[0][0] && - 49 == llmat_obj3.mMatrix[0][1] && - 39 == llmat_obj3.mMatrix[0][2] && - 29 == llmat_obj3.mMatrix[1][0] && - 45 == llmat_obj3.mMatrix[1][1] && - 65 == llmat_obj3.mMatrix[1][2] && - 94 == llmat_obj3.mMatrix[2][0] && - 94 == llmat_obj3.mMatrix[2][1] && - 86 == llmat_obj3.mMatrix[2][2]); - } - - - //test case for operator*(const LLVector3 &a, const LLMatrix3 &b) - template<> template<> - void m3math_test_object_t::test<6>() - { - - LLMatrix3 llmat_obj1; - - LLVector3 llvec(1, 3, 5); - LLVector3 res_vec(0, 0, 0); - LLVector3 llvec1(1, 3, 5); - LLVector3 llvec2(3, 6, 1); - LLVector3 llvec3(4, 6, 9); - - llmat_obj1.setRows(llvec1, llvec2, llvec3); - res_vec = llvec * llmat_obj1; - - LLVector3 expected_result(30, 51, 53); - - ensure("LLMatrix3::operator*(const LLVector3 &a, const LLMatrix3 &b) failed", res_vec == expected_result); - } - - //test case for operator*(const LLVector3d &a, const LLMatrix3 &b) - template<> template<> - void m3math_test_object_t::test<7>() - { - LLMatrix3 llmat_obj1; - LLVector3d llvec3d1; - LLVector3d llvec3d2(0, 3, 4); - - LLVector3 llvec1(1, 3, 5); - LLVector3 llvec2(3, 2, 1); - LLVector3 llvec3(4, 6, 0); - - llmat_obj1.setRows(llvec1, llvec2, llvec3); - llvec3d1 = llvec3d2 * llmat_obj1; - - LLVector3d expected_result(25, 30, 3); - - ensure("LLMatrix3::operator*(const LLVector3 &a, const LLMatrix3 &b) failed", llvec3d1 == expected_result); - } - - // test case for operator==(const LLMatrix3 &a, const LLMatrix3 &b) - template<> template<> - void m3math_test_object_t::test<8>() - { - LLMatrix3 llmat_obj1; - LLMatrix3 llmat_obj2; - - LLVector3 llvec1(1, 3, 5); - LLVector3 llvec2(3, 6, 1); - LLVector3 llvec3(4, 6, 9); - - llmat_obj1.setRows(llvec1, llvec2, llvec3); - llmat_obj2.setRows(llvec1, llvec2, llvec3); - ensure("LLMatrix3::operator==(const LLMatrix3 &a, const LLMatrix3 &b) failed", llmat_obj1 == llmat_obj2); - - llmat_obj2.setRows(llvec2, llvec2, llvec3); - ensure("LLMatrix3::operator!=(const LLMatrix3 &a, const LLMatrix3 &b) failed", llmat_obj1 != llmat_obj2); - } - - //test case for quaternion() fn. - template<> template<> - void m3math_test_object_t::test<9>() - { - LLMatrix3 llmat_obj1; - LLQuaternion llmat_quat; - - LLVector3 llmat1(2.0f, 1.0f, 6.0f); - LLVector3 llmat2(1.0f, 1.0f, 3.0f); - LLVector3 llmat3(1.0f, 7.0f, 5.0f); - - llmat_obj1.setRows(llmat1, llmat2, llmat3); - llmat_quat = llmat_obj1.quaternion(); - ensure("LLMatrix3::quaternion failed ", is_approx_equal(-0.66666669f, llmat_quat.mQ[0]) && - is_approx_equal(-0.83333337f, llmat_quat.mQ[1]) && - is_approx_equal(0.0f, llmat_quat.mQ[2]) && - is_approx_equal(1.5f, llmat_quat.mQ[3])); - } - - //test case for transpose() fn. - template<> template<> - void m3math_test_object_t::test<10>() - { - LLMatrix3 llmat_obj; - - LLVector3 llvec1(1, 2, 3); - LLVector3 llvec2(3, 2, 1); - LLVector3 llvec3(2, 2, 2); - - llmat_obj.setRows(llvec1, llvec2, llvec3); - llmat_obj.transpose(); - - LLVector3 resllvec1(1, 3, 2); - LLVector3 resllvec2(2, 2, 2); - LLVector3 resllvec3(3, 1, 2); - LLMatrix3 expectedllmat_obj; - expectedllmat_obj.setRows(resllvec1, resllvec2, resllvec3); - - ensure("LLMatrix3::transpose failed ", llmat_obj == expectedllmat_obj); - } - - //test case for determinant() fn. - template<> template<> - void m3math_test_object_t::test<11>() - { - LLMatrix3 llmat_obj1; - - LLVector3 llvec1(1, 2, 3); - LLVector3 llvec2(3, 2, 1); - LLVector3 llvec3(2, 2, 2); - llmat_obj1.setRows(llvec1, llvec2, llvec3); - ensure("LLMatrix3::determinant failed ", 0.0f == llmat_obj1.determinant()); - } - - //test case for orthogonalize() fn. - template<> template<> - void m3math_test_object_t::test<12>() - { - LLMatrix3 llmat_obj; - - LLVector3 llvec1(1, 4, 3); - LLVector3 llvec2(1, 2, 0); - LLVector3 llvec3(2, 4, 2); + struct m3math_test + { + }; + typedef test_group<m3math_test> m3math_test_t; + typedef m3math_test_t::object m3math_test_object_t; + tut::m3math_test_t tut_m3math_test("m3math_h"); + + //test case for setIdentity() fn. + template<> template<> + void m3math_test_object_t::test<1>() + { + LLMatrix3 llmat3_obj; + llmat3_obj.setIdentity(); + ensure("LLMatrix3::setIdentity failed", 1.f == llmat3_obj.mMatrix[0][0] && + 0.f == llmat3_obj.mMatrix[0][1] && + 0.f == llmat3_obj.mMatrix[0][2] && + 0.f == llmat3_obj.mMatrix[1][0] && + 1.f == llmat3_obj.mMatrix[1][1] && + 0.f == llmat3_obj.mMatrix[1][2] && + 0.f == llmat3_obj.mMatrix[2][0] && + 0.f == llmat3_obj.mMatrix[2][1] && + 1.f == llmat3_obj.mMatrix[2][2]); + } + + //test case for LLMatrix3& setZero() fn. + template<> template<> + void m3math_test_object_t::test<2>() + { + LLMatrix3 llmat3_obj; + llmat3_obj.setZero(); + + ensure("LLMatrix3::setZero failed", 0.f == llmat3_obj.setZero().mMatrix[0][0] && + 0.f == llmat3_obj.setZero().mMatrix[0][1] && + 0.f == llmat3_obj.setZero().mMatrix[0][2] && + 0.f == llmat3_obj.setZero().mMatrix[1][0] && + 0.f == llmat3_obj.setZero().mMatrix[1][1] && + 0.f == llmat3_obj.setZero().mMatrix[1][2] && + 0.f == llmat3_obj.setZero().mMatrix[2][0] && + 0.f == llmat3_obj.setZero().mMatrix[2][1] && + 0.f == llmat3_obj.setZero().mMatrix[2][2]); + } + + //test case for setRows(const LLVector3 &x_axis, const LLVector3 &y_axis, const LLVector3 &z_axis) fns. + template<> template<> + void m3math_test_object_t::test<3>() + { + LLMatrix3 llmat3_obj; + LLVector3 vect1(2, 1, 4); + LLVector3 vect2(3, 5, 7); + LLVector3 vect3(6, 9, 7); + llmat3_obj.setRows(vect1, vect2, vect3); + ensure("LLVector3::setRows failed ", 2 == llmat3_obj.mMatrix[0][0] && + 1 == llmat3_obj.mMatrix[0][1] && + 4 == llmat3_obj.mMatrix[0][2] && + 3 == llmat3_obj.mMatrix[1][0] && + 5 == llmat3_obj.mMatrix[1][1] && + 7 == llmat3_obj.mMatrix[1][2] && + 6 == llmat3_obj.mMatrix[2][0] && + 9 == llmat3_obj.mMatrix[2][1] && + 7 == llmat3_obj.mMatrix[2][2]); + } + + //test case for getFwdRow(), getLeftRow(), getUpRow() fns. + template<> template<> + void m3math_test_object_t::test<4>() + { + LLMatrix3 llmat3_obj; + LLVector3 vect1(2, 1, 4); + LLVector3 vect2(3, 5, 7); + LLVector3 vect3(6, 9, 7); + llmat3_obj.setRows(vect1, vect2, vect3); + + ensure("LLVector3::getFwdRow failed ", vect1 == llmat3_obj.getFwdRow()); + ensure("LLVector3::getLeftRow failed ", vect2 == llmat3_obj.getLeftRow()); + ensure("LLVector3::getUpRow failed ", vect3 == llmat3_obj.getUpRow()); + } + + //test case for operator*(const LLMatrix3 &a, const LLMatrix3 &b) + template<> template<> + void m3math_test_object_t::test<5>() + { + LLMatrix3 llmat_obj1; + LLMatrix3 llmat_obj2; + LLMatrix3 llmat_obj3; + + LLVector3 llvec1(1, 3, 5); + LLVector3 llvec2(3, 6, 1); + LLVector3 llvec3(4, 6, 9); + + LLVector3 llvec4(1, 1, 5); + LLVector3 llvec5(3, 6, 8); + LLVector3 llvec6(8, 6, 2); + + LLVector3 llvec7(0, 0, 0); + LLVector3 llvec8(0, 0, 0); + LLVector3 llvec9(0, 0, 0); + + llmat_obj1.setRows(llvec1, llvec2, llvec3); + llmat_obj2.setRows(llvec4, llvec5, llvec6); + llmat_obj3.setRows(llvec7, llvec8, llvec9); + llmat_obj3 = llmat_obj1 * llmat_obj2; + ensure("LLMatrix3::operator*(const LLMatrix3 &a, const LLMatrix3 &b) failed", + 50 == llmat_obj3.mMatrix[0][0] && + 49 == llmat_obj3.mMatrix[0][1] && + 39 == llmat_obj3.mMatrix[0][2] && + 29 == llmat_obj3.mMatrix[1][0] && + 45 == llmat_obj3.mMatrix[1][1] && + 65 == llmat_obj3.mMatrix[1][2] && + 94 == llmat_obj3.mMatrix[2][0] && + 94 == llmat_obj3.mMatrix[2][1] && + 86 == llmat_obj3.mMatrix[2][2]); + } + + + //test case for operator*(const LLVector3 &a, const LLMatrix3 &b) + template<> template<> + void m3math_test_object_t::test<6>() + { + + LLMatrix3 llmat_obj1; + + LLVector3 llvec(1, 3, 5); + LLVector3 res_vec(0, 0, 0); + LLVector3 llvec1(1, 3, 5); + LLVector3 llvec2(3, 6, 1); + LLVector3 llvec3(4, 6, 9); + + llmat_obj1.setRows(llvec1, llvec2, llvec3); + res_vec = llvec * llmat_obj1; + + LLVector3 expected_result(30, 51, 53); + + ensure("LLMatrix3::operator*(const LLVector3 &a, const LLMatrix3 &b) failed", res_vec == expected_result); + } + + //test case for operator*(const LLVector3d &a, const LLMatrix3 &b) + template<> template<> + void m3math_test_object_t::test<7>() + { + LLMatrix3 llmat_obj1; + LLVector3d llvec3d1; + LLVector3d llvec3d2(0, 3, 4); + + LLVector3 llvec1(1, 3, 5); + LLVector3 llvec2(3, 2, 1); + LLVector3 llvec3(4, 6, 0); + + llmat_obj1.setRows(llvec1, llvec2, llvec3); + llvec3d1 = llvec3d2 * llmat_obj1; + + LLVector3d expected_result(25, 30, 3); + + ensure("LLMatrix3::operator*(const LLVector3 &a, const LLMatrix3 &b) failed", llvec3d1 == expected_result); + } + + // test case for operator==(const LLMatrix3 &a, const LLMatrix3 &b) + template<> template<> + void m3math_test_object_t::test<8>() + { + LLMatrix3 llmat_obj1; + LLMatrix3 llmat_obj2; + + LLVector3 llvec1(1, 3, 5); + LLVector3 llvec2(3, 6, 1); + LLVector3 llvec3(4, 6, 9); + + llmat_obj1.setRows(llvec1, llvec2, llvec3); + llmat_obj2.setRows(llvec1, llvec2, llvec3); + ensure("LLMatrix3::operator==(const LLMatrix3 &a, const LLMatrix3 &b) failed", llmat_obj1 == llmat_obj2); + + llmat_obj2.setRows(llvec2, llvec2, llvec3); + ensure("LLMatrix3::operator!=(const LLMatrix3 &a, const LLMatrix3 &b) failed", llmat_obj1 != llmat_obj2); + } + + //test case for quaternion() fn. + template<> template<> + void m3math_test_object_t::test<9>() + { + LLMatrix3 llmat_obj1; + LLQuaternion llmat_quat; + + LLVector3 llmat1(2.0f, 1.0f, 6.0f); + LLVector3 llmat2(1.0f, 1.0f, 3.0f); + LLVector3 llmat3(1.0f, 7.0f, 5.0f); + + llmat_obj1.setRows(llmat1, llmat2, llmat3); + llmat_quat = llmat_obj1.quaternion(); + ensure("LLMatrix3::quaternion failed ", is_approx_equal(-0.66666669f, llmat_quat.mQ[0]) && + is_approx_equal(-0.83333337f, llmat_quat.mQ[1]) && + is_approx_equal(0.0f, llmat_quat.mQ[2]) && + is_approx_equal(1.5f, llmat_quat.mQ[3])); + } + + //test case for transpose() fn. + template<> template<> + void m3math_test_object_t::test<10>() + { + LLMatrix3 llmat_obj; + + LLVector3 llvec1(1, 2, 3); + LLVector3 llvec2(3, 2, 1); + LLVector3 llvec3(2, 2, 2); + + llmat_obj.setRows(llvec1, llvec2, llvec3); + llmat_obj.transpose(); + + LLVector3 resllvec1(1, 3, 2); + LLVector3 resllvec2(2, 2, 2); + LLVector3 resllvec3(3, 1, 2); + LLMatrix3 expectedllmat_obj; + expectedllmat_obj.setRows(resllvec1, resllvec2, resllvec3); + + ensure("LLMatrix3::transpose failed ", llmat_obj == expectedllmat_obj); + } + + //test case for determinant() fn. + template<> template<> + void m3math_test_object_t::test<11>() + { + LLMatrix3 llmat_obj1; + + LLVector3 llvec1(1, 2, 3); + LLVector3 llvec2(3, 2, 1); + LLVector3 llvec3(2, 2, 2); + llmat_obj1.setRows(llvec1, llvec2, llvec3); + ensure("LLMatrix3::determinant failed ", 0.0f == llmat_obj1.determinant()); + } + + //test case for orthogonalize() fn. + template<> template<> + void m3math_test_object_t::test<12>() + { + LLMatrix3 llmat_obj; + + LLVector3 llvec1(1, 4, 3); + LLVector3 llvec2(1, 2, 0); + LLVector3 llvec3(2, 4, 2); skip("This test fails depending on architecture. Need to fix comparison operation, is_approx_equal, to work on more than one platform."); - llmat_obj.setRows(llvec1, llvec2, llvec3); - llmat_obj.orthogonalize(); - - ensure("LLMatrix3::orthogonalize failed ", - is_approx_equal(0.19611614f, llmat_obj.mMatrix[0][0]) && - is_approx_equal(0.78446454f, llmat_obj.mMatrix[0][1]) && - is_approx_equal(0.58834841f, llmat_obj.mMatrix[0][2]) && - is_approx_equal(0.47628204f, llmat_obj.mMatrix[1][0]) && - is_approx_equal(0.44826545f, llmat_obj.mMatrix[1][1]) && - is_approx_equal(-0.75644795f, llmat_obj.mMatrix[1][2]) && - is_approx_equal(-0.85714286f, llmat_obj.mMatrix[2][0]) && - is_approx_equal(0.42857143f, llmat_obj.mMatrix[2][1]) && - is_approx_equal(-0.28571429f, llmat_obj.mMatrix[2][2])); - } - - //test case for adjointTranspose() fn. - template<> template<> - void m3math_test_object_t::test<13>() - { - LLMatrix3 llmat_obj; - - LLVector3 llvec1(3, 2, 1); - LLVector3 llvec2(6, 2, 1); - LLVector3 llvec3(3, 6, 8); - - llmat_obj.setRows(llvec1, llvec2, llvec3); - llmat_obj.adjointTranspose(); - - ensure("LLMatrix3::adjointTranspose failed ", 10 == llmat_obj.mMatrix[0][0] && - -45 == llmat_obj.mMatrix[1][0] && - 30 == llmat_obj.mMatrix[2][0] && - -10 == llmat_obj.mMatrix[0][1] && - 21 == llmat_obj.mMatrix[1][1] && - -12 == llmat_obj.mMatrix[2][1] && - 0 == llmat_obj.mMatrix[0][2] && - 3 == llmat_obj.mMatrix[1][2] && - -6 == llmat_obj.mMatrix[2][2]); - } - - /* TBD: Need to add test cases for getEulerAngles() and setRot() functions */ + llmat_obj.setRows(llvec1, llvec2, llvec3); + llmat_obj.orthogonalize(); + + ensure("LLMatrix3::orthogonalize failed ", + is_approx_equal(0.19611614f, llmat_obj.mMatrix[0][0]) && + is_approx_equal(0.78446454f, llmat_obj.mMatrix[0][1]) && + is_approx_equal(0.58834841f, llmat_obj.mMatrix[0][2]) && + is_approx_equal(0.47628204f, llmat_obj.mMatrix[1][0]) && + is_approx_equal(0.44826545f, llmat_obj.mMatrix[1][1]) && + is_approx_equal(-0.75644795f, llmat_obj.mMatrix[1][2]) && + is_approx_equal(-0.85714286f, llmat_obj.mMatrix[2][0]) && + is_approx_equal(0.42857143f, llmat_obj.mMatrix[2][1]) && + is_approx_equal(-0.28571429f, llmat_obj.mMatrix[2][2])); + } + + //test case for adjointTranspose() fn. + template<> template<> + void m3math_test_object_t::test<13>() + { + LLMatrix3 llmat_obj; + + LLVector3 llvec1(3, 2, 1); + LLVector3 llvec2(6, 2, 1); + LLVector3 llvec3(3, 6, 8); + + llmat_obj.setRows(llvec1, llvec2, llvec3); + llmat_obj.adjointTranspose(); + + ensure("LLMatrix3::adjointTranspose failed ", 10 == llmat_obj.mMatrix[0][0] && + -45 == llmat_obj.mMatrix[1][0] && + 30 == llmat_obj.mMatrix[2][0] && + -10 == llmat_obj.mMatrix[0][1] && + 21 == llmat_obj.mMatrix[1][1] && + -12 == llmat_obj.mMatrix[2][1] && + 0 == llmat_obj.mMatrix[0][2] && + 3 == llmat_obj.mMatrix[1][2] && + -6 == llmat_obj.mMatrix[2][2]); + } + + /* TBD: Need to add test cases for getEulerAngles() and setRot() functions */ } diff --git a/indra/llmath/tests/mathmisc_test.cpp b/indra/llmath/tests/mathmisc_test.cpp index 46bdc1cf95..ff0899e975 100644 --- a/indra/llmath/tests/mathmisc_test.cpp +++ b/indra/llmath/tests/mathmisc_test.cpp @@ -1,4 +1,4 @@ -/** +/** * @file math.cpp * @author Phoenix * @date 2005-09-26 @@ -7,21 +7,21 @@ * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -40,684 +40,684 @@ namespace tut { - struct math_data - { - }; - typedef test_group<math_data> math_test; - typedef math_test::object math_object; - tut::math_test tm("BasicLindenMath"); - - template<> template<> - void math_object::test<1>() - { - S32 val = 89543; - val = llabs(val); - ensure("integer absolute value 1", (89543 == val)); - val = -500; - val = llabs(val); - ensure("integer absolute value 2", (500 == val)); - } - - template<> template<> - void math_object::test<2>() - { - F32 val = -2583.4f; - val = llabs(val); - ensure("float absolute value 1", (2583.4f == val)); - val = 430903.f; - val = llabs(val); - ensure("float absolute value 2", (430903.f == val)); - } - - template<> template<> - void math_object::test<3>() - { - F64 val = 387439393.987329839; - val = llabs(val); - ensure("double absolute value 1", (387439393.987329839 == val)); - val = -8937843.9394878; - val = llabs(val); - ensure("double absolute value 2", (8937843.9394878 == val)); - } - - template<> template<> - void math_object::test<4>() - { - F32 val = 430903.9f; - S32 val1 = lltrunc(val); - ensure("float truncate value 1", (430903 == val1)); - val = -2303.9f; - val1 = lltrunc(val); - ensure("float truncate value 2", (-2303 == val1)); - } - - template<> template<> - void math_object::test<5>() - { - F64 val = 387439393.987329839 ; - S32 val1 = lltrunc(val); - ensure("float truncate value 1", (387439393 == val1)); - val = -387439393.987329839; - val1 = lltrunc(val); - ensure("float truncate value 2", (-387439393 == val1)); - } - - template<> template<> - void math_object::test<6>() - { - F32 val = 430903.2f; - S32 val1 = llfloor(val); - ensure("float llfloor value 1", (430903 == val1)); - val = -430903.9f; - val1 = llfloor(val); - ensure("float llfloor value 2", (-430904 == val1)); - } - - template<> template<> - void math_object::test<7>() - { - F32 val = 430903.2f; - S32 val1 = llceil(val); - ensure("float llceil value 1", (430904 == val1)); - val = -430903.9f; - val1 = llceil(val); - ensure("float llceil value 2", (-430903 == val1)); - } - - template<> template<> - void math_object::test<8>() - { - F32 val = 430903.2f; - S32 val1 = ll_round(val); - ensure("float ll_round value 1", (430903 == val1)); - val = -430903.9f; - val1 = ll_round(val); - ensure("float ll_round value 2", (-430904 == val1)); - } - - template<> template<> - void math_object::test<9>() - { - F32 val = 430905.2654f, nearest = 100.f; - val = ll_round(val, nearest); - ensure("float ll_round value 1", (430900 == val)); - val = -430905.2654f, nearest = 10.f; - val = ll_round(val, nearest); - ensure("float ll_round value 1", (-430910 == val)); - } - - template<> template<> - void math_object::test<10>() - { - F64 val = 430905.2654, nearest = 100.0; - val = ll_round(val, nearest); - ensure("double ll_round value 1", (430900 == val)); - val = -430905.2654, nearest = 10.0; - val = ll_round(val, nearest); - ensure("double ll_round value 1", (-430910.00000 == val)); - } - - template<> template<> - void math_object::test<11>() - { - const F32 F_PI = 3.1415926535897932384626433832795f; - F32 angle = 3506.f; - angle = llsimple_angle(angle); - ensure("llsimple_angle value 1", (angle <=F_PI && angle >= -F_PI)); - angle = -431.f; - angle = llsimple_angle(angle); - ensure("llsimple_angle value 1", (angle <=F_PI && angle >= -F_PI)); - } + struct math_data + { + }; + typedef test_group<math_data> math_test; + typedef math_test::object math_object; + tut::math_test tm("BasicLindenMath"); + + template<> template<> + void math_object::test<1>() + { + S32 val = 89543; + val = llabs(val); + ensure("integer absolute value 1", (89543 == val)); + val = -500; + val = llabs(val); + ensure("integer absolute value 2", (500 == val)); + } + + template<> template<> + void math_object::test<2>() + { + F32 val = -2583.4f; + val = llabs(val); + ensure("float absolute value 1", (2583.4f == val)); + val = 430903.f; + val = llabs(val); + ensure("float absolute value 2", (430903.f == val)); + } + + template<> template<> + void math_object::test<3>() + { + F64 val = 387439393.987329839; + val = llabs(val); + ensure("double absolute value 1", (387439393.987329839 == val)); + val = -8937843.9394878; + val = llabs(val); + ensure("double absolute value 2", (8937843.9394878 == val)); + } + + template<> template<> + void math_object::test<4>() + { + F32 val = 430903.9f; + S32 val1 = lltrunc(val); + ensure("float truncate value 1", (430903 == val1)); + val = -2303.9f; + val1 = lltrunc(val); + ensure("float truncate value 2", (-2303 == val1)); + } + + template<> template<> + void math_object::test<5>() + { + F64 val = 387439393.987329839 ; + S32 val1 = lltrunc(val); + ensure("float truncate value 1", (387439393 == val1)); + val = -387439393.987329839; + val1 = lltrunc(val); + ensure("float truncate value 2", (-387439393 == val1)); + } + + template<> template<> + void math_object::test<6>() + { + F32 val = 430903.2f; + S32 val1 = llfloor(val); + ensure("float llfloor value 1", (430903 == val1)); + val = -430903.9f; + val1 = llfloor(val); + ensure("float llfloor value 2", (-430904 == val1)); + } + + template<> template<> + void math_object::test<7>() + { + F32 val = 430903.2f; + S32 val1 = llceil(val); + ensure("float llceil value 1", (430904 == val1)); + val = -430903.9f; + val1 = llceil(val); + ensure("float llceil value 2", (-430903 == val1)); + } + + template<> template<> + void math_object::test<8>() + { + F32 val = 430903.2f; + S32 val1 = ll_round(val); + ensure("float ll_round value 1", (430903 == val1)); + val = -430903.9f; + val1 = ll_round(val); + ensure("float ll_round value 2", (-430904 == val1)); + } + + template<> template<> + void math_object::test<9>() + { + F32 val = 430905.2654f, nearest = 100.f; + val = ll_round(val, nearest); + ensure("float ll_round value 1", (430900 == val)); + val = -430905.2654f, nearest = 10.f; + val = ll_round(val, nearest); + ensure("float ll_round value 1", (-430910 == val)); + } + + template<> template<> + void math_object::test<10>() + { + F64 val = 430905.2654, nearest = 100.0; + val = ll_round(val, nearest); + ensure("double ll_round value 1", (430900 == val)); + val = -430905.2654, nearest = 10.0; + val = ll_round(val, nearest); + ensure("double ll_round value 1", (-430910.00000 == val)); + } + + template<> template<> + void math_object::test<11>() + { + const F32 F_PI = 3.1415926535897932384626433832795f; + F32 angle = 3506.f; + angle = llsimple_angle(angle); + ensure("llsimple_angle value 1", (angle <=F_PI && angle >= -F_PI)); + angle = -431.f; + angle = llsimple_angle(angle); + ensure("llsimple_angle value 1", (angle <=F_PI && angle >= -F_PI)); + } } namespace tut { - struct uuid_data - { - LLUUID id; - }; - typedef test_group<uuid_data> uuid_test; - typedef uuid_test::object uuid_object; - tut::uuid_test tu("LLUUID"); - - template<> template<> - void uuid_object::test<1>() - { - ensure("uuid null", id.isNull()); - id.generate(); - ensure("generate not null", id.notNull()); - id.setNull(); - ensure("set null", id.isNull()); - } - - template<> template<> - void uuid_object::test<2>() - { - id.generate(); - LLUUID a(id); - ensure_equals("copy equal", id, a); - a.generate(); - ensure_not_equals("generate not equal", id, a); - a = id; - ensure_equals("assignment equal", id, a); - } - - template<> template<> - void uuid_object::test<3>() - { - id.generate(); - LLUUID copy(id); - LLUUID mask; - mask.generate(); - copy ^= mask; - ensure_not_equals("mask not equal", id, copy); - copy ^= mask; - ensure_equals("mask back", id, copy); - } - - template<> template<> - void uuid_object::test<4>() - { - id.generate(); - std::string id_str = id.asString(); - LLUUID copy(id_str.c_str()); - ensure_equals("string serialization", id, copy); - } - + struct uuid_data + { + LLUUID id; + }; + typedef test_group<uuid_data> uuid_test; + typedef uuid_test::object uuid_object; + tut::uuid_test tu("LLUUID"); + + template<> template<> + void uuid_object::test<1>() + { + ensure("uuid null", id.isNull()); + id.generate(); + ensure("generate not null", id.notNull()); + id.setNull(); + ensure("set null", id.isNull()); + } + + template<> template<> + void uuid_object::test<2>() + { + id.generate(); + LLUUID a(id); + ensure_equals("copy equal", id, a); + a.generate(); + ensure_not_equals("generate not equal", id, a); + a = id; + ensure_equals("assignment equal", id, a); + } + + template<> template<> + void uuid_object::test<3>() + { + id.generate(); + LLUUID copy(id); + LLUUID mask; + mask.generate(); + copy ^= mask; + ensure_not_equals("mask not equal", id, copy); + copy ^= mask; + ensure_equals("mask back", id, copy); + } + + template<> template<> + void uuid_object::test<4>() + { + id.generate(); + std::string id_str = id.asString(); + LLUUID copy(id_str.c_str()); + ensure_equals("string serialization", id, copy); + } + } namespace tut { - struct crc_data - { - }; - typedef test_group<crc_data> crc_test; - typedef crc_test::object crc_object; - tut::crc_test tc("LLCrc"); - - template<> template<> - void crc_object::test<1>() - { - /* Test buffer update and individual char update */ - const char TEST_BUFFER[] = "hello &#$)$&Nd0"; - LLCRC c1, c2; - c1.update((U8*)TEST_BUFFER, sizeof(TEST_BUFFER) - 1); - char* rh = (char*)TEST_BUFFER; - while(*rh != '\0') - { - c2.update(*rh); - ++rh; - } - ensure_equals("crc update 1", c1.getCRC(), c2.getCRC()); - } - - template<> template<> - void crc_object::test<2>() - { - /* Test mixing of buffer and individual char update */ - const char TEST_BUFFER1[] = "Split Buffer one $^%$%#@$"; - const char TEST_BUFFER2[] = "Split Buffer two )(8723#5dsds"; - LLCRC c1, c2; - c1.update((U8*)TEST_BUFFER1, sizeof(TEST_BUFFER1) - 1); - char* rh = (char*)TEST_BUFFER2; - while(*rh != '\0') - { - c1.update(*rh); - ++rh; - } - - rh = (char*)TEST_BUFFER1; - while(*rh != '\0') - { - c2.update(*rh); - ++rh; - } - c2.update((U8*)TEST_BUFFER2, sizeof(TEST_BUFFER2) - 1); - - ensure_equals("crc update 2", c1.getCRC(), c2.getCRC()); - } + struct crc_data + { + }; + typedef test_group<crc_data> crc_test; + typedef crc_test::object crc_object; + tut::crc_test tc("LLCrc"); + + template<> template<> + void crc_object::test<1>() + { + /* Test buffer update and individual char update */ + const char TEST_BUFFER[] = "hello &#$)$&Nd0"; + LLCRC c1, c2; + c1.update((U8*)TEST_BUFFER, sizeof(TEST_BUFFER) - 1); + char* rh = (char*)TEST_BUFFER; + while(*rh != '\0') + { + c2.update(*rh); + ++rh; + } + ensure_equals("crc update 1", c1.getCRC(), c2.getCRC()); + } + + template<> template<> + void crc_object::test<2>() + { + /* Test mixing of buffer and individual char update */ + const char TEST_BUFFER1[] = "Split Buffer one $^%$%#@$"; + const char TEST_BUFFER2[] = "Split Buffer two )(8723#5dsds"; + LLCRC c1, c2; + c1.update((U8*)TEST_BUFFER1, sizeof(TEST_BUFFER1) - 1); + char* rh = (char*)TEST_BUFFER2; + while(*rh != '\0') + { + c1.update(*rh); + ++rh; + } + + rh = (char*)TEST_BUFFER1; + while(*rh != '\0') + { + c2.update(*rh); + ++rh; + } + c2.update((U8*)TEST_BUFFER2, sizeof(TEST_BUFFER2) - 1); + + ensure_equals("crc update 2", c1.getCRC(), c2.getCRC()); + } } namespace tut { - struct sphere_data - { - }; - typedef test_group<sphere_data> sphere_test; - typedef sphere_test::object sphere_object; - tut::sphere_test tsphere("LLSphere"); - - template<> template<> - void sphere_object::test<1>() - { - // test LLSphere::contains() and ::overlaps() - S32 number_of_tests = 10; - for (S32 test = 0; test < number_of_tests; ++test) - { - LLVector3 first_center(1.f, 1.f, 1.f); - F32 first_radius = 3.f; - LLSphere first_sphere( first_center, first_radius ); - - F32 half_millimeter = 0.0005f; - LLVector3 direction( ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f); - direction.normalize(); - - F32 distance = ll_frand(first_radius - 2.f * half_millimeter); - LLVector3 second_center = first_center + distance * direction; - F32 second_radius = first_radius - distance - half_millimeter; - LLSphere second_sphere( second_center, second_radius ); - ensure("first sphere should contain the second", first_sphere.contains(second_sphere)); - ensure("first sphere should overlap the second", first_sphere.overlaps(second_sphere)); - - distance = first_radius + ll_frand(first_radius); - second_center = first_center + distance * direction; - second_radius = distance - first_radius + half_millimeter; - second_sphere.set( second_center, second_radius ); - ensure("first sphere should NOT contain the second", !first_sphere.contains(second_sphere)); - ensure("first sphere should overlap the second", first_sphere.overlaps(second_sphere)); - - distance = first_radius + ll_frand(first_radius) + half_millimeter; - second_center = first_center + distance * direction; - second_radius = distance - first_radius - half_millimeter; - second_sphere.set( second_center, second_radius ); - ensure("first sphere should NOT contain the second", !first_sphere.contains(second_sphere)); - ensure("first sphere should NOT overlap the second", !first_sphere.overlaps(second_sphere)); - } - } - - template<> template<> - void sphere_object::test<2>() - { - skip("See SNOW-620. Neither the test nor the code being tested seem good. Also sim-only."); - - // test LLSphere::getBoundingSphere() - S32 number_of_tests = 100; - S32 number_of_spheres = 10; - F32 sphere_center_range = 32.f; - F32 sphere_radius_range = 5.f; - - for (S32 test = 0; test < number_of_tests; ++test) - { - // gegnerate a bunch of random sphere - std::vector< LLSphere > sphere_list; - for (S32 sphere_count=0; sphere_count < number_of_spheres; ++sphere_count) - { - LLVector3 direction( ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f); - direction.normalize(); - F32 distance = ll_frand(sphere_center_range); - LLVector3 center = distance * direction; - F32 radius = ll_frand(sphere_radius_range); - LLSphere sphere( center, radius ); - sphere_list.push_back(sphere); - } - - // compute the bounding sphere - LLSphere bounding_sphere = LLSphere::getBoundingSphere(sphere_list); - - // make sure all spheres are inside the bounding sphere - { - std::vector< LLSphere >::const_iterator sphere_itr; - for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr) - { - ensure("sphere should be contained by the bounding sphere", bounding_sphere.contains(*sphere_itr)); - } - } - - // TODO -- improve LLSphere::getBoundingSphere() to the point where - // we can reduce the 'expansion' in the two tests below to about - // 2 mm or less - - F32 expansion = 0.005f; - // move all spheres out a little bit - // and count how many are NOT contained - { - std::vector< LLVector3 > uncontained_directions; - std::vector< LLSphere >::iterator sphere_itr; - for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr) - { - LLVector3 direction = sphere_itr->getCenter() - bounding_sphere.getCenter(); - direction.normalize(); - - sphere_itr->setCenter( sphere_itr->getCenter() + expansion * direction ); - if (! bounding_sphere.contains( *sphere_itr ) ) - { - uncontained_directions.push_back(direction); - } - } - ensure("when moving spheres out there should be at least two uncontained spheres", - uncontained_directions.size() > 1); - - /* TODO -- when the bounding sphere algorithm is improved we can open up this test - * at the moment it occasionally fails when the sphere collection is tight and small - * (2 meters or less) - if (2 == uncontained_directions.size() ) - { - // if there were only two uncontained spheres then - // the two directions should be nearly opposite - F32 dir_dot = uncontained_directions[0] * uncontained_directions[1]; - ensure("two uncontained spheres should lie opposite the bounding center", dir_dot < -0.95f); - } - */ - } - - // compute the new bounding sphere - bounding_sphere = LLSphere::getBoundingSphere(sphere_list); - - // increase the size of all spheres a little bit - // and count how many are NOT contained - { - std::vector< LLVector3 > uncontained_directions; - std::vector< LLSphere >::iterator sphere_itr; - for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr) - { - LLVector3 direction = sphere_itr->getCenter() - bounding_sphere.getCenter(); - direction.normalize(); - - sphere_itr->setRadius( sphere_itr->getRadius() + expansion ); - if (! bounding_sphere.contains( *sphere_itr ) ) - { - uncontained_directions.push_back(direction); - } - } - ensure("when boosting sphere radii there should be at least two uncontained spheres", - uncontained_directions.size() > 1); - - /* TODO -- when the bounding sphere algorithm is improved we can open up this test - * at the moment it occasionally fails when the sphere collection is tight and small - * (2 meters or less) - if (2 == uncontained_directions.size() ) - { - // if there were only two uncontained spheres then - // the two directions should be nearly opposite - F32 dir_dot = uncontained_directions[0] * uncontained_directions[1]; - ensure("two uncontained spheres should lie opposite the bounding center", dir_dot < -0.95f); - } - */ - } - } - } + struct sphere_data + { + }; + typedef test_group<sphere_data> sphere_test; + typedef sphere_test::object sphere_object; + tut::sphere_test tsphere("LLSphere"); + + template<> template<> + void sphere_object::test<1>() + { + // test LLSphere::contains() and ::overlaps() + S32 number_of_tests = 10; + for (S32 test = 0; test < number_of_tests; ++test) + { + LLVector3 first_center(1.f, 1.f, 1.f); + F32 first_radius = 3.f; + LLSphere first_sphere( first_center, first_radius ); + + F32 half_millimeter = 0.0005f; + LLVector3 direction( ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f); + direction.normalize(); + + F32 distance = ll_frand(first_radius - 2.f * half_millimeter); + LLVector3 second_center = first_center + distance * direction; + F32 second_radius = first_radius - distance - half_millimeter; + LLSphere second_sphere( second_center, second_radius ); + ensure("first sphere should contain the second", first_sphere.contains(second_sphere)); + ensure("first sphere should overlap the second", first_sphere.overlaps(second_sphere)); + + distance = first_radius + ll_frand(first_radius); + second_center = first_center + distance * direction; + second_radius = distance - first_radius + half_millimeter; + second_sphere.set( second_center, second_radius ); + ensure("first sphere should NOT contain the second", !first_sphere.contains(second_sphere)); + ensure("first sphere should overlap the second", first_sphere.overlaps(second_sphere)); + + distance = first_radius + ll_frand(first_radius) + half_millimeter; + second_center = first_center + distance * direction; + second_radius = distance - first_radius - half_millimeter; + second_sphere.set( second_center, second_radius ); + ensure("first sphere should NOT contain the second", !first_sphere.contains(second_sphere)); + ensure("first sphere should NOT overlap the second", !first_sphere.overlaps(second_sphere)); + } + } + + template<> template<> + void sphere_object::test<2>() + { + skip("See SNOW-620. Neither the test nor the code being tested seem good. Also sim-only."); + + // test LLSphere::getBoundingSphere() + S32 number_of_tests = 100; + S32 number_of_spheres = 10; + F32 sphere_center_range = 32.f; + F32 sphere_radius_range = 5.f; + + for (S32 test = 0; test < number_of_tests; ++test) + { + // gegnerate a bunch of random sphere + std::vector< LLSphere > sphere_list; + for (S32 sphere_count=0; sphere_count < number_of_spheres; ++sphere_count) + { + LLVector3 direction( ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f); + direction.normalize(); + F32 distance = ll_frand(sphere_center_range); + LLVector3 center = distance * direction; + F32 radius = ll_frand(sphere_radius_range); + LLSphere sphere( center, radius ); + sphere_list.push_back(sphere); + } + + // compute the bounding sphere + LLSphere bounding_sphere = LLSphere::getBoundingSphere(sphere_list); + + // make sure all spheres are inside the bounding sphere + { + std::vector< LLSphere >::const_iterator sphere_itr; + for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr) + { + ensure("sphere should be contained by the bounding sphere", bounding_sphere.contains(*sphere_itr)); + } + } + + // TODO -- improve LLSphere::getBoundingSphere() to the point where + // we can reduce the 'expansion' in the two tests below to about + // 2 mm or less + + F32 expansion = 0.005f; + // move all spheres out a little bit + // and count how many are NOT contained + { + std::vector< LLVector3 > uncontained_directions; + std::vector< LLSphere >::iterator sphere_itr; + for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr) + { + LLVector3 direction = sphere_itr->getCenter() - bounding_sphere.getCenter(); + direction.normalize(); + + sphere_itr->setCenter( sphere_itr->getCenter() + expansion * direction ); + if (! bounding_sphere.contains( *sphere_itr ) ) + { + uncontained_directions.push_back(direction); + } + } + ensure("when moving spheres out there should be at least two uncontained spheres", + uncontained_directions.size() > 1); + + /* TODO -- when the bounding sphere algorithm is improved we can open up this test + * at the moment it occasionally fails when the sphere collection is tight and small + * (2 meters or less) + if (2 == uncontained_directions.size() ) + { + // if there were only two uncontained spheres then + // the two directions should be nearly opposite + F32 dir_dot = uncontained_directions[0] * uncontained_directions[1]; + ensure("two uncontained spheres should lie opposite the bounding center", dir_dot < -0.95f); + } + */ + } + + // compute the new bounding sphere + bounding_sphere = LLSphere::getBoundingSphere(sphere_list); + + // increase the size of all spheres a little bit + // and count how many are NOT contained + { + std::vector< LLVector3 > uncontained_directions; + std::vector< LLSphere >::iterator sphere_itr; + for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr) + { + LLVector3 direction = sphere_itr->getCenter() - bounding_sphere.getCenter(); + direction.normalize(); + + sphere_itr->setRadius( sphere_itr->getRadius() + expansion ); + if (! bounding_sphere.contains( *sphere_itr ) ) + { + uncontained_directions.push_back(direction); + } + } + ensure("when boosting sphere radii there should be at least two uncontained spheres", + uncontained_directions.size() > 1); + + /* TODO -- when the bounding sphere algorithm is improved we can open up this test + * at the moment it occasionally fails when the sphere collection is tight and small + * (2 meters or less) + if (2 == uncontained_directions.size() ) + { + // if there were only two uncontained spheres then + // the two directions should be nearly opposite + F32 dir_dot = uncontained_directions[0] * uncontained_directions[1]; + ensure("two uncontained spheres should lie opposite the bounding center", dir_dot < -0.95f); + } + */ + } + } + } } namespace tut { - F32 SMALL_RADIUS = 1.0f; - F32 MEDIUM_RADIUS = 5.0f; - F32 LARGE_RADIUS = 10.0f; - - struct line_data - { - }; - typedef test_group<line_data> line_test; - typedef line_test::object line_object; - tut::line_test tline("LLLine"); - - template<> template<> - void line_object::test<1>() - { - // this is a test for LLLine::intersects(point) which returns true - // if the line passes within some tolerance of point - - // these tests will have some floating point error, - // so we need to specify how much error is ok - F32 allowable_relative_error = 0.00001f; - S32 number_of_tests = 100; - for (S32 test = 0; test < number_of_tests; ++test) - { - // generate some random point to be on the line - LLVector3 point_on_line( ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f); - point_on_line.normalize(); - point_on_line *= ll_frand(LARGE_RADIUS); - - // generate some random point to "intersect" - LLVector3 random_direction ( ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f); - random_direction.normalize(); - - LLVector3 random_offset( ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f); - random_offset.normalize(); - random_offset *= ll_frand(SMALL_RADIUS); - - LLVector3 point = point_on_line + MEDIUM_RADIUS * random_direction - + random_offset; - - // compute the axis of approach (a unit vector between the points) - LLVector3 axis_of_approach = point - point_on_line; - axis_of_approach.normalize(); - - // compute the direction of the the first line (perp to axis_of_approach) - LLVector3 first_dir( ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f); - first_dir.normalize(); - F32 dot = first_dir * axis_of_approach; - first_dir -= dot * axis_of_approach; // subtract component parallel to axis - first_dir.normalize(); - - // construct the line - LLVector3 another_point_on_line = point_on_line + ll_frand(LARGE_RADIUS) * first_dir; - LLLine line(another_point_on_line, point_on_line); - - // test that the intersection point is within MEDIUM_RADIUS + SMALL_RADIUS - F32 test_radius = MEDIUM_RADIUS + SMALL_RADIUS; - test_radius += (LARGE_RADIUS * allowable_relative_error); - ensure("line should pass near intersection point", line.intersects(point, test_radius)); - - test_radius = allowable_relative_error * (point - point_on_line).length(); - ensure("line should intersect point used to define it", line.intersects(point_on_line, test_radius)); - } - } - - template<> template<> - void line_object::test<2>() - { + F32 SMALL_RADIUS = 1.0f; + F32 MEDIUM_RADIUS = 5.0f; + F32 LARGE_RADIUS = 10.0f; + + struct line_data + { + }; + typedef test_group<line_data> line_test; + typedef line_test::object line_object; + tut::line_test tline("LLLine"); + + template<> template<> + void line_object::test<1>() + { + // this is a test for LLLine::intersects(point) which returns true + // if the line passes within some tolerance of point + + // these tests will have some floating point error, + // so we need to specify how much error is ok + F32 allowable_relative_error = 0.00001f; + S32 number_of_tests = 100; + for (S32 test = 0; test < number_of_tests; ++test) + { + // generate some random point to be on the line + LLVector3 point_on_line( ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f); + point_on_line.normalize(); + point_on_line *= ll_frand(LARGE_RADIUS); + + // generate some random point to "intersect" + LLVector3 random_direction ( ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f); + random_direction.normalize(); + + LLVector3 random_offset( ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f); + random_offset.normalize(); + random_offset *= ll_frand(SMALL_RADIUS); + + LLVector3 point = point_on_line + MEDIUM_RADIUS * random_direction + + random_offset; + + // compute the axis of approach (a unit vector between the points) + LLVector3 axis_of_approach = point - point_on_line; + axis_of_approach.normalize(); + + // compute the direction of the the first line (perp to axis_of_approach) + LLVector3 first_dir( ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f); + first_dir.normalize(); + F32 dot = first_dir * axis_of_approach; + first_dir -= dot * axis_of_approach; // subtract component parallel to axis + first_dir.normalize(); + + // construct the line + LLVector3 another_point_on_line = point_on_line + ll_frand(LARGE_RADIUS) * first_dir; + LLLine line(another_point_on_line, point_on_line); + + // test that the intersection point is within MEDIUM_RADIUS + SMALL_RADIUS + F32 test_radius = MEDIUM_RADIUS + SMALL_RADIUS; + test_radius += (LARGE_RADIUS * allowable_relative_error); + ensure("line should pass near intersection point", line.intersects(point, test_radius)); + + test_radius = allowable_relative_error * (point - point_on_line).length(); + ensure("line should intersect point used to define it", line.intersects(point_on_line, test_radius)); + } + } + + template<> template<> + void line_object::test<2>() + { /* These tests fail intermittently on all platforms - see DEV-16600 Commenting this out until dev has time to investigate. - - // this is a test for LLLine::nearestApproach(LLLIne) method - // which computes the point on a line nearest another line - - // these tests will have some floating point error, - // so we need to specify how much error is ok - // TODO -- make nearestApproach() algorithm more accurate so - // we can tighten the allowable_error. Most tests are tighter - // than one milimeter, however when doing randomized testing - // you can walk into inaccurate cases. - F32 allowable_relative_error = 0.001f; - S32 number_of_tests = 100; - for (S32 test = 0; test < number_of_tests; ++test) - { - // generate two points to be our known nearest approaches - LLVector3 some_point( ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f); - some_point.normalize(); - some_point *= ll_frand(LARGE_RADIUS); - - LLVector3 another_point( ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f); - another_point.normalize(); - another_point *= ll_frand(LARGE_RADIUS); - - // compute the axis of approach (a unit vector between the points) - LLVector3 axis_of_approach = another_point - some_point; - axis_of_approach.normalize(); - - // compute the direction of the the first line (perp to axis_of_approach) - LLVector3 first_dir( ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f); - F32 dot = first_dir * axis_of_approach; - first_dir -= dot * axis_of_approach; // subtract component parallel to axis - first_dir.normalize(); // normalize - - // compute the direction of the the second line - LLVector3 second_dir( ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f); - dot = second_dir * axis_of_approach; - second_dir -= dot * axis_of_approach; - second_dir.normalize(); - - // make sure the lines aren't too parallel, - dot = fabsf(first_dir * second_dir); - if (dot > 0.99f) - { - // skip this test, we're not interested in testing - // the intractible cases - continue; - } - - // construct the lines - LLVector3 first_point = some_point + ll_frand(LARGE_RADIUS) * first_dir; - LLLine first_line(first_point, some_point); - - LLVector3 second_point = another_point + ll_frand(LARGE_RADIUS) * second_dir; - LLLine second_line(second_point, another_point); - - // compute the points of nearest approach - LLVector3 some_computed_point = first_line.nearestApproach(second_line); - LLVector3 another_computed_point = second_line.nearestApproach(first_line); - - // compute the error - F32 first_error = (some_point - some_computed_point).length(); - F32 scale = llmax((some_point - another_point).length(), some_point.length()); - scale = llmax(scale, another_point.length()); - scale = llmax(scale, 1.f); - F32 first_relative_error = first_error / scale; - - F32 second_error = (another_point - another_computed_point).length(); - F32 second_relative_error = second_error / scale; - - //if (first_relative_error > allowable_relative_error) - //{ - // std::cout << "first_error = " << first_error - // << " first_relative_error = " << first_relative_error - // << " scale = " << scale - // << " dir_dot = " << (first_dir * second_dir) - // << std::endl; - //} - //if (second_relative_error > allowable_relative_error) - //{ - // std::cout << "second_error = " << second_error - // << " second_relative_error = " << second_relative_error - // << " scale = " << scale - // << " dist = " << (some_point - another_point).length() - // << " dir_dot = " << (first_dir * second_dir) - // << std::endl; - //} - - // test that the errors are small - - ensure("first line should accurately compute its closest approach", - first_relative_error <= allowable_relative_error); - ensure("second line should accurately compute its closest approach", - second_relative_error <= allowable_relative_error); - } + + // this is a test for LLLine::nearestApproach(LLLIne) method + // which computes the point on a line nearest another line + + // these tests will have some floating point error, + // so we need to specify how much error is ok + // TODO -- make nearestApproach() algorithm more accurate so + // we can tighten the allowable_error. Most tests are tighter + // than one milimeter, however when doing randomized testing + // you can walk into inaccurate cases. + F32 allowable_relative_error = 0.001f; + S32 number_of_tests = 100; + for (S32 test = 0; test < number_of_tests; ++test) + { + // generate two points to be our known nearest approaches + LLVector3 some_point( ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f); + some_point.normalize(); + some_point *= ll_frand(LARGE_RADIUS); + + LLVector3 another_point( ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f); + another_point.normalize(); + another_point *= ll_frand(LARGE_RADIUS); + + // compute the axis of approach (a unit vector between the points) + LLVector3 axis_of_approach = another_point - some_point; + axis_of_approach.normalize(); + + // compute the direction of the the first line (perp to axis_of_approach) + LLVector3 first_dir( ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f); + F32 dot = first_dir * axis_of_approach; + first_dir -= dot * axis_of_approach; // subtract component parallel to axis + first_dir.normalize(); // normalize + + // compute the direction of the the second line + LLVector3 second_dir( ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f); + dot = second_dir * axis_of_approach; + second_dir -= dot * axis_of_approach; + second_dir.normalize(); + + // make sure the lines aren't too parallel, + dot = fabsf(first_dir * second_dir); + if (dot > 0.99f) + { + // skip this test, we're not interested in testing + // the intractible cases + continue; + } + + // construct the lines + LLVector3 first_point = some_point + ll_frand(LARGE_RADIUS) * first_dir; + LLLine first_line(first_point, some_point); + + LLVector3 second_point = another_point + ll_frand(LARGE_RADIUS) * second_dir; + LLLine second_line(second_point, another_point); + + // compute the points of nearest approach + LLVector3 some_computed_point = first_line.nearestApproach(second_line); + LLVector3 another_computed_point = second_line.nearestApproach(first_line); + + // compute the error + F32 first_error = (some_point - some_computed_point).length(); + F32 scale = llmax((some_point - another_point).length(), some_point.length()); + scale = llmax(scale, another_point.length()); + scale = llmax(scale, 1.f); + F32 first_relative_error = first_error / scale; + + F32 second_error = (another_point - another_computed_point).length(); + F32 second_relative_error = second_error / scale; + + //if (first_relative_error > allowable_relative_error) + //{ + // std::cout << "first_error = " << first_error + // << " first_relative_error = " << first_relative_error + // << " scale = " << scale + // << " dir_dot = " << (first_dir * second_dir) + // << std::endl; + //} + //if (second_relative_error > allowable_relative_error) + //{ + // std::cout << "second_error = " << second_error + // << " second_relative_error = " << second_relative_error + // << " scale = " << scale + // << " dist = " << (some_point - another_point).length() + // << " dir_dot = " << (first_dir * second_dir) + // << std::endl; + //} + + // test that the errors are small + + ensure("first line should accurately compute its closest approach", + first_relative_error <= allowable_relative_error); + ensure("second line should accurately compute its closest approach", + second_relative_error <= allowable_relative_error); + } */ - } - - F32 ALMOST_PARALLEL = 0.99f; - template<> template<> - void line_object::test<3>() - { - // this is a test for LLLine::getIntersectionBetweenTwoPlanes() method - - // first some known tests - LLLine xy_plane(LLVector3(0.f, 0.f, 2.f), LLVector3(0.f, 0.f, 3.f)); - LLLine yz_plane(LLVector3(2.f, 0.f, 0.f), LLVector3(3.f, 0.f, 0.f)); - LLLine zx_plane(LLVector3(0.f, 2.f, 0.f), LLVector3(0.f, 3.f, 0.f)); - - LLLine x_line; - LLLine y_line; - LLLine z_line; - - bool x_success = LLLine::getIntersectionBetweenTwoPlanes(x_line, xy_plane, zx_plane); - bool y_success = LLLine::getIntersectionBetweenTwoPlanes(y_line, yz_plane, xy_plane); - bool z_success = LLLine::getIntersectionBetweenTwoPlanes(z_line, zx_plane, yz_plane); - - ensure("xy and zx planes should intersect", x_success); - ensure("yz and xy planes should intersect", y_success); - ensure("zx and yz planes should intersect", z_success); - - LLVector3 direction = x_line.getDirection(); - ensure("x_line should be parallel to x_axis", fabs(direction.mV[VX]) == 1.f - && 0.f == direction.mV[VY] - && 0.f == direction.mV[VZ] ); - direction = y_line.getDirection(); - ensure("y_line should be parallel to y_axis", 0.f == direction.mV[VX] - && fabs(direction.mV[VY]) == 1.f - && 0.f == direction.mV[VZ] ); - direction = z_line.getDirection(); - ensure("z_line should be parallel to z_axis", 0.f == direction.mV[VX] - && 0.f == direction.mV[VY] - && fabs(direction.mV[VZ]) == 1.f ); - - // next some random tests - F32 allowable_relative_error = 0.0001f; - S32 number_of_tests = 20; - for (S32 test = 0; test < number_of_tests; ++test) - { - // generate the known line - LLVector3 some_point( ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f); - some_point.normalize(); - some_point *= ll_frand(LARGE_RADIUS); - LLVector3 another_point( ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f); - another_point.normalize(); - another_point *= ll_frand(LARGE_RADIUS); - LLLine known_intersection(some_point, another_point); - - // compute a plane that intersect the line - LLVector3 point_on_plane( ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f); - point_on_plane.normalize(); - point_on_plane *= ll_frand(LARGE_RADIUS); - LLVector3 plane_normal = (point_on_plane - some_point) % known_intersection.getDirection(); - plane_normal.normalize(); - LLLine first_plane(point_on_plane, point_on_plane + plane_normal); - - // compute a different plane that intersect the line - LLVector3 point_on_different_plane( ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f, - ll_frand(2.f) - 1.f); - point_on_different_plane.normalize(); - point_on_different_plane *= ll_frand(LARGE_RADIUS); - LLVector3 different_plane_normal = (point_on_different_plane - another_point) % known_intersection.getDirection(); - different_plane_normal.normalize(); - LLLine second_plane(point_on_different_plane, point_on_different_plane + different_plane_normal); - - if (fabs(plane_normal * different_plane_normal) > ALMOST_PARALLEL) - { - // the two planes are approximately parallel, so we won't test this case - continue; - } - - LLLine measured_intersection; - bool success = LLLine::getIntersectionBetweenTwoPlanes( - measured_intersection, - first_plane, - second_plane); - - ensure("plane intersection should succeed", success); - - F32 dot = fabs(known_intersection.getDirection() * measured_intersection.getDirection()); - ensure("measured intersection should be parallel to known intersection", - dot > ALMOST_PARALLEL); - - ensure("measured intersection should pass near known point", - measured_intersection.intersects(some_point, LARGE_RADIUS * allowable_relative_error)); - } - } + } + + F32 ALMOST_PARALLEL = 0.99f; + template<> template<> + void line_object::test<3>() + { + // this is a test for LLLine::getIntersectionBetweenTwoPlanes() method + + // first some known tests + LLLine xy_plane(LLVector3(0.f, 0.f, 2.f), LLVector3(0.f, 0.f, 3.f)); + LLLine yz_plane(LLVector3(2.f, 0.f, 0.f), LLVector3(3.f, 0.f, 0.f)); + LLLine zx_plane(LLVector3(0.f, 2.f, 0.f), LLVector3(0.f, 3.f, 0.f)); + + LLLine x_line; + LLLine y_line; + LLLine z_line; + + bool x_success = LLLine::getIntersectionBetweenTwoPlanes(x_line, xy_plane, zx_plane); + bool y_success = LLLine::getIntersectionBetweenTwoPlanes(y_line, yz_plane, xy_plane); + bool z_success = LLLine::getIntersectionBetweenTwoPlanes(z_line, zx_plane, yz_plane); + + ensure("xy and zx planes should intersect", x_success); + ensure("yz and xy planes should intersect", y_success); + ensure("zx and yz planes should intersect", z_success); + + LLVector3 direction = x_line.getDirection(); + ensure("x_line should be parallel to x_axis", fabs(direction.mV[VX]) == 1.f + && 0.f == direction.mV[VY] + && 0.f == direction.mV[VZ] ); + direction = y_line.getDirection(); + ensure("y_line should be parallel to y_axis", 0.f == direction.mV[VX] + && fabs(direction.mV[VY]) == 1.f + && 0.f == direction.mV[VZ] ); + direction = z_line.getDirection(); + ensure("z_line should be parallel to z_axis", 0.f == direction.mV[VX] + && 0.f == direction.mV[VY] + && fabs(direction.mV[VZ]) == 1.f ); + + // next some random tests + F32 allowable_relative_error = 0.0001f; + S32 number_of_tests = 20; + for (S32 test = 0; test < number_of_tests; ++test) + { + // generate the known line + LLVector3 some_point( ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f); + some_point.normalize(); + some_point *= ll_frand(LARGE_RADIUS); + LLVector3 another_point( ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f); + another_point.normalize(); + another_point *= ll_frand(LARGE_RADIUS); + LLLine known_intersection(some_point, another_point); + + // compute a plane that intersect the line + LLVector3 point_on_plane( ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f); + point_on_plane.normalize(); + point_on_plane *= ll_frand(LARGE_RADIUS); + LLVector3 plane_normal = (point_on_plane - some_point) % known_intersection.getDirection(); + plane_normal.normalize(); + LLLine first_plane(point_on_plane, point_on_plane + plane_normal); + + // compute a different plane that intersect the line + LLVector3 point_on_different_plane( ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f, + ll_frand(2.f) - 1.f); + point_on_different_plane.normalize(); + point_on_different_plane *= ll_frand(LARGE_RADIUS); + LLVector3 different_plane_normal = (point_on_different_plane - another_point) % known_intersection.getDirection(); + different_plane_normal.normalize(); + LLLine second_plane(point_on_different_plane, point_on_different_plane + different_plane_normal); + + if (fabs(plane_normal * different_plane_normal) > ALMOST_PARALLEL) + { + // the two planes are approximately parallel, so we won't test this case + continue; + } + + LLLine measured_intersection; + bool success = LLLine::getIntersectionBetweenTwoPlanes( + measured_intersection, + first_plane, + second_plane); + + ensure("plane intersection should succeed", success); + + F32 dot = fabs(known_intersection.getDirection() * measured_intersection.getDirection()); + ensure("measured intersection should be parallel to known intersection", + dot > ALMOST_PARALLEL); + + ensure("measured intersection should pass near known point", + measured_intersection.intersects(some_point, LARGE_RADIUS * allowable_relative_error)); + } + } } diff --git a/indra/llmath/tests/v2math_test.cpp b/indra/llmath/tests/v2math_test.cpp index 06e1292941..860e3ef672 100644 --- a/indra/llmath/tests/v2math_test.cpp +++ b/indra/llmath/tests/v2math_test.cpp @@ -7,442 +7,442 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #include "linden_common.h" -#include "../test/lltut.h" +#include "../test/lltut.h" #include "../v2math.h" namespace tut { - struct v2math_data - { - }; - typedef test_group<v2math_data> v2math_test; - typedef v2math_test::object v2math_object; - tut::v2math_test v2math_testcase("v2math_h"); - - template<> template<> - void v2math_object::test<1>() - { - LLVector2 vec2; - ensure("LLVector2:Fail to initialize ", (0.f == vec2.mV[VX] && 0.f == vec2.mV[VY])); - - F32 x =2.0f, y = 3.2f ; - LLVector2 vec3(x,y); - ensure("LLVector2(F32 x, F32 y):Fail to initialize ", (x == vec3.mV[VX]) && (y == vec3.mV[VY])); - - const F32 vec[2] = {3.2f, 4.5f}; - LLVector2 vec4(vec); - ensure("LLVector2(const F32 *vec):Fail to initialize ", (vec[0] == vec4.mV[VX]) && (vec[1] == vec4.mV[VY])); - - vec4.clearVec(); - ensure("clearVec():Fail to clean the values ", (0.f == vec4.mV[VX] && 0.f == vec4.mV[VY])); - - vec3.zeroVec(); - ensure("zeroVec():Fail to fill the zero ", (0.f == vec3.mV[VX] && 0.f == vec3.mV[VY])); - } - - template<> template<> - void v2math_object::test<2>() - { - F32 x = 123.356f, y = 2387.453f; - LLVector2 vec2,vec3; - vec2.setVec(x, y); - ensure("1:setVec: Fail ", (x == vec2.mV[VX]) && (y == vec2.mV[VY])); - - vec3.setVec(vec2); - ensure("2:setVec: Fail " ,(vec2 == vec3)); - - vec3.zeroVec(); - const F32 vec[2] = {3.24653f, 457653.4f}; - vec3.setVec(vec); - ensure("3:setVec: Fail ", (vec[0] == vec3.mV[VX]) && (vec[1] == vec3.mV[VY])); - } - - template<> template<> - void v2math_object::test<3>() - { - F32 x = 2.2345f, y = 3.5678f ; - LLVector2 vec2(x,y); - ensure("magVecSquared:Fail ", is_approx_equal(vec2.magVecSquared(), (x*x + y*y))); - ensure("magVec:Fail ", is_approx_equal(vec2.magVec(), (F32) sqrt(x*x + y*y))); - } - - template<> template<> - void v2math_object::test<4>() - { - F32 x =-2.0f, y = -3.0f ; - LLVector2 vec2(x,y); - ensure_equals("abs():Fail", vec2.abs(), true); - ensure("abs() x", is_approx_equal(vec2.mV[VX], 2.f)); - ensure("abs() y", is_approx_equal(vec2.mV[VY], 3.f)); - - ensure("isNull():Fail ", false == vec2.isNull()); //Returns true if vector has a _very_small_ length - - x =.00000001f, y = .000001001f; - vec2.setVec(x, y); - ensure("isNull(): Fail ", true == vec2.isNull()); - } - - template<> template<> - void v2math_object::test<5>() - { - F32 x =1.f, y = 2.f; - LLVector2 vec2(x, y), vec3; - vec3 = vec3.scaleVec(vec2); - ensure("scaleVec: Fail ", vec3.mV[VX] == 0. && vec3.mV[VY] == 0.); - ensure("isExactlyZero(): Fail", true == vec3.isExactlyZero()); - - vec3.setVec(2.f, 1.f); - vec3 = vec3.scaleVec(vec2); - ensure("scaleVec: Fail ", (2.f == vec3.mV[VX]) && (2.f == vec3.mV[VY])); - ensure("isExactlyZero():Fail", false == vec3.isExactlyZero()); - } - - template<> template<> - void v2math_object::test<6>() - { - F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f; - F32 val1, val2; - LLVector2 vec2(x1, y1), vec3(x2, y2), vec4; - vec4 = vec2 + vec3 ; - val1 = x1+x2; - val2 = y1+y2; - ensure("1:operator+ failed",(val1 == vec4.mV[VX]) && ((val2 == vec4.mV[VY]))); - - vec2.clearVec(); - vec3.clearVec(); - x1 = -.235f, y1 = -24.32f, x2 = -2.3f, y2 = 1.f; - vec2.setVec(x1, y1); - vec3.setVec(x2, y2); - vec4 = vec2 + vec3; - val1 = x1+x2; - val2 = y1+y2; - ensure("2:operator+ failed",(val1 == vec4.mV[VX]) && ((val2 == vec4.mV[VY]))); - } - - template<> template<> - void v2math_object::test<7>() - { - F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f; - F32 val1, val2; - LLVector2 vec2(x1, y1), vec3(x2, y2), vec4; - vec4 = vec2 - vec3 ; - val1 = x1-x2; - val2 = y1-y2; - ensure("1:operator- failed",(val1 == vec4.mV[VX]) && ((val2 == vec4.mV[VY]))); - - vec2.clearVec(); - vec3.clearVec(); - vec4.clearVec(); - x1 = -.235f, y1 = -24.32f, x2 = -2.3f, y2 = 1.f; - vec2.setVec(x1, y1); - vec3.setVec(x2, y2); - vec4 = vec2 - vec3; - val1 = x1-x2; - val2 = y1-y2; - ensure("2:operator- failed",(val1 == vec4.mV[VX]) && ((val2 == vec4.mV[VY]))); - } - - template<> template<> - void v2math_object::test<8>() - { - F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f; - F32 val1, val2; - LLVector2 vec2(x1, y1), vec3(x2, y2); - val1 = vec2 * vec3; - val2 = x1*x2 + y1*y2; - ensure("1:operator* failed",(val1 == val2)); - - vec3.clearVec(); - F32 mulVal = 4.332f; - vec3 = vec2 * mulVal; - val1 = x1*mulVal; - val2 = y1*mulVal; - ensure("2:operator* failed",(val1 == vec3.mV[VX]) && (val2 == vec3.mV[VY])); - - vec3.clearVec(); - vec3 = mulVal * vec2; - ensure("3:operator* failed",(val1 == vec3.mV[VX]) && (val2 == vec3.mV[VY])); - } - - template<> template<> - void v2math_object::test<9>() - { - F32 x1 =1.f, y1 = 2.f, div = 3.2f; - F32 val1, val2; - LLVector2 vec2(x1, y1), vec3; - vec3 = vec2 / div; - val1 = x1 / div; - val2 = y1 / div; - ensure("1:operator/ failed", is_approx_equal(val1, vec3.mV[VX]) && is_approx_equal(val2, vec3.mV[VY])); - - vec3.clearVec(); - x1 = -.235f, y1 = -24.32f, div = -2.2f; - vec2.setVec(x1, y1); - vec3 = vec2 / div; - val1 = x1 / div; - val2 = y1 / div; - ensure("2:operator/ failed", is_approx_equal(val1, vec3.mV[VX]) && is_approx_equal(val2, vec3.mV[VY])); - } - - template<> template<> - void v2math_object::test<10>() - { - F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f; - F32 val1, val2; - LLVector2 vec2(x1, y1), vec3(x2, y2), vec4; - vec4 = vec2 % vec3; - val1 = x1*y2 - x2*y1; - val2 = y1*x2 - y2*x1; - ensure("1:operator% failed",(val1 == vec4.mV[VX]) && (val2 == vec4.mV[VY])); - - vec2.clearVec(); - vec3.clearVec(); - vec4.clearVec(); - x1 = -.235f, y1 = -24.32f, x2 = -2.3f, y2 = 1.f; - vec2.setVec(x1, y1); - vec3.setVec(x2, y2); - vec4 = vec2 % vec3; - val1 = x1*y2 - x2*y1; - val2 = y1*x2 - y2*x1; - ensure("2:operator% failed",(val1 == vec4.mV[VX]) && (val2 == vec4.mV[VY])); - } - template<> template<> - void v2math_object::test<11>() - { - F32 x1 =1.f, y1 = 2.f; - LLVector2 vec2(x1, y1), vec3(x1, y1); - ensure("1:operator== failed",(vec2 == vec3)); - - vec2.clearVec(); - vec3.clearVec(); - x1 = -.235f, y1 = -24.32f; - vec2.setVec(x1, y1); - vec3.setVec(vec2); - ensure("2:operator== failed",(vec2 == vec3)); - } - - template<> template<> - void v2math_object::test<12>() - { - F32 x1 = 1.f, y1 = 2.f,x2 = 2.332f, y2 = -1.23f; - LLVector2 vec2(x1, y1), vec3(x2, y2); - ensure("1:operator!= failed",(vec2 != vec3)); - - vec2.clearVec(); - vec3.clearVec(); - vec2.setVec(x1, y1); - vec3.setVec(vec2); - ensure("2:operator!= failed", (false == (vec2 != vec3))); - } - template<> template<> - void v2math_object::test<13>() - { - F32 x1 = 1.f, y1 = 2.f,x2 = 2.332f, y2 = -1.23f; - F32 val1, val2; - LLVector2 vec2(x1, y1), vec3(x2, y2); - vec2 +=vec3; - val1 = x1+x2; - val2 = y1+y2; - ensure("1:operator+= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY])); - - vec2.setVec(x1, y1); - vec2 -=vec3; - val1 = x1-x2; - val2 = y1-y2; - ensure("2:operator-= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY])); - - vec2.clearVec(); - vec3.clearVec(); - x1 = -21.000466f, y1 = 2.98382f,x2 = 0.332f, y2 = -01.23f; - vec2.setVec(x1, y1); - vec3.setVec(x2, y2); - vec2 +=vec3; - val1 = x1+x2; - val2 = y1+y2; - ensure("3:operator+= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY])); - - vec2.setVec(x1, y1); - vec2 -=vec3; - val1 = x1-x2; - val2 = y1-y2; - ensure("4:operator-= failed", is_approx_equal(val1, vec2.mV[VX]) && is_approx_equal(val2, vec2.mV[VY])); - } - - template<> template<> - void v2math_object::test<14>() - { - F32 x1 =1.f, y1 = 2.f; - F32 val1, val2, mulVal = 4.332f; - LLVector2 vec2(x1, y1); - vec2 /=mulVal; - val1 = x1 / mulVal; - val2 = y1 / mulVal; - ensure("1:operator/= failed", is_approx_equal(val1, vec2.mV[VX]) && is_approx_equal(val2, vec2.mV[VY])); - - vec2.clearVec(); - x1 = .213f, y1 = -2.34f, mulVal = -.23f; - vec2.setVec(x1, y1); - vec2 /=mulVal; - val1 = x1 / mulVal; - val2 = y1 / mulVal; - ensure("2:operator/= failed", is_approx_equal(val1, vec2.mV[VX]) && is_approx_equal(val2, vec2.mV[VY])); - } - - template<> template<> - void v2math_object::test<15>() - { - F32 x1 =1.f, y1 = 2.f; - F32 val1, val2, mulVal = 4.332f; - LLVector2 vec2(x1, y1); - vec2 *=mulVal; - val1 = x1*mulVal; - val2 = y1*mulVal; - ensure("1:operator*= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY])); - - vec2.clearVec(); - x1 = .213f, y1 = -2.34f, mulVal = -.23f; - vec2.setVec(x1, y1); - vec2 *=mulVal; - val1 = x1*mulVal; - val2 = y1*mulVal; - ensure("2:operator*= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY])); - } - - template<> template<> - void v2math_object::test<16>() - { - F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f; - F32 val1, val2; - LLVector2 vec2(x1, y1), vec3(x2, y2); - vec2 %= vec3; - val1 = x1*y2 - x2*y1; - val2 = y1*x2 - y2*x1; - ensure("1:operator%= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY])); - } - - template<> template<> - void v2math_object::test<17>() - { - F32 x1 =1.f, y1 = 2.f; - LLVector2 vec2(x1, y1),vec3; - vec3 = -vec2; - ensure("1:operator- failed",(-vec3 == vec2)); - } - - template<> template<> - void v2math_object::test<18>() - { - F32 x1 =1.f, y1 = 2.f; - std::ostringstream stream1, stream2; - LLVector2 vec2(x1, y1),vec3; - stream1 << vec2; - vec3.setVec(x1, y1); - stream2 << vec3; - ensure("1:operator << failed",(stream1.str() == stream2.str())); - } - - template<> template<> - void v2math_object::test<19>() - { - F32 x1 =1.0f, y1 = 2.0f, x2 = -.32f, y2 = .2234f; - LLVector2 vec2(x1, y1),vec3(x2, y2); - ensure("1:operator < failed",(vec3 < vec2)); - - x1 = 1.0f, y1 = 2.0f, x2 = 1.0f, y2 = 3.2234f; - vec2.setVec(x1, y1); - vec3.setVec(x2, y2); - ensure("2:operator < failed", (false == (vec3 < vec2))); - } - - template<> template<> - void v2math_object::test<20>() - { - F32 x1 =1.0f, y1 = 2.0f; - LLVector2 vec2(x1, y1); - ensure("1:operator [] failed",( x1 == vec2[0])); - ensure("2:operator [] failed",( y1 == vec2[1])); - - vec2.clearVec(); - x1 = 23.0f, y1 = -.2361f; - vec2.setVec(x1, y1); - F32 ref1 = vec2[0]; - ensure("3:operator [] failed", ( ref1 == x1)); - F32 ref2 = vec2[1]; - ensure("4:operator [] failed", ( ref2 == y1)); - } - - template<> template<> - void v2math_object::test<21>() - { - F32 x1 =1.f, y1 = 2.f, x2 = -.32f, y2 = .2234f; - F32 val1, val2; - LLVector2 vec2(x1, y1),vec3(x2, y2); - val1 = dist_vec_squared2D(vec2, vec3); - val2 = (x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2); - ensure_equals("dist_vec_squared2D values are not equal",val2, val1); - - val1 = dist_vec_squared(vec2, vec3); - ensure_equals("dist_vec_squared values are not equal",val2, val1); - - val1 = dist_vec(vec2, vec3); - val2 = (F32) sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2)); - ensure_equals("dist_vec values are not equal",val2, val1); - } - - template<> template<> - void v2math_object::test<22>() - { - F32 x1 =1.f, y1 = 2.f, x2 = -.32f, y2 = .2234f,fVal = .0121f; - F32 val1, val2; - LLVector2 vec2(x1, y1),vec3(x2, y2); - LLVector2 vec4 = lerp(vec2, vec3, fVal); - val1 = x1 + (x2 - x1) * fVal; - val2 = y1 + (y2 - y1) * fVal; - ensure("lerp values are not equal", ((val1 == vec4.mV[VX]) && (val2 == vec4.mV[VY]))); - } - - template<> template<> - void v2math_object::test<23>() - { - F32 x1 =1.f, y1 = 2.f; - F32 val1, val2; - LLVector2 vec2(x1, y1); - - F32 vecMag = vec2.normVec(); - F32 mag = (F32) sqrt(x1*x1 + y1*y1); - - F32 oomag = 1.f / mag; - val1 = x1 * oomag; - val2 = y1 * oomag; - - ensure("normVec failed", is_approx_equal(val1, vec2.mV[VX]) && is_approx_equal(val2, vec2.mV[VY]) && is_approx_equal(vecMag, mag)); - - x1 =.00000001f, y1 = 0.f; - - vec2.setVec(x1, y1); - vecMag = vec2.normVec(); - ensure("normVec failed should be 0.", 0. == vec2.mV[VX] && 0. == vec2.mV[VY] && vecMag == 0.); - } + struct v2math_data + { + }; + typedef test_group<v2math_data> v2math_test; + typedef v2math_test::object v2math_object; + tut::v2math_test v2math_testcase("v2math_h"); + + template<> template<> + void v2math_object::test<1>() + { + LLVector2 vec2; + ensure("LLVector2:Fail to initialize ", (0.f == vec2.mV[VX] && 0.f == vec2.mV[VY])); + + F32 x =2.0f, y = 3.2f ; + LLVector2 vec3(x,y); + ensure("LLVector2(F32 x, F32 y):Fail to initialize ", (x == vec3.mV[VX]) && (y == vec3.mV[VY])); + + const F32 vec[2] = {3.2f, 4.5f}; + LLVector2 vec4(vec); + ensure("LLVector2(const F32 *vec):Fail to initialize ", (vec[0] == vec4.mV[VX]) && (vec[1] == vec4.mV[VY])); + + vec4.clearVec(); + ensure("clearVec():Fail to clean the values ", (0.f == vec4.mV[VX] && 0.f == vec4.mV[VY])); + + vec3.zeroVec(); + ensure("zeroVec():Fail to fill the zero ", (0.f == vec3.mV[VX] && 0.f == vec3.mV[VY])); + } + + template<> template<> + void v2math_object::test<2>() + { + F32 x = 123.356f, y = 2387.453f; + LLVector2 vec2,vec3; + vec2.setVec(x, y); + ensure("1:setVec: Fail ", (x == vec2.mV[VX]) && (y == vec2.mV[VY])); + + vec3.setVec(vec2); + ensure("2:setVec: Fail " ,(vec2 == vec3)); + + vec3.zeroVec(); + const F32 vec[2] = {3.24653f, 457653.4f}; + vec3.setVec(vec); + ensure("3:setVec: Fail ", (vec[0] == vec3.mV[VX]) && (vec[1] == vec3.mV[VY])); + } + + template<> template<> + void v2math_object::test<3>() + { + F32 x = 2.2345f, y = 3.5678f ; + LLVector2 vec2(x,y); + ensure("magVecSquared:Fail ", is_approx_equal(vec2.magVecSquared(), (x*x + y*y))); + ensure("magVec:Fail ", is_approx_equal(vec2.magVec(), (F32) sqrt(x*x + y*y))); + } + + template<> template<> + void v2math_object::test<4>() + { + F32 x =-2.0f, y = -3.0f ; + LLVector2 vec2(x,y); + ensure_equals("abs():Fail", vec2.abs(), true); + ensure("abs() x", is_approx_equal(vec2.mV[VX], 2.f)); + ensure("abs() y", is_approx_equal(vec2.mV[VY], 3.f)); + + ensure("isNull():Fail ", false == vec2.isNull()); //Returns true if vector has a _very_small_ length + + x =.00000001f, y = .000001001f; + vec2.setVec(x, y); + ensure("isNull(): Fail ", true == vec2.isNull()); + } + + template<> template<> + void v2math_object::test<5>() + { + F32 x =1.f, y = 2.f; + LLVector2 vec2(x, y), vec3; + vec3 = vec3.scaleVec(vec2); + ensure("scaleVec: Fail ", vec3.mV[VX] == 0. && vec3.mV[VY] == 0.); + ensure("isExactlyZero(): Fail", true == vec3.isExactlyZero()); + + vec3.setVec(2.f, 1.f); + vec3 = vec3.scaleVec(vec2); + ensure("scaleVec: Fail ", (2.f == vec3.mV[VX]) && (2.f == vec3.mV[VY])); + ensure("isExactlyZero():Fail", false == vec3.isExactlyZero()); + } + + template<> template<> + void v2math_object::test<6>() + { + F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f; + F32 val1, val2; + LLVector2 vec2(x1, y1), vec3(x2, y2), vec4; + vec4 = vec2 + vec3 ; + val1 = x1+x2; + val2 = y1+y2; + ensure("1:operator+ failed",(val1 == vec4.mV[VX]) && ((val2 == vec4.mV[VY]))); + + vec2.clearVec(); + vec3.clearVec(); + x1 = -.235f, y1 = -24.32f, x2 = -2.3f, y2 = 1.f; + vec2.setVec(x1, y1); + vec3.setVec(x2, y2); + vec4 = vec2 + vec3; + val1 = x1+x2; + val2 = y1+y2; + ensure("2:operator+ failed",(val1 == vec4.mV[VX]) && ((val2 == vec4.mV[VY]))); + } + + template<> template<> + void v2math_object::test<7>() + { + F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f; + F32 val1, val2; + LLVector2 vec2(x1, y1), vec3(x2, y2), vec4; + vec4 = vec2 - vec3 ; + val1 = x1-x2; + val2 = y1-y2; + ensure("1:operator- failed",(val1 == vec4.mV[VX]) && ((val2 == vec4.mV[VY]))); + + vec2.clearVec(); + vec3.clearVec(); + vec4.clearVec(); + x1 = -.235f, y1 = -24.32f, x2 = -2.3f, y2 = 1.f; + vec2.setVec(x1, y1); + vec3.setVec(x2, y2); + vec4 = vec2 - vec3; + val1 = x1-x2; + val2 = y1-y2; + ensure("2:operator- failed",(val1 == vec4.mV[VX]) && ((val2 == vec4.mV[VY]))); + } + + template<> template<> + void v2math_object::test<8>() + { + F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f; + F32 val1, val2; + LLVector2 vec2(x1, y1), vec3(x2, y2); + val1 = vec2 * vec3; + val2 = x1*x2 + y1*y2; + ensure("1:operator* failed",(val1 == val2)); + + vec3.clearVec(); + F32 mulVal = 4.332f; + vec3 = vec2 * mulVal; + val1 = x1*mulVal; + val2 = y1*mulVal; + ensure("2:operator* failed",(val1 == vec3.mV[VX]) && (val2 == vec3.mV[VY])); + + vec3.clearVec(); + vec3 = mulVal * vec2; + ensure("3:operator* failed",(val1 == vec3.mV[VX]) && (val2 == vec3.mV[VY])); + } + + template<> template<> + void v2math_object::test<9>() + { + F32 x1 =1.f, y1 = 2.f, div = 3.2f; + F32 val1, val2; + LLVector2 vec2(x1, y1), vec3; + vec3 = vec2 / div; + val1 = x1 / div; + val2 = y1 / div; + ensure("1:operator/ failed", is_approx_equal(val1, vec3.mV[VX]) && is_approx_equal(val2, vec3.mV[VY])); + + vec3.clearVec(); + x1 = -.235f, y1 = -24.32f, div = -2.2f; + vec2.setVec(x1, y1); + vec3 = vec2 / div; + val1 = x1 / div; + val2 = y1 / div; + ensure("2:operator/ failed", is_approx_equal(val1, vec3.mV[VX]) && is_approx_equal(val2, vec3.mV[VY])); + } + + template<> template<> + void v2math_object::test<10>() + { + F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f; + F32 val1, val2; + LLVector2 vec2(x1, y1), vec3(x2, y2), vec4; + vec4 = vec2 % vec3; + val1 = x1*y2 - x2*y1; + val2 = y1*x2 - y2*x1; + ensure("1:operator% failed",(val1 == vec4.mV[VX]) && (val2 == vec4.mV[VY])); + + vec2.clearVec(); + vec3.clearVec(); + vec4.clearVec(); + x1 = -.235f, y1 = -24.32f, x2 = -2.3f, y2 = 1.f; + vec2.setVec(x1, y1); + vec3.setVec(x2, y2); + vec4 = vec2 % vec3; + val1 = x1*y2 - x2*y1; + val2 = y1*x2 - y2*x1; + ensure("2:operator% failed",(val1 == vec4.mV[VX]) && (val2 == vec4.mV[VY])); + } + template<> template<> + void v2math_object::test<11>() + { + F32 x1 =1.f, y1 = 2.f; + LLVector2 vec2(x1, y1), vec3(x1, y1); + ensure("1:operator== failed",(vec2 == vec3)); + + vec2.clearVec(); + vec3.clearVec(); + x1 = -.235f, y1 = -24.32f; + vec2.setVec(x1, y1); + vec3.setVec(vec2); + ensure("2:operator== failed",(vec2 == vec3)); + } + + template<> template<> + void v2math_object::test<12>() + { + F32 x1 = 1.f, y1 = 2.f,x2 = 2.332f, y2 = -1.23f; + LLVector2 vec2(x1, y1), vec3(x2, y2); + ensure("1:operator!= failed",(vec2 != vec3)); + + vec2.clearVec(); + vec3.clearVec(); + vec2.setVec(x1, y1); + vec3.setVec(vec2); + ensure("2:operator!= failed", (false == (vec2 != vec3))); + } + template<> template<> + void v2math_object::test<13>() + { + F32 x1 = 1.f, y1 = 2.f,x2 = 2.332f, y2 = -1.23f; + F32 val1, val2; + LLVector2 vec2(x1, y1), vec3(x2, y2); + vec2 +=vec3; + val1 = x1+x2; + val2 = y1+y2; + ensure("1:operator+= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY])); + + vec2.setVec(x1, y1); + vec2 -=vec3; + val1 = x1-x2; + val2 = y1-y2; + ensure("2:operator-= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY])); + + vec2.clearVec(); + vec3.clearVec(); + x1 = -21.000466f, y1 = 2.98382f,x2 = 0.332f, y2 = -01.23f; + vec2.setVec(x1, y1); + vec3.setVec(x2, y2); + vec2 +=vec3; + val1 = x1+x2; + val2 = y1+y2; + ensure("3:operator+= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY])); + + vec2.setVec(x1, y1); + vec2 -=vec3; + val1 = x1-x2; + val2 = y1-y2; + ensure("4:operator-= failed", is_approx_equal(val1, vec2.mV[VX]) && is_approx_equal(val2, vec2.mV[VY])); + } + + template<> template<> + void v2math_object::test<14>() + { + F32 x1 =1.f, y1 = 2.f; + F32 val1, val2, mulVal = 4.332f; + LLVector2 vec2(x1, y1); + vec2 /=mulVal; + val1 = x1 / mulVal; + val2 = y1 / mulVal; + ensure("1:operator/= failed", is_approx_equal(val1, vec2.mV[VX]) && is_approx_equal(val2, vec2.mV[VY])); + + vec2.clearVec(); + x1 = .213f, y1 = -2.34f, mulVal = -.23f; + vec2.setVec(x1, y1); + vec2 /=mulVal; + val1 = x1 / mulVal; + val2 = y1 / mulVal; + ensure("2:operator/= failed", is_approx_equal(val1, vec2.mV[VX]) && is_approx_equal(val2, vec2.mV[VY])); + } + + template<> template<> + void v2math_object::test<15>() + { + F32 x1 =1.f, y1 = 2.f; + F32 val1, val2, mulVal = 4.332f; + LLVector2 vec2(x1, y1); + vec2 *=mulVal; + val1 = x1*mulVal; + val2 = y1*mulVal; + ensure("1:operator*= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY])); + + vec2.clearVec(); + x1 = .213f, y1 = -2.34f, mulVal = -.23f; + vec2.setVec(x1, y1); + vec2 *=mulVal; + val1 = x1*mulVal; + val2 = y1*mulVal; + ensure("2:operator*= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY])); + } + + template<> template<> + void v2math_object::test<16>() + { + F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f; + F32 val1, val2; + LLVector2 vec2(x1, y1), vec3(x2, y2); + vec2 %= vec3; + val1 = x1*y2 - x2*y1; + val2 = y1*x2 - y2*x1; + ensure("1:operator%= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY])); + } + + template<> template<> + void v2math_object::test<17>() + { + F32 x1 =1.f, y1 = 2.f; + LLVector2 vec2(x1, y1),vec3; + vec3 = -vec2; + ensure("1:operator- failed",(-vec3 == vec2)); + } + + template<> template<> + void v2math_object::test<18>() + { + F32 x1 =1.f, y1 = 2.f; + std::ostringstream stream1, stream2; + LLVector2 vec2(x1, y1),vec3; + stream1 << vec2; + vec3.setVec(x1, y1); + stream2 << vec3; + ensure("1:operator << failed",(stream1.str() == stream2.str())); + } + + template<> template<> + void v2math_object::test<19>() + { + F32 x1 =1.0f, y1 = 2.0f, x2 = -.32f, y2 = .2234f; + LLVector2 vec2(x1, y1),vec3(x2, y2); + ensure("1:operator < failed",(vec3 < vec2)); + + x1 = 1.0f, y1 = 2.0f, x2 = 1.0f, y2 = 3.2234f; + vec2.setVec(x1, y1); + vec3.setVec(x2, y2); + ensure("2:operator < failed", (false == (vec3 < vec2))); + } + + template<> template<> + void v2math_object::test<20>() + { + F32 x1 =1.0f, y1 = 2.0f; + LLVector2 vec2(x1, y1); + ensure("1:operator [] failed",( x1 == vec2[0])); + ensure("2:operator [] failed",( y1 == vec2[1])); + + vec2.clearVec(); + x1 = 23.0f, y1 = -.2361f; + vec2.setVec(x1, y1); + F32 ref1 = vec2[0]; + ensure("3:operator [] failed", ( ref1 == x1)); + F32 ref2 = vec2[1]; + ensure("4:operator [] failed", ( ref2 == y1)); + } + + template<> template<> + void v2math_object::test<21>() + { + F32 x1 =1.f, y1 = 2.f, x2 = -.32f, y2 = .2234f; + F32 val1, val2; + LLVector2 vec2(x1, y1),vec3(x2, y2); + val1 = dist_vec_squared2D(vec2, vec3); + val2 = (x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2); + ensure_equals("dist_vec_squared2D values are not equal",val2, val1); + + val1 = dist_vec_squared(vec2, vec3); + ensure_equals("dist_vec_squared values are not equal",val2, val1); + + val1 = dist_vec(vec2, vec3); + val2 = (F32) sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2)); + ensure_equals("dist_vec values are not equal",val2, val1); + } + + template<> template<> + void v2math_object::test<22>() + { + F32 x1 =1.f, y1 = 2.f, x2 = -.32f, y2 = .2234f,fVal = .0121f; + F32 val1, val2; + LLVector2 vec2(x1, y1),vec3(x2, y2); + LLVector2 vec4 = lerp(vec2, vec3, fVal); + val1 = x1 + (x2 - x1) * fVal; + val2 = y1 + (y2 - y1) * fVal; + ensure("lerp values are not equal", ((val1 == vec4.mV[VX]) && (val2 == vec4.mV[VY]))); + } + + template<> template<> + void v2math_object::test<23>() + { + F32 x1 =1.f, y1 = 2.f; + F32 val1, val2; + LLVector2 vec2(x1, y1); + + F32 vecMag = vec2.normVec(); + F32 mag = (F32) sqrt(x1*x1 + y1*y1); + + F32 oomag = 1.f / mag; + val1 = x1 * oomag; + val2 = y1 * oomag; + + ensure("normVec failed", is_approx_equal(val1, vec2.mV[VX]) && is_approx_equal(val2, vec2.mV[VY]) && is_approx_equal(vecMag, mag)); + + x1 =.00000001f, y1 = 0.f; + + vec2.setVec(x1, y1); + vecMag = vec2.normVec(); + ensure("normVec failed should be 0.", 0. == vec2.mV[VX] && 0. == vec2.mV[VY] && vecMag == 0.); + } } diff --git a/indra/llmath/tests/v3color_test.cpp b/indra/llmath/tests/v3color_test.cpp index 0fb52394a5..8897d48365 100644 --- a/indra/llmath/tests/v3color_test.cpp +++ b/indra/llmath/tests/v3color_test.cpp @@ -7,21 +7,21 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -34,276 +34,276 @@ namespace tut { - struct v3color_data - { - }; - typedef test_group<v3color_data> v3color_test; - typedef v3color_test::object v3color_object; - tut::v3color_test v3color_testcase("v3color_h"); + struct v3color_data + { + }; + typedef test_group<v3color_data> v3color_test; + typedef v3color_test::object v3color_object; + tut::v3color_test v3color_testcase("v3color_h"); + + template<> template<> + void v3color_object::test<1>() + { + LLColor3 llcolor3; + ensure("1:LLColor3:Fail to default-initialize ", (0.0f == llcolor3.mV[0]) && (0.0f == llcolor3.mV[1]) && (0.0f == llcolor3.mV[2])); + F32 r = 2.0f, g = 3.2f, b = 1.f; + F32 v1,v2,v3; + LLColor3 llcolor3a(r,g,b); + ensure("2:LLColor3:Fail to initialize " ,(2.0f == llcolor3a.mV[0]) && (3.2f == llcolor3a.mV[1]) && (1.f == llcolor3a.mV[2])); + + const F32 vec[3] = {2.0f, 3.2f,1.f}; + LLColor3 llcolor3b(vec); + ensure("3:LLColor3:Fail to initialize " ,(2.0f == llcolor3b.mV[0]) && (3.2f == llcolor3b.mV[1]) && (1.f == llcolor3b.mV[2])); + const char* str = "561122"; + LLColor3 llcolor3c(str); + v1 = (F32)86.0f/255.0f; // 0x56 = 86 + v2 = (F32)17.0f/255.0f; // 0x11 = 17 + v3 = (F32)34.0f/255.f; // 0x22 = 34 + ensure("4:LLColor3:Fail to initialize " , is_approx_equal(v1, llcolor3c.mV[0]) && is_approx_equal(v2, llcolor3c.mV[1]) && is_approx_equal(v3, llcolor3c.mV[2])); + } + + template<> template<> + void v3color_object::test<2>() + { + LLColor3 llcolor3; + llcolor3.setToBlack(); + ensure("setToBlack:Fail to set black ", ((llcolor3.mV[0] == 0.f) && (llcolor3.mV[1] == 0.f) && (llcolor3.mV[2] == 0.f))); + llcolor3.setToWhite(); + ensure("setToWhite:Fail to set white ", ((llcolor3.mV[0] == 1.f) && (llcolor3.mV[1] == 1.f) && (llcolor3.mV[2] == 1.f))); + } + + template<> template<> + void v3color_object::test<3>() + { + F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f; + LLColor3 llcolor3, llcolor3a; + llcolor3.setVec(r,g,b); + ensure("1:setVec(r,g,b) Fail ",((r == llcolor3.mV[0]) && (g == llcolor3.mV[1]) && (b == llcolor3.mV[2]))); + llcolor3a.setVec(llcolor3); + ensure_equals("2:setVec(LLColor3) Fail ", llcolor3,llcolor3a); + F32 vec[3] = {1.2324f, 2.45634f, .234563f}; + llcolor3.setToBlack(); + llcolor3.setVec(vec); + ensure("3:setVec(F32*) Fail ",((vec[0] == llcolor3.mV[0]) && (vec[1] == llcolor3.mV[1]) && (vec[2] == llcolor3.mV[2]))); + } - template<> template<> - void v3color_object::test<1>() - { - LLColor3 llcolor3; - ensure("1:LLColor3:Fail to default-initialize ", (0.0f == llcolor3.mV[0]) && (0.0f == llcolor3.mV[1]) && (0.0f == llcolor3.mV[2])); - F32 r = 2.0f, g = 3.2f, b = 1.f; - F32 v1,v2,v3; - LLColor3 llcolor3a(r,g,b); - ensure("2:LLColor3:Fail to initialize " ,(2.0f == llcolor3a.mV[0]) && (3.2f == llcolor3a.mV[1]) && (1.f == llcolor3a.mV[2])); - - const F32 vec[3] = {2.0f, 3.2f,1.f}; - LLColor3 llcolor3b(vec); - ensure("3:LLColor3:Fail to initialize " ,(2.0f == llcolor3b.mV[0]) && (3.2f == llcolor3b.mV[1]) && (1.f == llcolor3b.mV[2])); - const char* str = "561122"; - LLColor3 llcolor3c(str); - v1 = (F32)86.0f/255.0f; // 0x56 = 86 - v2 = (F32)17.0f/255.0f; // 0x11 = 17 - v3 = (F32)34.0f/255.f; // 0x22 = 34 - ensure("4:LLColor3:Fail to initialize " , is_approx_equal(v1, llcolor3c.mV[0]) && is_approx_equal(v2, llcolor3c.mV[1]) && is_approx_equal(v3, llcolor3c.mV[2])); - } + template<> template<> + void v3color_object::test<4>() + { + F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f; + LLColor3 llcolor3(r,g,b); + ensure("magVecSquared:Fail ", is_approx_equal(llcolor3.magVecSquared(), (r*r + g*g + b*b))); + ensure("magVec:Fail ", is_approx_equal(llcolor3.magVec(), (F32) sqrt(r*r + g*g + b*b))); + } - template<> template<> - void v3color_object::test<2>() - { - LLColor3 llcolor3; - llcolor3.setToBlack(); - ensure("setToBlack:Fail to set black ", ((llcolor3.mV[0] == 0.f) && (llcolor3.mV[1] == 0.f) && (llcolor3.mV[2] == 0.f))); - llcolor3.setToWhite(); - ensure("setToWhite:Fail to set white ", ((llcolor3.mV[0] == 1.f) && (llcolor3.mV[1] == 1.f) && (llcolor3.mV[2] == 1.f))); - } + template<> template<> + void v3color_object::test<5>() + { + F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f; + F32 val1, val2,val3; + LLColor3 llcolor3(r,g,b); + F32 vecMag = llcolor3.normVec(); + F32 mag = (F32) sqrt(r*r + g*g + b*b); + F32 oomag = 1.f / mag; + val1 = r * oomag; + val2 = g * oomag; + val3 = b * oomag; + ensure("1:normVec failed ", (is_approx_equal(val1, llcolor3.mV[0]) && is_approx_equal(val2, llcolor3.mV[1]) && is_approx_equal(val3, llcolor3.mV[2]) && is_approx_equal(vecMag, mag))); + r = .000000000f, g = 0.f, b = 0.0f; + llcolor3.setVec(r,g,b); + vecMag = llcolor3.normVec(); + ensure("2:normVec failed should be 0. ", (0. == llcolor3.mV[0] && 0. == llcolor3.mV[1] && 0. == llcolor3.mV[2] && vecMag == 0.)); + } - template<> template<> - void v3color_object::test<3>() - { - F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f; - LLColor3 llcolor3, llcolor3a; - llcolor3.setVec(r,g,b); - ensure("1:setVec(r,g,b) Fail ",((r == llcolor3.mV[0]) && (g == llcolor3.mV[1]) && (b == llcolor3.mV[2]))); - llcolor3a.setVec(llcolor3); - ensure_equals("2:setVec(LLColor3) Fail ", llcolor3,llcolor3a); - F32 vec[3] = {1.2324f, 2.45634f, .234563f}; - llcolor3.setToBlack(); - llcolor3.setVec(vec); - ensure("3:setVec(F32*) Fail ",((vec[0] == llcolor3.mV[0]) && (vec[1] == llcolor3.mV[1]) && (vec[2] == llcolor3.mV[2]))); - } + template<> template<> + void v3color_object::test<6>() + { + F32 r = 2.3436212f, g = -1231.f, b = .7849321232f; + std::ostringstream stream1, stream2; + LLColor3 llcolor3(r,g,b),llcolor3a; + stream1 << llcolor3; + llcolor3a.setVec(r,g,b); + stream2 << llcolor3a; + ensure("operator << failed ", (stream1.str() == stream2.str())); + } - template<> template<> - void v3color_object::test<4>() - { - F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f; - LLColor3 llcolor3(r,g,b); - ensure("magVecSquared:Fail ", is_approx_equal(llcolor3.magVecSquared(), (r*r + g*g + b*b))); - ensure("magVec:Fail ", is_approx_equal(llcolor3.magVec(), (F32) sqrt(r*r + g*g + b*b))); - } + template<> template<> + void v3color_object::test<7>() + { + F32 r = 2.3436212f, g = -1231.f, b = .7849321232f; + LLColor3 llcolor3(r,g,b),llcolor3a; + llcolor3a = llcolor3; + ensure("operator == failed ", (llcolor3a == llcolor3)); + } - template<> template<> - void v3color_object::test<5>() - { - F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f; - F32 val1, val2,val3; - LLColor3 llcolor3(r,g,b); - F32 vecMag = llcolor3.normVec(); - F32 mag = (F32) sqrt(r*r + g*g + b*b); - F32 oomag = 1.f / mag; - val1 = r * oomag; - val2 = g * oomag; - val3 = b * oomag; - ensure("1:normVec failed ", (is_approx_equal(val1, llcolor3.mV[0]) && is_approx_equal(val2, llcolor3.mV[1]) && is_approx_equal(val3, llcolor3.mV[2]) && is_approx_equal(vecMag, mag))); - r = .000000000f, g = 0.f, b = 0.0f; - llcolor3.setVec(r,g,b); - vecMag = llcolor3.normVec(); - ensure("2:normVec failed should be 0. ", (0. == llcolor3.mV[0] && 0. == llcolor3.mV[1] && 0. == llcolor3.mV[2] && vecMag == 0.)); - } + template<> template<> + void v3color_object::test<8>() + { + F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f; + LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2),llcolor3b; + llcolor3b = llcolor3 + llcolor3a ; + ensure("1:operator+ failed",is_approx_equal(r1+r2 ,llcolor3b.mV[0]) && is_approx_equal(g1+g2,llcolor3b.mV[1])&& is_approx_equal(b1+b2,llcolor3b.mV[2])); + r1 = -.235f, g1 = -24.32f, b1 = 2.13f, r2 = -2.3f, g2 = 1.f, b2 = 34.21f; + llcolor3.setVec(r1,g1,b1); + llcolor3a.setVec(r2,g2,b2); + llcolor3b = llcolor3 + llcolor3a; + ensure("2:operator+ failed",is_approx_equal(r1+r2 ,llcolor3b.mV[0]) && is_approx_equal(g1+g2,llcolor3b.mV[1])&& is_approx_equal(b1+b2,llcolor3b.mV[2])); + } - template<> template<> - void v3color_object::test<6>() - { - F32 r = 2.3436212f, g = -1231.f, b = .7849321232f; - std::ostringstream stream1, stream2; - LLColor3 llcolor3(r,g,b),llcolor3a; - stream1 << llcolor3; - llcolor3a.setVec(r,g,b); - stream2 << llcolor3a; - ensure("operator << failed ", (stream1.str() == stream2.str())); - } - - template<> template<> - void v3color_object::test<7>() - { - F32 r = 2.3436212f, g = -1231.f, b = .7849321232f; - LLColor3 llcolor3(r,g,b),llcolor3a; - llcolor3a = llcolor3; - ensure("operator == failed ", (llcolor3a == llcolor3)); - } + template<> template<> + void v3color_object::test<9>() + { + F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f; + LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2),llcolor3b; + llcolor3b = llcolor3 - llcolor3a ; + ensure("1:operator- failed",is_approx_equal(r1-r2 ,llcolor3b.mV[0]) && is_approx_equal(g1-g2,llcolor3b.mV[1])&& is_approx_equal(b1-b2,llcolor3b.mV[2])); + r1 = -.235f, g1 = -24.32f, b1 = 2.13f, r2 = -2.3f, g2 = 1.f, b2 = 34.21f; + llcolor3.setVec(r1,g1,b1); + llcolor3a.setVec(r2,g2,b2); + llcolor3b = llcolor3 - llcolor3a; + ensure("2:operator- failed",is_approx_equal(r1-r2 ,llcolor3b.mV[0]) && is_approx_equal(g1-g2,llcolor3b.mV[1])&& is_approx_equal(b1-b2,llcolor3b.mV[2])); + } - template<> template<> - void v3color_object::test<8>() - { - F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f; - LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2),llcolor3b; - llcolor3b = llcolor3 + llcolor3a ; - ensure("1:operator+ failed",is_approx_equal(r1+r2 ,llcolor3b.mV[0]) && is_approx_equal(g1+g2,llcolor3b.mV[1])&& is_approx_equal(b1+b2,llcolor3b.mV[2])); - r1 = -.235f, g1 = -24.32f, b1 = 2.13f, r2 = -2.3f, g2 = 1.f, b2 = 34.21f; - llcolor3.setVec(r1,g1,b1); - llcolor3a.setVec(r2,g2,b2); - llcolor3b = llcolor3 + llcolor3a; - ensure("2:operator+ failed",is_approx_equal(r1+r2 ,llcolor3b.mV[0]) && is_approx_equal(g1+g2,llcolor3b.mV[1])&& is_approx_equal(b1+b2,llcolor3b.mV[2])); - } + template<> template<> + void v3color_object::test<10>() + { + F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f; + LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2),llcolor3b; + llcolor3b = llcolor3 * llcolor3a; + ensure("1:operator* failed",is_approx_equal(r1*r2 ,llcolor3b.mV[0]) && is_approx_equal(g1*g2,llcolor3b.mV[1])&& is_approx_equal(b1*b2,llcolor3b.mV[2])); + llcolor3a.setToBlack(); + F32 mulVal = 4.332f; + llcolor3a = llcolor3 * mulVal; + ensure("2:operator* failed",is_approx_equal(r1*mulVal ,llcolor3a.mV[0]) && is_approx_equal(g1*mulVal,llcolor3a.mV[1])&& is_approx_equal(b1*mulVal,llcolor3a.mV[2])); + llcolor3a.setToBlack(); + llcolor3a = mulVal * llcolor3; + ensure("3:operator* failed",is_approx_equal(r1*mulVal ,llcolor3a.mV[0]) && is_approx_equal(g1*mulVal,llcolor3a.mV[1])&& is_approx_equal(b1*mulVal,llcolor3a.mV[2])); + } - template<> template<> - void v3color_object::test<9>() - { - F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f; - LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2),llcolor3b; - llcolor3b = llcolor3 - llcolor3a ; - ensure("1:operator- failed",is_approx_equal(r1-r2 ,llcolor3b.mV[0]) && is_approx_equal(g1-g2,llcolor3b.mV[1])&& is_approx_equal(b1-b2,llcolor3b.mV[2])); - r1 = -.235f, g1 = -24.32f, b1 = 2.13f, r2 = -2.3f, g2 = 1.f, b2 = 34.21f; - llcolor3.setVec(r1,g1,b1); - llcolor3a.setVec(r2,g2,b2); - llcolor3b = llcolor3 - llcolor3a; - ensure("2:operator- failed",is_approx_equal(r1-r2 ,llcolor3b.mV[0]) && is_approx_equal(g1-g2,llcolor3b.mV[1])&& is_approx_equal(b1-b2,llcolor3b.mV[2])); - } + template<> template<> + void v3color_object::test<11>() + { + F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f; + LLColor3 llcolor3(r,g,b),llcolor3a; + llcolor3a = -llcolor3; + ensure("operator- failed ", (-llcolor3a == llcolor3)); + } - template<> template<> - void v3color_object::test<10>() - { - F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f; - LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2),llcolor3b; - llcolor3b = llcolor3 * llcolor3a; - ensure("1:operator* failed",is_approx_equal(r1*r2 ,llcolor3b.mV[0]) && is_approx_equal(g1*g2,llcolor3b.mV[1])&& is_approx_equal(b1*b2,llcolor3b.mV[2])); - llcolor3a.setToBlack(); - F32 mulVal = 4.332f; - llcolor3a = llcolor3 * mulVal; - ensure("2:operator* failed",is_approx_equal(r1*mulVal ,llcolor3a.mV[0]) && is_approx_equal(g1*mulVal,llcolor3a.mV[1])&& is_approx_equal(b1*mulVal,llcolor3a.mV[2])); - llcolor3a.setToBlack(); - llcolor3a = mulVal * llcolor3; - ensure("3:operator* failed",is_approx_equal(r1*mulVal ,llcolor3a.mV[0]) && is_approx_equal(g1*mulVal,llcolor3a.mV[1])&& is_approx_equal(b1*mulVal,llcolor3a.mV[2])); - } + template<> template<> + void v3color_object::test<12>() + { + F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f; + LLColor3 llcolor3(r,g,b),llcolor3a(r,g,b); + ensure_equals("1:operator== failed",llcolor3a,llcolor3); + r = 13.3436212f, g = -11.f, b = .7849321232f; + llcolor3.setVec(r,g,b); + llcolor3a.setVec(r,g,b); + ensure_equals("2:operator== failed",llcolor3a,llcolor3); + } - template<> template<> - void v3color_object::test<11>() - { - F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f; - LLColor3 llcolor3(r,g,b),llcolor3a; - llcolor3a = -llcolor3; - ensure("operator- failed ", (-llcolor3a == llcolor3)); - } + template<> template<> + void v3color_object::test<13>() + { + F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f; + LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2); + ensure("1:operator!= failed",(llcolor3 != llcolor3a)); + llcolor3.setToBlack(); + llcolor3a.setVec(llcolor3); + ensure("2:operator!= failed", ( false == (llcolor3a != llcolor3))); + } - template<> template<> - void v3color_object::test<12>() - { - F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f; - LLColor3 llcolor3(r,g,b),llcolor3a(r,g,b); - ensure_equals("1:operator== failed",llcolor3a,llcolor3); - r = 13.3436212f, g = -11.f, b = .7849321232f; - llcolor3.setVec(r,g,b); - llcolor3a.setVec(r,g,b); - ensure_equals("2:operator== failed",llcolor3a,llcolor3); - } + template<> template<> + void v3color_object::test<14>() + { + F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f; + LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2); + llcolor3a += llcolor3; + ensure("1:operator+= failed",is_approx_equal(r1+r2 ,llcolor3a.mV[0]) && is_approx_equal(g1+g2,llcolor3a.mV[1])&& is_approx_equal(b1+b2,llcolor3a.mV[2])); + llcolor3.setVec(r1,g1,b1); + llcolor3a.setVec(r2,g2,b2); + llcolor3a += llcolor3; + ensure("2:operator+= failed",is_approx_equal(r1+r2 ,llcolor3a.mV[0]) && is_approx_equal(g1+g2,llcolor3a.mV[1])&& is_approx_equal(b1+b2,llcolor3a.mV[2])); + } - template<> template<> - void v3color_object::test<13>() - { - F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f; - LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2); - ensure("1:operator!= failed",(llcolor3 != llcolor3a)); - llcolor3.setToBlack(); - llcolor3a.setVec(llcolor3); - ensure("2:operator!= failed", ( false == (llcolor3a != llcolor3))); - } + template<> template<> + void v3color_object::test<15>() + { + F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f; + LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2); + llcolor3a -= llcolor3; + ensure("1:operator-= failed", is_approx_equal(r2-r1, llcolor3a.mV[0])); + ensure("2:operator-= failed", is_approx_equal(g2-g1, llcolor3a.mV[1])); + ensure("3:operator-= failed", is_approx_equal(b2-b1, llcolor3a.mV[2])); + llcolor3.setVec(r1,g1,b1); + llcolor3a.setVec(r2,g2,b2); + llcolor3a -= llcolor3; + ensure("4:operator-= failed", is_approx_equal(r2-r1, llcolor3a.mV[0])); + ensure("5:operator-= failed", is_approx_equal(g2-g1, llcolor3a.mV[1])); + ensure("6:operator-= failed", is_approx_equal(b2-b1, llcolor3a.mV[2])); + } - template<> template<> - void v3color_object::test<14>() - { - F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f; - LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2); - llcolor3a += llcolor3; - ensure("1:operator+= failed",is_approx_equal(r1+r2 ,llcolor3a.mV[0]) && is_approx_equal(g1+g2,llcolor3a.mV[1])&& is_approx_equal(b1+b2,llcolor3a.mV[2])); - llcolor3.setVec(r1,g1,b1); - llcolor3a.setVec(r2,g2,b2); - llcolor3a += llcolor3; - ensure("2:operator+= failed",is_approx_equal(r1+r2 ,llcolor3a.mV[0]) && is_approx_equal(g1+g2,llcolor3a.mV[1])&& is_approx_equal(b1+b2,llcolor3a.mV[2])); - } + template<> template<> + void v3color_object::test<16>() + { + F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f; + LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2); + llcolor3a *= llcolor3; + ensure("1:operator*= failed",is_approx_equal(r1*r2 ,llcolor3a.mV[0]) && is_approx_equal(g1*g2,llcolor3a.mV[1])&& is_approx_equal(b1*b2,llcolor3a.mV[2])); + F32 mulVal = 4.332f; + llcolor3 *=mulVal; + ensure("2:operator*= failed",is_approx_equal(r1*mulVal ,llcolor3.mV[0]) && is_approx_equal(g1*mulVal,llcolor3.mV[1])&& is_approx_equal(b1*mulVal,llcolor3.mV[2])); + } - template<> template<> - void v3color_object::test<15>() - { - F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f; - LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2); - llcolor3a -= llcolor3; - ensure("1:operator-= failed", is_approx_equal(r2-r1, llcolor3a.mV[0])); - ensure("2:operator-= failed", is_approx_equal(g2-g1, llcolor3a.mV[1])); - ensure("3:operator-= failed", is_approx_equal(b2-b1, llcolor3a.mV[2])); - llcolor3.setVec(r1,g1,b1); - llcolor3a.setVec(r2,g2,b2); - llcolor3a -= llcolor3; - ensure("4:operator-= failed", is_approx_equal(r2-r1, llcolor3a.mV[0])); - ensure("5:operator-= failed", is_approx_equal(g2-g1, llcolor3a.mV[1])); - ensure("6:operator-= failed", is_approx_equal(b2-b1, llcolor3a.mV[2])); - } - - template<> template<> - void v3color_object::test<16>() - { - F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f; - LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2); - llcolor3a *= llcolor3; - ensure("1:operator*= failed",is_approx_equal(r1*r2 ,llcolor3a.mV[0]) && is_approx_equal(g1*g2,llcolor3a.mV[1])&& is_approx_equal(b1*b2,llcolor3a.mV[2])); - F32 mulVal = 4.332f; - llcolor3 *=mulVal; - ensure("2:operator*= failed",is_approx_equal(r1*mulVal ,llcolor3.mV[0]) && is_approx_equal(g1*mulVal,llcolor3.mV[1])&& is_approx_equal(b1*mulVal,llcolor3.mV[2])); - } + template<> template<> + void v3color_object::test<17>() + { + F32 r = 2.3436212f, g = -1231.f, b = .7849321232f; + LLColor3 llcolor3(r,g,b); + llcolor3.clamp(); + ensure("1:clamp:Fail to clamp " ,(1.0f == llcolor3.mV[0]) && (0.f == llcolor3.mV[1]) && (b == llcolor3.mV[2])); + r = -2.3436212f, g = -1231.f, b = 67.7849321232f; + llcolor3.setVec(r,g,b); + llcolor3.clamp(); + ensure("2:clamp:Fail to clamp " ,(0.f == llcolor3.mV[0]) && (0.f == llcolor3.mV[1]) && (1.f == llcolor3.mV[2])); + } - template<> template<> - void v3color_object::test<17>() - { - F32 r = 2.3436212f, g = -1231.f, b = .7849321232f; - LLColor3 llcolor3(r,g,b); - llcolor3.clamp(); - ensure("1:clamp:Fail to clamp " ,(1.0f == llcolor3.mV[0]) && (0.f == llcolor3.mV[1]) && (b == llcolor3.mV[2])); - r = -2.3436212f, g = -1231.f, b = 67.7849321232f; - llcolor3.setVec(r,g,b); - llcolor3.clamp(); - ensure("2:clamp:Fail to clamp " ,(0.f == llcolor3.mV[0]) && (0.f == llcolor3.mV[1]) && (1.f == llcolor3.mV[2])); - } + template<> template<> + void v3color_object::test<18>() + { + F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f; + F32 val = 2.3f,val1,val2,val3; + LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2); + val1 = r1 + (r2 - r1)* val; + val2 = g1 + (g2 - g1)* val; + val3 = b1 + (b2 - b1)* val; + LLColor3 llcolor3b = lerp(llcolor3,llcolor3a,val); + ensure("lerp failed ", ((val1 ==llcolor3b.mV[0])&& (val2 ==llcolor3b.mV[1]) && (val3 ==llcolor3b.mV[2]))); + } - template<> template<> - void v3color_object::test<18>() - { - F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f; - F32 val = 2.3f,val1,val2,val3; - LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2); - val1 = r1 + (r2 - r1)* val; - val2 = g1 + (g2 - g1)* val; - val3 = b1 + (b2 - b1)* val; - LLColor3 llcolor3b = lerp(llcolor3,llcolor3a,val); - ensure("lerp failed ", ((val1 ==llcolor3b.mV[0])&& (val2 ==llcolor3b.mV[1]) && (val3 ==llcolor3b.mV[2]))); - } + template<> template<> + void v3color_object::test<19>() + { + F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f; + LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2); + F32 val = distVec(llcolor3,llcolor3a); + ensure("distVec failed ", is_approx_equal((F32) sqrt((r1-r2)*(r1-r2) + (g1-g2)*(g1-g2) + (b1-b2)*(b1-b2)) ,val)); - template<> template<> - void v3color_object::test<19>() - { - F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f; - LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2); - F32 val = distVec(llcolor3,llcolor3a); - ensure("distVec failed ", is_approx_equal((F32) sqrt((r1-r2)*(r1-r2) + (g1-g2)*(g1-g2) + (b1-b2)*(b1-b2)) ,val)); - - F32 val1 = distVec_squared(llcolor3,llcolor3a); - ensure("distVec_squared failed ", is_approx_equal(((r1-r2)*(r1-r2) + (g1-g2)*(g1-g2) + (b1-b2)*(b1-b2)) ,val1)); - } + F32 val1 = distVec_squared(llcolor3,llcolor3a); + ensure("distVec_squared failed ", is_approx_equal(((r1-r2)*(r1-r2) + (g1-g2)*(g1-g2) + (b1-b2)*(b1-b2)) ,val1)); + } - template<> template<> - void v3color_object::test<20>() - { - F32 r1 = 1.02223f, g1 = 22222.212f, b1 = 122222.00002f; - LLColor3 llcolor31(r1,g1,b1); + template<> template<> + void v3color_object::test<20>() + { + F32 r1 = 1.02223f, g1 = 22222.212f, b1 = 122222.00002f; + LLColor3 llcolor31(r1,g1,b1); - LLSD sd = llcolor31.getValue(); - LLColor3 llcolor32; - llcolor32.setValue(sd); - ensure_equals("LLColor3::setValue/getValue failed", llcolor31, llcolor32); + LLSD sd = llcolor31.getValue(); + LLColor3 llcolor32; + llcolor32.setValue(sd); + ensure_equals("LLColor3::setValue/getValue failed", llcolor31, llcolor32); - LLColor3 llcolor33(sd); - ensure_equals("LLColor3(LLSD) failed", llcolor31, llcolor33); - } + LLColor3 llcolor33(sd); + ensure_equals("LLColor3(LLSD) failed", llcolor31, llcolor33); + } } diff --git a/indra/llmath/tests/v3dmath_test.cpp b/indra/llmath/tests/v3dmath_test.cpp index 0c8c01a77a..db08419012 100644 --- a/indra/llmath/tests/v3dmath_test.cpp +++ b/indra/llmath/tests/v3dmath_test.cpp @@ -7,25 +7,25 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ - + #include "linden_common.h" #include "llsd.h" #include "../test/lltut.h" @@ -38,494 +38,494 @@ namespace tut { - struct v3dmath_data - { - }; - typedef test_group<v3dmath_data> v3dmath_test; - typedef v3dmath_test::object v3dmath_object; - tut::v3dmath_test v3dmath_testcase("v3dmath_h"); + struct v3dmath_data + { + }; + typedef test_group<v3dmath_data> v3dmath_test; + typedef v3dmath_test::object v3dmath_object; + tut::v3dmath_test v3dmath_testcase("v3dmath_h"); - template<> template<> - void v3dmath_object::test<1>() - { - LLVector3d vec3D; - ensure("1:LLVector3d:Fail to initialize ", ((0 == vec3D.mdV[VX]) && (0 == vec3D.mdV[VY]) && (0 == vec3D.mdV[VZ]))); - F64 x = 2.32f, y = 1.212f, z = -.12f; - LLVector3d vec3Da(x,y,z); - ensure("2:LLVector3d:Fail to initialize ", ((2.32f == vec3Da.mdV[VX]) && (1.212f == vec3Da.mdV[VY]) && (-.12f == vec3Da.mdV[VZ]))); - const F64 vec[3] = {1.2f ,3.2f, -4.2f}; - LLVector3d vec3Db(vec); - ensure("3:LLVector3d:Fail to initialize ", ((1.2f == vec3Db.mdV[VX]) && (3.2f == vec3Db.mdV[VY]) && (-4.2f == vec3Db.mdV[VZ]))); - LLVector3 vec3((F32)x,(F32)y,(F32)z); - LLVector3d vec3Dc(vec3); - ensure_equals("4:LLVector3d Fail to initialize",vec3Da,vec3Dc); - } + template<> template<> + void v3dmath_object::test<1>() + { + LLVector3d vec3D; + ensure("1:LLVector3d:Fail to initialize ", ((0 == vec3D.mdV[VX]) && (0 == vec3D.mdV[VY]) && (0 == vec3D.mdV[VZ]))); + F64 x = 2.32f, y = 1.212f, z = -.12f; + LLVector3d vec3Da(x,y,z); + ensure("2:LLVector3d:Fail to initialize ", ((2.32f == vec3Da.mdV[VX]) && (1.212f == vec3Da.mdV[VY]) && (-.12f == vec3Da.mdV[VZ]))); + const F64 vec[3] = {1.2f ,3.2f, -4.2f}; + LLVector3d vec3Db(vec); + ensure("3:LLVector3d:Fail to initialize ", ((1.2f == vec3Db.mdV[VX]) && (3.2f == vec3Db.mdV[VY]) && (-4.2f == vec3Db.mdV[VZ]))); + LLVector3 vec3((F32)x,(F32)y,(F32)z); + LLVector3d vec3Dc(vec3); + ensure_equals("4:LLVector3d Fail to initialize",vec3Da,vec3Dc); + } - template<> template<> - void v3dmath_object::test<2>() - { - S32 a = -235; - LLSD llsd(a); - LLVector3d vec3d(llsd); - LLSD sd = vec3d.getValue(); - LLVector3d vec3da(sd); - ensure("1:getValue:Fail ", (vec3d == vec3da)); - } + template<> template<> + void v3dmath_object::test<2>() + { + S32 a = -235; + LLSD llsd(a); + LLVector3d vec3d(llsd); + LLSD sd = vec3d.getValue(); + LLVector3d vec3da(sd); + ensure("1:getValue:Fail ", (vec3d == vec3da)); + } - template<> template<> - void v3dmath_object::test<3>() - { - F64 a = 232345521.411132; - LLSD llsd(a); - LLVector3d vec3d; - vec3d.setValue(llsd); - LLSD sd = vec3d.getValue(); - LLVector3d vec3da(sd); - ensure("1:setValue:Fail to initialize ", (vec3d == vec3da)); - } + template<> template<> + void v3dmath_object::test<3>() + { + F64 a = 232345521.411132; + LLSD llsd(a); + LLVector3d vec3d; + vec3d.setValue(llsd); + LLSD sd = vec3d.getValue(); + LLVector3d vec3da(sd); + ensure("1:setValue:Fail to initialize ", (vec3d == vec3da)); + } - template<> template<> - void v3dmath_object::test<4>() - { - F64 a[3] = {222231.43222, 12345.2343, -434343.33222}; - LLSD llsd; - llsd[0] = a[0]; - llsd[1] = a[1]; - llsd[2] = a[2]; - LLVector3d vec3D; - vec3D = (LLVector3d)llsd; - ensure("1:operator=:Fail to initialize ", ((llsd[0].asReal()== vec3D.mdV[VX]) && (llsd[1].asReal() == vec3D.mdV[VY]) && (llsd[2].asReal() == vec3D.mdV[VZ]))); - } - - template<> template<> - void v3dmath_object::test<5>() - { - F64 x = 2.32f, y = 1.212f, z = -.12f; - LLVector3d vec3D(x,y,z); - vec3D.clearVec(); - ensure("1:clearVec:Fail to initialize ", ((0 == vec3D.mdV[VX]) && (0 == vec3D.mdV[VY]) && (0 == vec3D.mdV[VZ]))); - vec3D.setVec(x,y,z); - ensure("2:setVec:Fail to initialize ", ((x == vec3D.mdV[VX]) && (y == vec3D.mdV[VY]) && (z == vec3D.mdV[VZ]))); - vec3D.zeroVec(); - ensure("3:zeroVec:Fail to initialize ", ((0 == vec3D.mdV[VX]) && (0 == vec3D.mdV[VY]) && (0 == vec3D.mdV[VZ]))); - vec3D.clearVec(); - LLVector3 vec3((F32)x,(F32)y,(F32)z); - vec3D.setVec(vec3); - ensure("4:setVec:Fail to initialize ", ((x == vec3D.mdV[VX]) && (y == vec3D.mdV[VY]) && (z == vec3D.mdV[VZ]))); - vec3D.clearVec(); - const F64 vec[3] = {x,y,z}; - vec3D.setVec(vec); - ensure("5:setVec:Fail to initialize ", ((x == vec3D.mdV[VX]) && (y == vec3D.mdV[VY]) && (z == vec3D.mdV[VZ]))); - LLVector3d vec3Da; - vec3Da.setVec(vec3D); - ensure_equals("6:setVec: Fail to initialize", vec3D, vec3Da); - } - - template<> template<> - void v3dmath_object::test<6>() - { - F64 x = -2.32, y = 1.212, z = -.12; - LLVector3d vec3D(x,y,z); - vec3D.abs(); - ensure("1:abs:Fail ", ((-x == vec3D.mdV[VX]) && (y == vec3D.mdV[VY]) && (-z == vec3D.mdV[VZ]))); - ensure("2:isNull():Fail ", (false == vec3D.isNull())); - vec3D.clearVec(); - x =.00000001, y = .000001001, z = .000001001; - vec3D.setVec(x,y,z); - ensure("3:isNull():Fail ", (true == vec3D.isNull())); - ensure("4:isExactlyZero():Fail ", (false == vec3D.isExactlyZero())); - x =.0000000, y = .00000000, z = .00000000; - vec3D.setVec(x,y,z); - ensure("5:isExactlyZero():Fail ", (true == vec3D.isExactlyZero())); - } + template<> template<> + void v3dmath_object::test<4>() + { + F64 a[3] = {222231.43222, 12345.2343, -434343.33222}; + LLSD llsd; + llsd[0] = a[0]; + llsd[1] = a[1]; + llsd[2] = a[2]; + LLVector3d vec3D; + vec3D = (LLVector3d)llsd; + ensure("1:operator=:Fail to initialize ", ((llsd[0].asReal()== vec3D.mdV[VX]) && (llsd[1].asReal() == vec3D.mdV[VY]) && (llsd[2].asReal() == vec3D.mdV[VZ]))); + } - template<> template<> - void v3dmath_object::test<7>() - { - F64 x = -2.32, y = 1.212, z = -.12; - LLVector3d vec3D(x,y,z); - - ensure("1:operator [] failed",( x == vec3D[0])); - ensure("2:operator [] failed",( y == vec3D[1])); - ensure("3:operator [] failed",( z == vec3D[2])); - vec3D.clearVec(); - x = 23.23, y = -.2361, z = 3.25; - vec3D.setVec(x,y,z); - F64 &ref1 = vec3D[0]; - ensure("4:operator [] failed",( ref1 == vec3D[0])); - F64 &ref2 = vec3D[1]; - ensure("5:operator [] failed",( ref2 == vec3D[1])); - F64 &ref3 = vec3D[2]; - ensure("6:operator [] failed",( ref3 == vec3D[2])); - } + template<> template<> + void v3dmath_object::test<5>() + { + F64 x = 2.32f, y = 1.212f, z = -.12f; + LLVector3d vec3D(x,y,z); + vec3D.clearVec(); + ensure("1:clearVec:Fail to initialize ", ((0 == vec3D.mdV[VX]) && (0 == vec3D.mdV[VY]) && (0 == vec3D.mdV[VZ]))); + vec3D.setVec(x,y,z); + ensure("2:setVec:Fail to initialize ", ((x == vec3D.mdV[VX]) && (y == vec3D.mdV[VY]) && (z == vec3D.mdV[VZ]))); + vec3D.zeroVec(); + ensure("3:zeroVec:Fail to initialize ", ((0 == vec3D.mdV[VX]) && (0 == vec3D.mdV[VY]) && (0 == vec3D.mdV[VZ]))); + vec3D.clearVec(); + LLVector3 vec3((F32)x,(F32)y,(F32)z); + vec3D.setVec(vec3); + ensure("4:setVec:Fail to initialize ", ((x == vec3D.mdV[VX]) && (y == vec3D.mdV[VY]) && (z == vec3D.mdV[VZ]))); + vec3D.clearVec(); + const F64 vec[3] = {x,y,z}; + vec3D.setVec(vec); + ensure("5:setVec:Fail to initialize ", ((x == vec3D.mdV[VX]) && (y == vec3D.mdV[VY]) && (z == vec3D.mdV[VZ]))); + LLVector3d vec3Da; + vec3Da.setVec(vec3D); + ensure_equals("6:setVec: Fail to initialize", vec3D, vec3Da); + } - template<> template<> - void v3dmath_object::test<8>() - { - F32 x = 1.f, y = 2.f, z = -1.f; - LLVector4 vec4(x,y,z); - LLVector3d vec3D; - vec3D = vec4; - ensure("1:operator=:Fail to initialize ", ((vec4.mV[VX] == vec3D.mdV[VX]) && (vec4.mV[VY] == vec3D.mdV[VY]) && (vec4.mV[VZ] == vec3D.mdV[VZ]))); - } + template<> template<> + void v3dmath_object::test<6>() + { + F64 x = -2.32, y = 1.212, z = -.12; + LLVector3d vec3D(x,y,z); + vec3D.abs(); + ensure("1:abs:Fail ", ((-x == vec3D.mdV[VX]) && (y == vec3D.mdV[VY]) && (-z == vec3D.mdV[VZ]))); + ensure("2:isNull():Fail ", (false == vec3D.isNull())); + vec3D.clearVec(); + x =.00000001, y = .000001001, z = .000001001; + vec3D.setVec(x,y,z); + ensure("3:isNull():Fail ", (true == vec3D.isNull())); + ensure("4:isExactlyZero():Fail ", (false == vec3D.isExactlyZero())); + x =.0000000, y = .00000000, z = .00000000; + vec3D.setVec(x,y,z); + ensure("5:isExactlyZero():Fail ", (true == vec3D.isExactlyZero())); + } - template<> template<> - void v3dmath_object::test<9>() - { - F64 x1 = 1.78787878, y1 = 232322.2121, z1 = -12121.121212; - F64 x2 = 1.2, y2 = 2.5, z2 = 1.; - LLVector3d vec3D(x1,y1,z1),vec3Da(x2,y2,z2),vec3Db; - vec3Db = vec3Da+ vec3D; - ensure("1:operator+:Fail to initialize ", ((x1+x2 == vec3Db.mdV[VX]) && (y1+y2 == vec3Db.mdV[VY]) && (z1+z2 == vec3Db.mdV[VZ]))); - x1 = -2.45, y1 = 2.1, z1 = 3.0; - vec3D.clearVec(); - vec3Da.clearVec(); - vec3D.setVec(x1,y1,z1); - vec3Da += vec3D; - ensure_equals("2:operator+=: Fail to initialize", vec3Da,vec3D); - vec3Da += vec3D; - ensure("3:operator+=:Fail to initialize ", ((2*x1 == vec3Da.mdV[VX]) && (2*y1 == vec3Da.mdV[VY]) && (2*z1 == vec3Da.mdV[VZ]))); - } + template<> template<> + void v3dmath_object::test<7>() + { + F64 x = -2.32, y = 1.212, z = -.12; + LLVector3d vec3D(x,y,z); - template<> template<> - void v3dmath_object::test<10>() - { - F64 x1 = 1., y1 = 2., z1 = -1.1; - F64 x2 = 1.2, y2 = 2.5, z2 = 1.; - LLVector3d vec3D(x1,y1,z1),vec3Da(x2,y2,z2),vec3Db; - vec3Db = vec3Da - vec3D; - ensure("1:operator-:Fail to initialize ", ((x2-x1 == vec3Db.mdV[VX]) && (y2-y1 == vec3Db.mdV[VY]) && (z2-z1 == vec3Db.mdV[VZ]))); - x1 = -2.45, y1 = 2.1, z1 = 3.0; - vec3D.clearVec(); - vec3Da.clearVec(); - vec3D.setVec(x1,y1,z1); - vec3Da -=vec3D; - ensure("2:operator-=:Fail to initialize ", ((2.45 == vec3Da.mdV[VX]) && (-2.1 == vec3Da.mdV[VY]) && (-3.0 == vec3Da.mdV[VZ]))); - vec3Da -= vec3D; - ensure("3:operator-=:Fail to initialize ", ((-2*x1 == vec3Da.mdV[VX]) && (-2*y1 == vec3Da.mdV[VY]) && (-2*z1 == vec3Da.mdV[VZ]))); - } - template<> template<> - void v3dmath_object::test<11>() - { - F64 x1 = 1., y1 = 2., z1 = -1.1; - F64 x2 = 1.2, y2 = 2.5, z2 = 1.; - LLVector3d vec3D(x1,y1,z1),vec3Da(x2,y2,z2); - F64 res = vec3D * vec3Da; - ensure_approximately_equals( - "1:operator* failed", - res, - (x1*x2 + y1*y2 + z1*z2), - 8); - vec3Da.clearVec(); - F64 mulVal = 4.2; - vec3Da = vec3D * mulVal; - ensure_approximately_equals( - "2a:operator* failed", - vec3Da.mdV[VX], - x1*mulVal, - 8); - ensure_approximately_equals( - "2b:operator* failed", - vec3Da.mdV[VY], - y1*mulVal, - 8); - ensure_approximately_equals( - "2c:operator* failed", - vec3Da.mdV[VZ], - z1*mulVal, - 8); - vec3Da.clearVec(); - vec3Da = mulVal * vec3D; - ensure_approximately_equals( - "3a:operator* failed", - vec3Da.mdV[VX], - x1*mulVal, - 8); - ensure_approximately_equals( - "3b:operator* failed", - vec3Da.mdV[VY], - y1*mulVal, - 8); - ensure_approximately_equals( - "3c:operator* failed", - vec3Da.mdV[VZ], - z1*mulVal, - 8); - vec3D *= mulVal; - ensure_approximately_equals( - "4a:operator*= failed", - vec3D.mdV[VX], - x1*mulVal, - 8); - ensure_approximately_equals( - "4b:operator*= failed", - vec3D.mdV[VY], - y1*mulVal, - 8); - ensure_approximately_equals( - "4c:operator*= failed", - vec3D.mdV[VZ], - z1*mulVal, - 8); - } + ensure("1:operator [] failed",( x == vec3D[0])); + ensure("2:operator [] failed",( y == vec3D[1])); + ensure("3:operator [] failed",( z == vec3D[2])); + vec3D.clearVec(); + x = 23.23, y = -.2361, z = 3.25; + vec3D.setVec(x,y,z); + F64 &ref1 = vec3D[0]; + ensure("4:operator [] failed",( ref1 == vec3D[0])); + F64 &ref2 = vec3D[1]; + ensure("5:operator [] failed",( ref2 == vec3D[1])); + F64 &ref3 = vec3D[2]; + ensure("6:operator [] failed",( ref3 == vec3D[2])); + } - template<> template<> - void v3dmath_object::test<12>() - { - F64 x1 = 1., y1 = 2., z1 = -1.1; - F64 x2 = 1.2, y2 = 2.5, z2 = 1.; - F64 val1, val2, val3; - LLVector3d vec3D(x1,y1,z1),vec3Da(x2,y2,z2), vec3Db; - vec3Db = vec3D % vec3Da; - val1 = y1*z2 - y2*z1; - val2 = z1*x2 -z2*x1; - val3 = x1*y2-x2*y1; - ensure("1:operator% failed",(val1 == vec3Db.mdV[VX]) && (val2 == vec3Db.mdV[VY]) && (val3 == vec3Db.mdV[VZ])); - vec3D %= vec3Da; - ensure("2:operator%= failed", - is_approx_equal(vec3D.mdV[VX],vec3Db.mdV[VX]) && - is_approx_equal(vec3D.mdV[VY],vec3Db.mdV[VY]) && - is_approx_equal(vec3D.mdV[VZ],vec3Db.mdV[VZ]) ); - } + template<> template<> + void v3dmath_object::test<8>() + { + F32 x = 1.f, y = 2.f, z = -1.f; + LLVector4 vec4(x,y,z); + LLVector3d vec3D; + vec3D = vec4; + ensure("1:operator=:Fail to initialize ", ((vec4.mV[VX] == vec3D.mdV[VX]) && (vec4.mV[VY] == vec3D.mdV[VY]) && (vec4.mV[VZ] == vec3D.mdV[VZ]))); + } - template<> template<> - void v3dmath_object::test<13>() - { - F64 x1 = 1., y1 = 2., z1 = -1.1,div = 4.2; - F64 t = 1.f / div; - LLVector3d vec3D(x1,y1,z1), vec3Da; - vec3Da = vec3D/div; - ensure_approximately_equals( - "1a:operator/ failed", - vec3Da.mdV[VX], - x1*t, - 8); - ensure_approximately_equals( - "1b:operator/ failed", - vec3Da.mdV[VY], - y1*t, - 8); - ensure_approximately_equals( - "1c:operator/ failed", - vec3Da.mdV[VZ], - z1*t, - 8); - x1 = 1.23, y1 = 4., z1 = -2.32; - vec3D.clearVec(); - vec3Da.clearVec(); - vec3D.setVec(x1,y1,z1); - vec3Da = vec3D/div; - ensure_approximately_equals( - "2a:operator/ failed", - vec3Da.mdV[VX], - x1*t, - 8); - ensure_approximately_equals( - "2b:operator/ failed", - vec3Da.mdV[VY], - y1*t, - 8); - ensure_approximately_equals( - "2c:operator/ failed", - vec3Da.mdV[VZ], - z1*t, - 8); - vec3D /= div; - ensure_approximately_equals( - "3a:operator/= failed", - vec3D.mdV[VX], - x1*t, - 8); - ensure_approximately_equals( - "3b:operator/= failed", - vec3D.mdV[VY], - y1*t, - 8); - ensure_approximately_equals( - "3c:operator/= failed", - vec3D.mdV[VZ], - z1*t, - 8); - } + template<> template<> + void v3dmath_object::test<9>() + { + F64 x1 = 1.78787878, y1 = 232322.2121, z1 = -12121.121212; + F64 x2 = 1.2, y2 = 2.5, z2 = 1.; + LLVector3d vec3D(x1,y1,z1),vec3Da(x2,y2,z2),vec3Db; + vec3Db = vec3Da+ vec3D; + ensure("1:operator+:Fail to initialize ", ((x1+x2 == vec3Db.mdV[VX]) && (y1+y2 == vec3Db.mdV[VY]) && (z1+z2 == vec3Db.mdV[VZ]))); + x1 = -2.45, y1 = 2.1, z1 = 3.0; + vec3D.clearVec(); + vec3Da.clearVec(); + vec3D.setVec(x1,y1,z1); + vec3Da += vec3D; + ensure_equals("2:operator+=: Fail to initialize", vec3Da,vec3D); + vec3Da += vec3D; + ensure("3:operator+=:Fail to initialize ", ((2*x1 == vec3Da.mdV[VX]) && (2*y1 == vec3Da.mdV[VY]) && (2*z1 == vec3Da.mdV[VZ]))); + } - template<> template<> - void v3dmath_object::test<14>() - { - F64 x1 = 1., y1 = 2., z1 = -1.1; - LLVector3d vec3D(x1,y1,z1), vec3Da; - ensure("1:operator!= failed",(true == (vec3D !=vec3Da))); - vec3Da = vec3D; - ensure("2:operator== failed",(vec3D ==vec3Da)); - vec3D.clearVec(); - vec3Da.clearVec(); - x1 = .211, y1 = 21.111, z1 = 23.22; - vec3D.setVec(x1,y1,z1); - vec3Da.setVec(x1,y1,z1); - ensure("3:operator== failed",(vec3D ==vec3Da)); - ensure("4:operator!= failed",(false == (vec3D !=vec3Da))); - } - - template<> template<> - void v3dmath_object::test<15>() - { - F64 x1 = 1., y1 = 2., z1 = -1.1; - LLVector3d vec3D(x1,y1,z1), vec3Da; - std::ostringstream stream1, stream2; - stream1 << vec3D; - vec3Da.setVec(x1,y1,z1); - stream2 << vec3Da; - ensure("1:operator << failed",(stream1.str() == stream2.str())); - } + template<> template<> + void v3dmath_object::test<10>() + { + F64 x1 = 1., y1 = 2., z1 = -1.1; + F64 x2 = 1.2, y2 = 2.5, z2 = 1.; + LLVector3d vec3D(x1,y1,z1),vec3Da(x2,y2,z2),vec3Db; + vec3Db = vec3Da - vec3D; + ensure("1:operator-:Fail to initialize ", ((x2-x1 == vec3Db.mdV[VX]) && (y2-y1 == vec3Db.mdV[VY]) && (z2-z1 == vec3Db.mdV[VZ]))); + x1 = -2.45, y1 = 2.1, z1 = 3.0; + vec3D.clearVec(); + vec3Da.clearVec(); + vec3D.setVec(x1,y1,z1); + vec3Da -=vec3D; + ensure("2:operator-=:Fail to initialize ", ((2.45 == vec3Da.mdV[VX]) && (-2.1 == vec3Da.mdV[VY]) && (-3.0 == vec3Da.mdV[VZ]))); + vec3Da -= vec3D; + ensure("3:operator-=:Fail to initialize ", ((-2*x1 == vec3Da.mdV[VX]) && (-2*y1 == vec3Da.mdV[VY]) && (-2*z1 == vec3Da.mdV[VZ]))); + } + template<> template<> + void v3dmath_object::test<11>() + { + F64 x1 = 1., y1 = 2., z1 = -1.1; + F64 x2 = 1.2, y2 = 2.5, z2 = 1.; + LLVector3d vec3D(x1,y1,z1),vec3Da(x2,y2,z2); + F64 res = vec3D * vec3Da; + ensure_approximately_equals( + "1:operator* failed", + res, + (x1*x2 + y1*y2 + z1*z2), + 8); + vec3Da.clearVec(); + F64 mulVal = 4.2; + vec3Da = vec3D * mulVal; + ensure_approximately_equals( + "2a:operator* failed", + vec3Da.mdV[VX], + x1*mulVal, + 8); + ensure_approximately_equals( + "2b:operator* failed", + vec3Da.mdV[VY], + y1*mulVal, + 8); + ensure_approximately_equals( + "2c:operator* failed", + vec3Da.mdV[VZ], + z1*mulVal, + 8); + vec3Da.clearVec(); + vec3Da = mulVal * vec3D; + ensure_approximately_equals( + "3a:operator* failed", + vec3Da.mdV[VX], + x1*mulVal, + 8); + ensure_approximately_equals( + "3b:operator* failed", + vec3Da.mdV[VY], + y1*mulVal, + 8); + ensure_approximately_equals( + "3c:operator* failed", + vec3Da.mdV[VZ], + z1*mulVal, + 8); + vec3D *= mulVal; + ensure_approximately_equals( + "4a:operator*= failed", + vec3D.mdV[VX], + x1*mulVal, + 8); + ensure_approximately_equals( + "4b:operator*= failed", + vec3D.mdV[VY], + y1*mulVal, + 8); + ensure_approximately_equals( + "4c:operator*= failed", + vec3D.mdV[VZ], + z1*mulVal, + 8); + } - template<> template<> - void v3dmath_object::test<16>() - { - F64 x1 = 1.23, y1 = 2.0, z1 = 4.; - std::string buf("1.23 2. 4"); - LLVector3d vec3D, vec3Da(x1,y1,z1); - LLVector3d::parseVector3d(buf, &vec3D); - ensure_equals("1:parseVector3d: failed " , vec3D, vec3Da); - } + template<> template<> + void v3dmath_object::test<12>() + { + F64 x1 = 1., y1 = 2., z1 = -1.1; + F64 x2 = 1.2, y2 = 2.5, z2 = 1.; + F64 val1, val2, val3; + LLVector3d vec3D(x1,y1,z1),vec3Da(x2,y2,z2), vec3Db; + vec3Db = vec3D % vec3Da; + val1 = y1*z2 - y2*z1; + val2 = z1*x2 -z2*x1; + val3 = x1*y2-x2*y1; + ensure("1:operator% failed",(val1 == vec3Db.mdV[VX]) && (val2 == vec3Db.mdV[VY]) && (val3 == vec3Db.mdV[VZ])); + vec3D %= vec3Da; + ensure("2:operator%= failed", + is_approx_equal(vec3D.mdV[VX],vec3Db.mdV[VX]) && + is_approx_equal(vec3D.mdV[VY],vec3Db.mdV[VY]) && + is_approx_equal(vec3D.mdV[VZ],vec3Db.mdV[VZ]) ); + } - template<> template<> - void v3dmath_object::test<17>() - { - F64 x1 = 1., y1 = 2., z1 = -1.1; - LLVector3d vec3D(x1,y1,z1), vec3Da; - vec3Da = -vec3D; - ensure("1:operator- failed", (vec3D == - vec3Da)); - } + template<> template<> + void v3dmath_object::test<13>() + { + F64 x1 = 1., y1 = 2., z1 = -1.1,div = 4.2; + F64 t = 1.f / div; + LLVector3d vec3D(x1,y1,z1), vec3Da; + vec3Da = vec3D/div; + ensure_approximately_equals( + "1a:operator/ failed", + vec3Da.mdV[VX], + x1*t, + 8); + ensure_approximately_equals( + "1b:operator/ failed", + vec3Da.mdV[VY], + y1*t, + 8); + ensure_approximately_equals( + "1c:operator/ failed", + vec3Da.mdV[VZ], + z1*t, + 8); + x1 = 1.23, y1 = 4., z1 = -2.32; + vec3D.clearVec(); + vec3Da.clearVec(); + vec3D.setVec(x1,y1,z1); + vec3Da = vec3D/div; + ensure_approximately_equals( + "2a:operator/ failed", + vec3Da.mdV[VX], + x1*t, + 8); + ensure_approximately_equals( + "2b:operator/ failed", + vec3Da.mdV[VY], + y1*t, + 8); + ensure_approximately_equals( + "2c:operator/ failed", + vec3Da.mdV[VZ], + z1*t, + 8); + vec3D /= div; + ensure_approximately_equals( + "3a:operator/= failed", + vec3D.mdV[VX], + x1*t, + 8); + ensure_approximately_equals( + "3b:operator/= failed", + vec3D.mdV[VY], + y1*t, + 8); + ensure_approximately_equals( + "3c:operator/= failed", + vec3D.mdV[VZ], + z1*t, + 8); + } - template<> template<> - void v3dmath_object::test<18>() - { - F64 x = 1., y = 2., z = -1.1; - LLVector3d vec3D(x,y,z); - F64 res = (x*x + y*y + z*z) - vec3D.magVecSquared(); - ensure("1:magVecSquared:Fail ", ((-F_APPROXIMATELY_ZERO <= res)&& (res <=F_APPROXIMATELY_ZERO))); - res = (F32) sqrt(x*x + y*y + z*z) - vec3D.magVec(); - ensure("2:magVec: Fail ", ((-F_APPROXIMATELY_ZERO <= res)&& (res <=F_APPROXIMATELY_ZERO))); - } + template<> template<> + void v3dmath_object::test<14>() + { + F64 x1 = 1., y1 = 2., z1 = -1.1; + LLVector3d vec3D(x1,y1,z1), vec3Da; + ensure("1:operator!= failed",(true == (vec3D !=vec3Da))); + vec3Da = vec3D; + ensure("2:operator== failed",(vec3D ==vec3Da)); + vec3D.clearVec(); + vec3Da.clearVec(); + x1 = .211, y1 = 21.111, z1 = 23.22; + vec3D.setVec(x1,y1,z1); + vec3Da.setVec(x1,y1,z1); + ensure("3:operator== failed",(vec3D ==vec3Da)); + ensure("4:operator!= failed",(false == (vec3D !=vec3Da))); + } - template<> template<> - void v3dmath_object::test<19>() - { - F64 x = 1., y = 2., z = -1.1; - LLVector3d vec3D(x,y,z); - F64 mag = vec3D.normVec(); - mag = 1.f/ mag; - ensure_approximately_equals( - "1a:normVec: Fail ", - vec3D.mdV[VX], - x * mag, - 8); - ensure_approximately_equals( - "1b:normVec: Fail ", - vec3D.mdV[VY], - y * mag, - 8); - ensure_approximately_equals( - "1c:normVec: Fail ", - vec3D.mdV[VZ], - z * mag, - 8); - x = 0.000000001, y = 0.000000001, z = 0.000000001; - vec3D.clearVec(); - vec3D.setVec(x,y,z); - mag = vec3D.normVec(); - ensure_approximately_equals( - "2a:normVec: Fail ", - vec3D.mdV[VX], - x * mag, - 8); - ensure_approximately_equals( - "2b:normVec: Fail ", - vec3D.mdV[VY], - y * mag, - 8); - ensure_approximately_equals( - "2c:normVec: Fail ", - vec3D.mdV[VZ], - z * mag, - 8); - } + template<> template<> + void v3dmath_object::test<15>() + { + F64 x1 = 1., y1 = 2., z1 = -1.1; + LLVector3d vec3D(x1,y1,z1), vec3Da; + std::ostringstream stream1, stream2; + stream1 << vec3D; + vec3Da.setVec(x1,y1,z1); + stream2 << vec3Da; + ensure("1:operator << failed",(stream1.str() == stream2.str())); + } - template<> template<> - void v3dmath_object::test<20>() - { - F64 x1 = 1111.232222; - F64 y1 = 2222222222.22; - F64 z1 = 422222222222.0; - std::string buf("1111.232222 2222222222.22 422222222222"); - LLVector3d vec3Da, vec3Db(x1,y1,z1); - LLVector3d::parseVector3d(buf, &vec3Da); - ensure_equals("1:parseVector3 failed", vec3Da, vec3Db); - } + template<> template<> + void v3dmath_object::test<16>() + { + F64 x1 = 1.23, y1 = 2.0, z1 = 4.; + std::string buf("1.23 2. 4"); + LLVector3d vec3D, vec3Da(x1,y1,z1); + LLVector3d::parseVector3d(buf, &vec3D); + ensure_equals("1:parseVector3d: failed " , vec3D, vec3Da); + } - template<> template<> - void v3dmath_object::test<21>() - { - F64 x1 = 1., y1 = 2., z1 = -1.1; - F64 x2 = 1.2, y2 = 2.5, z2 = 1.; - F64 val = 2.3f,val1,val2,val3; - val1 = x1 + (x2 - x1)* val; - val2 = y1 + (y2 - y1)* val; - val3 = z1 + (z2 - z1)* val; - LLVector3d vec3Da(x1,y1,z1),vec3Db(x2,y2,z2); - LLVector3d vec3d = lerp(vec3Da,vec3Db,val); - ensure("1:lerp failed", ((val1 ==vec3d.mdV[VX])&& (val2 ==vec3d.mdV[VY]) && (val3 ==vec3d.mdV[VZ]))); - } + template<> template<> + void v3dmath_object::test<17>() + { + F64 x1 = 1., y1 = 2., z1 = -1.1; + LLVector3d vec3D(x1,y1,z1), vec3Da; + vec3Da = -vec3D; + ensure("1:operator- failed", (vec3D == - vec3Da)); + } - template<> template<> - void v3dmath_object::test<22>() - { - F64 x = 2.32, y = 1.212, z = -.12; - F64 min = 0.0001, max = 3.0; - LLVector3d vec3d(x,y,z); - ensure("1:clamp:Fail ", (true == (vec3d.clamp(min, max)))); - x = 0.000001f, z = 5.3f; - vec3d.setVec(x,y,z); - ensure("2:clamp:Fail ", (true == (vec3d.clamp(min, max)))); - } + template<> template<> + void v3dmath_object::test<18>() + { + F64 x = 1., y = 2., z = -1.1; + LLVector3d vec3D(x,y,z); + F64 res = (x*x + y*y + z*z) - vec3D.magVecSquared(); + ensure("1:magVecSquared:Fail ", ((-F_APPROXIMATELY_ZERO <= res)&& (res <=F_APPROXIMATELY_ZERO))); + res = (F32) sqrt(x*x + y*y + z*z) - vec3D.magVec(); + ensure("2:magVec: Fail ", ((-F_APPROXIMATELY_ZERO <= res)&& (res <=F_APPROXIMATELY_ZERO))); + } - template<> template<> - void v3dmath_object::test<23>() - { - F64 x = 10., y = 20., z = -15.; - F64 epsilon = .23425; - LLVector3d vec3Da(x,y,z), vec3Db(x,y,z); - ensure("1:are_parallel: Fail ", (true == are_parallel(vec3Da,vec3Db,epsilon))); - F64 x1 = -12., y1 = -20., z1 = -100.; - vec3Db.clearVec(); - vec3Db.setVec(x1,y1,z1); - ensure("2:are_parallel: Fail ", (false == are_parallel(vec3Da,vec3Db,epsilon))); - } + template<> template<> + void v3dmath_object::test<19>() + { + F64 x = 1., y = 2., z = -1.1; + LLVector3d vec3D(x,y,z); + F64 mag = vec3D.normVec(); + mag = 1.f/ mag; + ensure_approximately_equals( + "1a:normVec: Fail ", + vec3D.mdV[VX], + x * mag, + 8); + ensure_approximately_equals( + "1b:normVec: Fail ", + vec3D.mdV[VY], + y * mag, + 8); + ensure_approximately_equals( + "1c:normVec: Fail ", + vec3D.mdV[VZ], + z * mag, + 8); + x = 0.000000001, y = 0.000000001, z = 0.000000001; + vec3D.clearVec(); + vec3D.setVec(x,y,z); + mag = vec3D.normVec(); + ensure_approximately_equals( + "2a:normVec: Fail ", + vec3D.mdV[VX], + x * mag, + 8); + ensure_approximately_equals( + "2b:normVec: Fail ", + vec3D.mdV[VY], + y * mag, + 8); + ensure_approximately_equals( + "2c:normVec: Fail ", + vec3D.mdV[VZ], + z * mag, + 8); + } - template<> template<> - void v3dmath_object::test<24>() - { + template<> template<> + void v3dmath_object::test<20>() + { + F64 x1 = 1111.232222; + F64 y1 = 2222222222.22; + F64 z1 = 422222222222.0; + std::string buf("1111.232222 2222222222.22 422222222222"); + LLVector3d vec3Da, vec3Db(x1,y1,z1); + LLVector3d::parseVector3d(buf, &vec3Da); + ensure_equals("1:parseVector3 failed", vec3Da, vec3Db); + } + + template<> template<> + void v3dmath_object::test<21>() + { + F64 x1 = 1., y1 = 2., z1 = -1.1; + F64 x2 = 1.2, y2 = 2.5, z2 = 1.; + F64 val = 2.3f,val1,val2,val3; + val1 = x1 + (x2 - x1)* val; + val2 = y1 + (y2 - y1)* val; + val3 = z1 + (z2 - z1)* val; + LLVector3d vec3Da(x1,y1,z1),vec3Db(x2,y2,z2); + LLVector3d vec3d = lerp(vec3Da,vec3Db,val); + ensure("1:lerp failed", ((val1 ==vec3d.mdV[VX])&& (val2 ==vec3d.mdV[VY]) && (val3 ==vec3d.mdV[VZ]))); + } + + template<> template<> + void v3dmath_object::test<22>() + { + F64 x = 2.32, y = 1.212, z = -.12; + F64 min = 0.0001, max = 3.0; + LLVector3d vec3d(x,y,z); + ensure("1:clamp:Fail ", (true == (vec3d.clamp(min, max)))); + x = 0.000001f, z = 5.3f; + vec3d.setVec(x,y,z); + ensure("2:clamp:Fail ", (true == (vec3d.clamp(min, max)))); + } + + template<> template<> + void v3dmath_object::test<23>() + { + F64 x = 10., y = 20., z = -15.; + F64 epsilon = .23425; + LLVector3d vec3Da(x,y,z), vec3Db(x,y,z); + ensure("1:are_parallel: Fail ", (true == are_parallel(vec3Da,vec3Db,epsilon))); + F64 x1 = -12., y1 = -20., z1 = -100.; + vec3Db.clearVec(); + vec3Db.setVec(x1,y1,z1); + ensure("2:are_parallel: Fail ", (false == are_parallel(vec3Da,vec3Db,epsilon))); + } + + template<> template<> + void v3dmath_object::test<24>() + { #if LL_WINDOWS && _MSC_VER < 1400 - skip("This fails on VS2003!"); + skip("This fails on VS2003!"); #else - F64 x = 10., y = 20., z = -15.; - F64 angle1, angle2; - LLVector3d vec3Da(x,y,z), vec3Db(x,y,z); - angle1 = angle_between(vec3Da, vec3Db); - ensure("1:angle_between: Fail ", (0 == angle1)); - F64 x1 = -1., y1 = -20., z1 = -1.; - vec3Da.clearVec(); - vec3Da.setVec(x1,y1,z1); - angle2 = angle_between(vec3Da, vec3Db); - vec3Db.normVec(); - vec3Da.normVec(); - F64 angle = vec3Db*vec3Da; - angle = acos(angle); + F64 x = 10., y = 20., z = -15.; + F64 angle1, angle2; + LLVector3d vec3Da(x,y,z), vec3Db(x,y,z); + angle1 = angle_between(vec3Da, vec3Db); + ensure("1:angle_between: Fail ", (0 == angle1)); + F64 x1 = -1., y1 = -20., z1 = -1.; + vec3Da.clearVec(); + vec3Da.setVec(x1,y1,z1); + angle2 = angle_between(vec3Da, vec3Db); + vec3Db.normVec(); + vec3Da.normVec(); + F64 angle = vec3Db*vec3Da; + angle = acos(angle); #if LL_WINDOWS && _MSC_VER > 1900 - skip("This fails on VS2017!"); + skip("This fails on VS2017!"); #else - ensure("2:angle_between: Fail ", (angle == angle2)); + ensure("2:angle_between: Fail ", (angle == angle2)); #endif - + #endif - } + } } diff --git a/indra/llmath/tests/v3math_test.cpp b/indra/llmath/tests/v3math_test.cpp index 090f399e62..6d95a9e5b7 100644 --- a/indra/llmath/tests/v3math_test.cpp +++ b/indra/llmath/tests/v3math_test.cpp @@ -7,25 +7,25 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ - + #include "linden_common.h" #include "../test/lltut.h" #include "llsd.h" @@ -40,546 +40,546 @@ namespace tut { - struct v3math_data - { - }; - typedef test_group<v3math_data> v3math_test; - typedef v3math_test::object v3math_object; - tut::v3math_test v3math_testcase("v3math_h"); - - template<> template<> - void v3math_object::test<1>() - { - LLVector3 vec3; - ensure("1:LLVector3:Fail to initialize ", ((0.f == vec3.mV[VX]) && (0.f == vec3.mV[VY]) && (0.f == vec3.mV[VZ]))); - F32 x = 2.32f, y = 1.212f, z = -.12f; - LLVector3 vec3a(x,y,z); - ensure("2:LLVector3:Fail to initialize ", ((2.32f == vec3a.mV[VX]) && (1.212f == vec3a.mV[VY]) && (-.12f == vec3a.mV[VZ]))); - const F32 vec[3] = {1.2f ,3.2f, -4.2f}; - LLVector3 vec3b(vec); - ensure("3:LLVector3:Fail to initialize ", ((1.2f == vec3b.mV[VX]) && (3.2f == vec3b.mV[VY]) && (-4.2f == vec3b.mV[VZ]))); - } - - template<> template<> - void v3math_object::test<2>() - { - F32 x = 2.32f, y = 1.212f, z = -.12f; - LLVector3 vec3(x,y,z); - LLVector3d vector3d(vec3); - LLVector3 vec3a(vector3d); - ensure("1:LLVector3:Fail to initialize ", vec3 == vec3a); - LLVector4 vector4(vec3); - LLVector3 vec3b(vector4); - ensure("2:LLVector3:Fail to initialize ", vec3 == vec3b); - } - - template<> template<> - void v3math_object::test<3>() - { - S32 a = 231; - LLSD llsd(a); - LLVector3 vec3(llsd); - LLSD sd = vec3.getValue(); - LLVector3 vec3a(sd); - ensure("1:LLVector3:Fail to initialize ", (vec3 == vec3a)); - } - - template<> template<> - void v3math_object::test<4>() - { - S32 a = 231; - LLSD llsd(a); - LLVector3 vec3(llsd),vec3a; - vec3a = vec3; - ensure("1:Operator= Fail to initialize " ,(vec3 == vec3a)); - } - - template<> template<> - void v3math_object::test<5>() - { - F32 x = 2.32f, y = 1.212f, z = -.12f; - LLVector3 vec3(x,y,z); - ensure("1:isFinite= Fail to initialize ", (true == vec3.isFinite()));//need more test cases: - vec3.clearVec(); - ensure("2:clearVec:Fail to set values ", ((0.f == vec3.mV[VX]) && (0.f == vec3.mV[VY]) && (0.f == vec3.mV[VZ]))); - vec3.setVec(x,y,z); - ensure("3:setVec:Fail to set values ", ((2.32f == vec3.mV[VX]) && (1.212f == vec3.mV[VY]) && (-.12f == vec3.mV[VZ]))); - vec3.zeroVec(); - ensure("4:zeroVec:Fail to set values ", ((0.f == vec3.mV[VX]) && (0.f == vec3.mV[VY]) && (0.f == vec3.mV[VZ]))); - } - - template<> template<> - void v3math_object::test<6>() - { - F32 x = 2.32f, y = 1.212f, z = -.12f; - LLVector3 vec3(x,y,z),vec3a; - vec3.abs(); - ensure("1:abs:Fail ", ((x == vec3.mV[VX]) && (y == vec3.mV[VY]) && (-z == vec3.mV[VZ]))); - vec3a.setVec(vec3); - ensure("2:setVec:Fail to initialize ", (vec3a == vec3)); - const F32 vec[3] = {1.2f ,3.2f, -4.2f}; - vec3.clearVec(); - vec3.setVec(vec); - ensure("3:setVec:Fail to initialize ", ((1.2f == vec3.mV[VX]) && (3.2f == vec3.mV[VY]) && (-4.2f == vec3.mV[VZ]))); - vec3a.clearVec(); - LLVector3d vector3d(vec3); - vec3a.setVec(vector3d); - ensure("4:setVec:Fail to initialize ", (vec3 == vec3a)); - LLVector4 vector4(vec3); - vec3a.clearVec(); - vec3a.setVec(vector4); - ensure("5:setVec:Fail to initialize ", (vec3 == vec3a)); - } - - template<> template<> - void v3math_object::test<7>() - { - F32 x = 2.32f, y = 3.212f, z = -.12f; - F32 min = 0.0001f, max = 3.0f; - LLVector3 vec3(x,y,z); - ensure("1:clamp:Fail ", true == vec3.clamp(min, max) && x == vec3.mV[VX] && max == vec3.mV[VY] && min == vec3.mV[VZ]); - x = 1.f, y = 2.2f, z = 2.8f; - vec3.setVec(x,y,z); - ensure("2:clamp:Fail ", false == vec3.clamp(min, max)); - } - - template<> template<> - void v3math_object::test<8>() - { - F32 x = 2.32f, y = 1.212f, z = -.12f; - LLVector3 vec3(x,y,z); - ensure("1:magVecSquared:Fail ", is_approx_equal(vec3.magVecSquared(), (x*x + y*y + z*z))); - ensure("2:magVec:Fail ", is_approx_equal(vec3.magVec(), (F32) sqrt(x*x + y*y + z*z))); - } - - template<> template<> - void v3math_object::test<9>() - { - F32 x =-2.0f, y = -3.0f, z = 1.23f ; - LLVector3 vec3(x,y,z); - ensure("1:abs():Fail ", (true == vec3.abs())); - ensure("2:isNull():Fail", (false == vec3.isNull())); //Returns true if vector has a _very_small_ length - x =.00000001f, y = .000001001f, z = .000001001f; - vec3.setVec(x,y,z); - ensure("3:isNull(): Fail ", (true == vec3.isNull())); - } - - template<> template<> - void v3math_object::test<10>() - { - F32 x =-2.0f, y = -3.0f, z = 1.f ; - LLVector3 vec3(x,y,z),vec3a; - ensure("1:isExactlyZero():Fail ", (true == vec3a.isExactlyZero())); - vec3a = vec3a.scaleVec(vec3); - ensure("2:scaleVec: Fail ", vec3a.mV[VX] == 0.f && vec3a.mV[VY] == 0.f && vec3a.mV[VZ] == 0.f); - vec3a.setVec(x,y,z); - vec3a = vec3a.scaleVec(vec3); - ensure("3:scaleVec: Fail ", ((4 == vec3a.mV[VX]) && (9 == vec3a.mV[VY]) &&(1 == vec3a.mV[VZ]))); - ensure("4:isExactlyZero():Fail ", (false == vec3.isExactlyZero())); - } - - template<> template<> - void v3math_object::test<11>() - { - F32 x =20.0f, y = 30.0f, z = 15.f ; - F32 angle = 100.f; - LLVector3 vec3(x,y,z),vec3a(1.f,2.f,3.f); - vec3a = vec3a.rotVec(angle, vec3); - LLVector3 vec3b(1.f,2.f,3.f); - vec3b = vec3b.rotVec(angle, vec3); - ensure_equals("rotVec():Fail" ,vec3b,vec3a); - } - - template<> template<> - void v3math_object::test<12>() - { - F32 x =-2.0f, y = -3.0f, z = 1.f ; - LLVector3 vec3(x,y,z); - ensure("1:operator [] failed",( x == vec3[0])); - ensure("2:operator [] failed",( y == vec3[1])); - ensure("3:operator [] failed",( z == vec3[2])); - - vec3.clearVec(); - x = 23.f, y = -.2361f, z = 3.25; - vec3.setVec(x,y,z); - F32 &ref1 = vec3[0]; - ensure("4:operator [] failed",( ref1 == vec3[0])); - F32 &ref2 = vec3[1]; - ensure("5:operator [] failed",( ref2 == vec3[1])); - F32 &ref3 = vec3[2]; - ensure("6:operator [] failed",( ref3 == vec3[2])); - } - - template<> template<> - void v3math_object::test<13>() - { - F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f; - F32 val1, val2, val3; - LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2), vec3b; - vec3b = vec3 + vec3a ; - val1 = x1+x2; - val2 = y1+y2; - val3 = z1+z2; - ensure("1:operator+ failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ])); - - vec3.clearVec(); - vec3a.clearVec(); - vec3b.clearVec(); - x1 = -.235f, y1 = -24.32f,z1 = 2.13f, x2 = -2.3f, y2 = 1.f, z2 = 34.21f; - vec3.setVec(x1,y1,z1); - vec3a.setVec(x2,y2,z2); - vec3b = vec3 + vec3a; - val1 = x1+x2; - val2 = y1+y2; - val3 = z1+z2; - ensure("2:operator+ failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ])); - } - - template<> template<> - void v3math_object::test<14>() - { - F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f; - F32 val1, val2, val3; - LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2), vec3b; - vec3b = vec3 - vec3a ; - val1 = x1-x2; - val2 = y1-y2; - val3 = z1-z2; - ensure("1:operator- failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ])); - - vec3.clearVec(); - vec3a.clearVec(); - vec3b.clearVec(); - x1 = -.235f, y1 = -24.32f,z1 = 2.13f, x2 = -2.3f, y2 = 1.f, z2 = 34.21f; - vec3.setVec(x1,y1,z1); - vec3a.setVec(x2,y2,z2); - vec3b = vec3 - vec3a; - val1 = x1-x2; - val2 = y1-y2; - val3 = z1-z2; - ensure("2:operator- failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ])); - } - - template<> template<> - void v3math_object::test<15>() - { - F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f; - F32 val1, val2, val3; - LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2); - val1 = vec3 * vec3a; - val2 = x1*x2 + y1*y2 + z1*z2; - ensure_equals("1:operator* failed",val1,val2); - - vec3a.clearVec(); - F32 mulVal = 4.332f; - vec3a = vec3 * mulVal; - val1 = x1*mulVal; - val2 = y1*mulVal; - val3 = z1*mulVal; - ensure("2:operator* failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ])); - vec3a.clearVec(); - vec3a = mulVal * vec3; - ensure("3:operator* failed ", (val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ])); - } - - template<> template<> - void v3math_object::test<16>() - { - F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f; - F32 val1, val2, val3; - LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2), vec3b; - vec3b = vec3 % vec3a ; - val1 = y1*z2 - y2*z1; - val2 = z1*x2 -z2*x1; - val3 = x1*y2-x2*y1; - ensure("1:operator% failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ])); - - vec3.clearVec(); - vec3a.clearVec(); - vec3b.clearVec(); - x1 =112.f, y1 = 22.3f,z1 = 1.2f, x2 = -2.3f, y2 = 341.11f, z2 = 1234.234f; - vec3.setVec(x1,y1,z1); - vec3a.setVec(x2,y2,z2); - vec3b = vec3 % vec3a ; - val1 = y1*z2 - y2*z1; - val2 = z1*x2 -z2*x1; - val3 = x1*y2-x2*y1; - ensure("2:operator% failed ", (val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ])); - } - - template<> template<> - void v3math_object::test<17>() - { - F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, div = 3.2f; - F32 t = 1.f / div, val1, val2, val3; - LLVector3 vec3(x1,y1,z1), vec3a; - vec3a = vec3 / div; - val1 = x1 * t; - val2 = y1 * t; - val3 = z1 *t; - ensure("1:operator/ failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY]) && (val3 == vec3a.mV[VZ])); - - vec3a.clearVec(); - x1 = -.235f, y1 = -24.32f, z1 = .342f, div = -2.2f; - t = 1.f / div; - vec3.setVec(x1,y1,z1); - vec3a = vec3 / div; - val1 = x1 * t; - val2 = y1 * t; - val3 = z1 *t; - ensure("2:operator/ failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY]) && (val3 == vec3a.mV[VZ])); - } - - template<> template<> - void v3math_object::test<18>() - { - F32 x1 =1.f, y1 = 2.f,z1 = 1.2f; - LLVector3 vec3(x1,y1,z1), vec3a(x1,y1,z1); - ensure("1:operator== failed",(vec3 == vec3a)); - - vec3a.clearVec(); - x1 = -.235f, y1 = -24.32f, z1 = .342f; - vec3.clearVec(); - vec3a.clearVec(); - vec3.setVec(x1,y1,z1); - vec3a.setVec(x1,y1,z1); - ensure("2:operator== failed ", (vec3 == vec3a)); - } - - template<> template<> - void v3math_object::test<19>() - { - F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 =112.f, y2 = 2.234f,z2 = 11.2f;; - LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2); - ensure("1:operator!= failed",(vec3a != vec3)); - - vec3.clearVec(); - vec3.clearVec(); - vec3a.setVec(vec3); - ensure("2:operator!= failed", ( false == (vec3a != vec3))); - } - - template<> template<> - void v3math_object::test<20>() - { - F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 =112.f, y2 = 2.2f,z2 = 11.2f;; - LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2); - vec3a += vec3; - F32 val1, val2, val3; - val1 = x1+x2; - val2 = y1+y2; - val3 = z1+z2; - ensure("1:operator+= failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ])); - } - - template<> template<> - void v3math_object::test<21>() - { - F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 =112.f, y2 = 2.2f,z2 = 11.2f;; - LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2); - vec3a -= vec3; - F32 val1, val2, val3; - val1 = x2-x1; - val2 = y2-y1; - val3 = z2-z1; - ensure("1:operator-= failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ])); - } - - template<> template<> - void v3math_object::test<22>() - { - F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f; - F32 val1,val2,val3; - LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2); - vec3a *= vec3; - val1 = x1*x2; - val2 = y1*y2; - val3 = z1*z2; - ensure("1:operator*= failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ])); - - F32 mulVal = 4.332f; - vec3 *=mulVal; - val1 = x1*mulVal; - val2 = y1*mulVal; - val3 = z1*mulVal; - ensure("2:operator*= failed ", is_approx_equal(val1, vec3.mV[VX]) && is_approx_equal(val2, vec3.mV[VY]) && is_approx_equal(val3, vec3.mV[VZ])); - } - - template<> template<> - void v3math_object::test<23>() - { - F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f; - LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2),vec3b; - vec3b = vec3a % vec3; - vec3a %= vec3; - ensure_equals("1:operator%= failed",vec3a,vec3b); - } - - template<> template<> - void v3math_object::test<24>() - { - F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, div = 3.2f; - F32 t = 1.f / div, val1, val2, val3; - LLVector3 vec3a(x1,y1,z1); - vec3a /= div; - val1 = x1 * t; - val2 = y1 * t; - val3 = z1 *t; - ensure("1:operator/= failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY]) && (val3 == vec3a.mV[VZ])); - } - - template<> template<> - void v3math_object::test<25>() - { - F32 x1 =1.f, y1 = 2.f,z1 = 1.2f; - LLVector3 vec3(x1,y1,z1), vec3a; - vec3a = -vec3; - ensure("1:operator- failed",(-vec3a == vec3)); - } - - template<> template<> - void v3math_object::test<26>() - { - F32 x1 =1.f, y1 = 2.f,z1 = 1.2f; - std::ostringstream stream1, stream2; - LLVector3 vec3(x1,y1,z1), vec3a; - stream1 << vec3; - vec3a.setVec(x1,y1,z1); - stream2 << vec3a; - ensure("1:operator << failed",(stream1.str() == stream2.str())); - } - - template<> template<> - void v3math_object::test<27>() - { - F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 1.11f, z2 = 1234.234f; - LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2); - ensure("1:operator< failed", (true == (vec3 < vec3a))); - x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 2.f, z2 = 1234.234f; - vec3.setVec(x1,y1,z1); - vec3a.setVec(x2,y2,z2); - ensure("2:operator< failed ", (true == (vec3 < vec3a))); - x1 =2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, - vec3.setVec(x1,y1,z1); - vec3a.setVec(x2,y2,z2); - ensure("3:operator< failed ", (false == (vec3 < vec3a))); - } - - template<> template<> - void v3math_object::test<28>() - { - F32 x1 =1.23f, y1 = 2.f,z1 = 4.f; - std::string buf("1.23 2. 4"); - LLVector3 vec3, vec3a(x1,y1,z1); - LLVector3::parseVector3(buf, &vec3); - ensure_equals("1:parseVector3 failed", vec3, vec3a); - } - - template<> template<> - void v3math_object::test<29>() - { - F32 x1 =1.f, y1 = 2.f,z1 = 4.f; - LLVector3 vec3(x1,y1,z1),vec3a,vec3b; - vec3a.setVec(1,1,1); - vec3a.scaleVec(vec3); - ensure_equals("1:scaleVec failed", vec3, vec3a); - vec3a.clearVec(); - vec3a.setVec(x1,y1,z1); - vec3a.scaleVec(vec3); - ensure("2:scaleVec failed", ((1.f ==vec3a.mV[VX])&& (4.f ==vec3a.mV[VY]) && (16.f ==vec3a.mV[VZ]))); - } - - template<> template<> - void v3math_object::test<30>() - { - F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 1.11f, z2 = 1234.234f; - F32 val = 2.3f,val1,val2,val3; - val1 = x1 + (x2 - x1)* val; - val2 = y1 + (y2 - y1)* val; - val3 = z1 + (z2 - z1)* val; - LLVector3 vec3(x1,y1,z1),vec3a(x2,y2,z2); - LLVector3 vec3b = lerp(vec3,vec3a,val); - ensure("1:lerp failed", ((val1 ==vec3b.mV[VX])&& (val2 ==vec3b.mV[VY]) && (val3 ==vec3b.mV[VZ]))); - } - - template<> template<> - void v3math_object::test<31>() - { - F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 1.f, z2 = 1.f; - F32 val1,val2; - LLVector3 vec3(x1,y1,z1),vec3a(x2,y2,z2); - val1 = dist_vec(vec3,vec3a); - val2 = (F32) sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); - ensure_equals("1:dist_vec: Fail ",val2, val1); - val1 = dist_vec_squared(vec3,vec3a); - val2 =((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); - ensure_equals("2:dist_vec_squared: Fail ",val2, val1); - val1 = dist_vec_squared2D(vec3, vec3a); - val2 =(x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2); - ensure_equals("3:dist_vec_squared2D: Fail ",val2, val1); - } - - template<> template<> - void v3math_object::test<32>() - { - F32 x =12.3524f, y = -342.f,z = 4.126341f; - LLVector3 vec3(x,y,z); - F32 mag = vec3.normVec(); - mag = 1.f/ mag; - F32 val1 = x* mag, val2 = y* mag, val3 = z* mag; - ensure("1:normVec: Fail ", is_approx_equal(val1, vec3.mV[VX]) && is_approx_equal(val2, vec3.mV[VY]) && is_approx_equal(val3, vec3.mV[VZ])); - x = 0.000000001f, y = 0.f, z = 0.f; - vec3.clearVec(); - vec3.setVec(x,y,z); - mag = vec3.normVec(); - val1 = x* mag, val2 = y* mag, val3 = z* mag; - ensure("2:normVec: Fail ", (mag == 0.) && (0. == vec3.mV[VX]) && (0. == vec3.mV[VY])&& (0. == vec3.mV[VZ])); - } - - template<> template<> - void v3math_object::test<33>() - { - F32 x = -202.23412f, y = 123.2312f, z = -89.f; - LLVector3 vec(x,y,z); - vec.snap(2); - ensure("1:snap: Fail ", is_approx_equal(-202.23f, vec.mV[VX]) && is_approx_equal(123.23f, vec.mV[VY]) && is_approx_equal(-89.f, vec.mV[VZ])); - } - - template<> template<> - void v3math_object::test<34>() - { - F32 x = 10.f, y = 20.f, z = -15.f; - F32 x1, y1, z1; - F32 lowerxy = 0.f, upperxy = 1.0f, lowerz = -1.0f, upperz = 1.f; - LLVector3 vec3(x,y,z); - vec3.quantize16(lowerxy,upperxy,lowerz,upperz); - x1 = U16_to_F32(F32_to_U16(x, lowerxy, upperxy), lowerxy, upperxy); - y1 = U16_to_F32(F32_to_U16(y, lowerxy, upperxy), lowerxy, upperxy); - z1 = U16_to_F32(F32_to_U16(z, lowerz, upperz), lowerz, upperz); - ensure("1:quantize16: Fail ", is_approx_equal(x1, vec3.mV[VX]) && is_approx_equal(y1, vec3.mV[VY]) && is_approx_equal(z1, vec3.mV[VZ])); - LLVector3 vec3a(x,y,z); - vec3a.quantize8(lowerxy,upperxy,lowerz,upperz); - x1 = U8_to_F32(F32_to_U8(x, lowerxy, upperxy), lowerxy, upperxy); - y1 = U8_to_F32(F32_to_U8(y, lowerxy, upperxy), lowerxy, upperxy); - z1 = U8_to_F32(F32_to_U8(z, lowerz, upperz), lowerz, upperz); - ensure("2:quantize8: Fail ", is_approx_equal(x1, vec3a.mV[VX]) && is_approx_equal(y1, vec3a.mV[VY]) && is_approx_equal(z1, vec3a.mV[VZ])); - } - - template<> template<> - void v3math_object::test<35>() - { - LLSD sd = LLSD::emptyArray(); - sd[0] = 1.f; - - LLVector3 parsed_1(sd); - ensure("1:LLSD parse: Fail ", is_approx_equal(parsed_1.mV[VX], 1.f) && is_approx_equal(parsed_1.mV[VY], 0.f) && is_approx_equal(parsed_1.mV[VZ], 0.f)); - - sd[1] = 2.f; - LLVector3 parsed_2(sd); - ensure("2:LLSD parse: Fail ", is_approx_equal(parsed_2.mV[VX], 1.f) && is_approx_equal(parsed_2.mV[VY], 2.f) && is_approx_equal(parsed_2.mV[VZ], 0.f)); - - sd[2] = 3.f; - LLVector3 parsed_3(sd); - ensure("3:LLSD parse: Fail ", is_approx_equal(parsed_3.mV[VX], 1.f) && is_approx_equal(parsed_3.mV[VY], 2.f) && is_approx_equal(parsed_3.mV[VZ], 3.f)); - } + struct v3math_data + { + }; + typedef test_group<v3math_data> v3math_test; + typedef v3math_test::object v3math_object; + tut::v3math_test v3math_testcase("v3math_h"); + + template<> template<> + void v3math_object::test<1>() + { + LLVector3 vec3; + ensure("1:LLVector3:Fail to initialize ", ((0.f == vec3.mV[VX]) && (0.f == vec3.mV[VY]) && (0.f == vec3.mV[VZ]))); + F32 x = 2.32f, y = 1.212f, z = -.12f; + LLVector3 vec3a(x,y,z); + ensure("2:LLVector3:Fail to initialize ", ((2.32f == vec3a.mV[VX]) && (1.212f == vec3a.mV[VY]) && (-.12f == vec3a.mV[VZ]))); + const F32 vec[3] = {1.2f ,3.2f, -4.2f}; + LLVector3 vec3b(vec); + ensure("3:LLVector3:Fail to initialize ", ((1.2f == vec3b.mV[VX]) && (3.2f == vec3b.mV[VY]) && (-4.2f == vec3b.mV[VZ]))); + } + + template<> template<> + void v3math_object::test<2>() + { + F32 x = 2.32f, y = 1.212f, z = -.12f; + LLVector3 vec3(x,y,z); + LLVector3d vector3d(vec3); + LLVector3 vec3a(vector3d); + ensure("1:LLVector3:Fail to initialize ", vec3 == vec3a); + LLVector4 vector4(vec3); + LLVector3 vec3b(vector4); + ensure("2:LLVector3:Fail to initialize ", vec3 == vec3b); + } + + template<> template<> + void v3math_object::test<3>() + { + S32 a = 231; + LLSD llsd(a); + LLVector3 vec3(llsd); + LLSD sd = vec3.getValue(); + LLVector3 vec3a(sd); + ensure("1:LLVector3:Fail to initialize ", (vec3 == vec3a)); + } + + template<> template<> + void v3math_object::test<4>() + { + S32 a = 231; + LLSD llsd(a); + LLVector3 vec3(llsd),vec3a; + vec3a = vec3; + ensure("1:Operator= Fail to initialize " ,(vec3 == vec3a)); + } + + template<> template<> + void v3math_object::test<5>() + { + F32 x = 2.32f, y = 1.212f, z = -.12f; + LLVector3 vec3(x,y,z); + ensure("1:isFinite= Fail to initialize ", (true == vec3.isFinite()));//need more test cases: + vec3.clearVec(); + ensure("2:clearVec:Fail to set values ", ((0.f == vec3.mV[VX]) && (0.f == vec3.mV[VY]) && (0.f == vec3.mV[VZ]))); + vec3.setVec(x,y,z); + ensure("3:setVec:Fail to set values ", ((2.32f == vec3.mV[VX]) && (1.212f == vec3.mV[VY]) && (-.12f == vec3.mV[VZ]))); + vec3.zeroVec(); + ensure("4:zeroVec:Fail to set values ", ((0.f == vec3.mV[VX]) && (0.f == vec3.mV[VY]) && (0.f == vec3.mV[VZ]))); + } + + template<> template<> + void v3math_object::test<6>() + { + F32 x = 2.32f, y = 1.212f, z = -.12f; + LLVector3 vec3(x,y,z),vec3a; + vec3.abs(); + ensure("1:abs:Fail ", ((x == vec3.mV[VX]) && (y == vec3.mV[VY]) && (-z == vec3.mV[VZ]))); + vec3a.setVec(vec3); + ensure("2:setVec:Fail to initialize ", (vec3a == vec3)); + const F32 vec[3] = {1.2f ,3.2f, -4.2f}; + vec3.clearVec(); + vec3.setVec(vec); + ensure("3:setVec:Fail to initialize ", ((1.2f == vec3.mV[VX]) && (3.2f == vec3.mV[VY]) && (-4.2f == vec3.mV[VZ]))); + vec3a.clearVec(); + LLVector3d vector3d(vec3); + vec3a.setVec(vector3d); + ensure("4:setVec:Fail to initialize ", (vec3 == vec3a)); + LLVector4 vector4(vec3); + vec3a.clearVec(); + vec3a.setVec(vector4); + ensure("5:setVec:Fail to initialize ", (vec3 == vec3a)); + } + + template<> template<> + void v3math_object::test<7>() + { + F32 x = 2.32f, y = 3.212f, z = -.12f; + F32 min = 0.0001f, max = 3.0f; + LLVector3 vec3(x,y,z); + ensure("1:clamp:Fail ", true == vec3.clamp(min, max) && x == vec3.mV[VX] && max == vec3.mV[VY] && min == vec3.mV[VZ]); + x = 1.f, y = 2.2f, z = 2.8f; + vec3.setVec(x,y,z); + ensure("2:clamp:Fail ", false == vec3.clamp(min, max)); + } + + template<> template<> + void v3math_object::test<8>() + { + F32 x = 2.32f, y = 1.212f, z = -.12f; + LLVector3 vec3(x,y,z); + ensure("1:magVecSquared:Fail ", is_approx_equal(vec3.magVecSquared(), (x*x + y*y + z*z))); + ensure("2:magVec:Fail ", is_approx_equal(vec3.magVec(), (F32) sqrt(x*x + y*y + z*z))); + } + + template<> template<> + void v3math_object::test<9>() + { + F32 x =-2.0f, y = -3.0f, z = 1.23f ; + LLVector3 vec3(x,y,z); + ensure("1:abs():Fail ", (true == vec3.abs())); + ensure("2:isNull():Fail", (false == vec3.isNull())); //Returns true if vector has a _very_small_ length + x =.00000001f, y = .000001001f, z = .000001001f; + vec3.setVec(x,y,z); + ensure("3:isNull(): Fail ", (true == vec3.isNull())); + } + + template<> template<> + void v3math_object::test<10>() + { + F32 x =-2.0f, y = -3.0f, z = 1.f ; + LLVector3 vec3(x,y,z),vec3a; + ensure("1:isExactlyZero():Fail ", (true == vec3a.isExactlyZero())); + vec3a = vec3a.scaleVec(vec3); + ensure("2:scaleVec: Fail ", vec3a.mV[VX] == 0.f && vec3a.mV[VY] == 0.f && vec3a.mV[VZ] == 0.f); + vec3a.setVec(x,y,z); + vec3a = vec3a.scaleVec(vec3); + ensure("3:scaleVec: Fail ", ((4 == vec3a.mV[VX]) && (9 == vec3a.mV[VY]) &&(1 == vec3a.mV[VZ]))); + ensure("4:isExactlyZero():Fail ", (false == vec3.isExactlyZero())); + } + + template<> template<> + void v3math_object::test<11>() + { + F32 x =20.0f, y = 30.0f, z = 15.f ; + F32 angle = 100.f; + LLVector3 vec3(x,y,z),vec3a(1.f,2.f,3.f); + vec3a = vec3a.rotVec(angle, vec3); + LLVector3 vec3b(1.f,2.f,3.f); + vec3b = vec3b.rotVec(angle, vec3); + ensure_equals("rotVec():Fail" ,vec3b,vec3a); + } + + template<> template<> + void v3math_object::test<12>() + { + F32 x =-2.0f, y = -3.0f, z = 1.f ; + LLVector3 vec3(x,y,z); + ensure("1:operator [] failed",( x == vec3[0])); + ensure("2:operator [] failed",( y == vec3[1])); + ensure("3:operator [] failed",( z == vec3[2])); + + vec3.clearVec(); + x = 23.f, y = -.2361f, z = 3.25; + vec3.setVec(x,y,z); + F32 &ref1 = vec3[0]; + ensure("4:operator [] failed",( ref1 == vec3[0])); + F32 &ref2 = vec3[1]; + ensure("5:operator [] failed",( ref2 == vec3[1])); + F32 &ref3 = vec3[2]; + ensure("6:operator [] failed",( ref3 == vec3[2])); + } + + template<> template<> + void v3math_object::test<13>() + { + F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f; + F32 val1, val2, val3; + LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2), vec3b; + vec3b = vec3 + vec3a ; + val1 = x1+x2; + val2 = y1+y2; + val3 = z1+z2; + ensure("1:operator+ failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ])); + + vec3.clearVec(); + vec3a.clearVec(); + vec3b.clearVec(); + x1 = -.235f, y1 = -24.32f,z1 = 2.13f, x2 = -2.3f, y2 = 1.f, z2 = 34.21f; + vec3.setVec(x1,y1,z1); + vec3a.setVec(x2,y2,z2); + vec3b = vec3 + vec3a; + val1 = x1+x2; + val2 = y1+y2; + val3 = z1+z2; + ensure("2:operator+ failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ])); + } + + template<> template<> + void v3math_object::test<14>() + { + F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f; + F32 val1, val2, val3; + LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2), vec3b; + vec3b = vec3 - vec3a ; + val1 = x1-x2; + val2 = y1-y2; + val3 = z1-z2; + ensure("1:operator- failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ])); + + vec3.clearVec(); + vec3a.clearVec(); + vec3b.clearVec(); + x1 = -.235f, y1 = -24.32f,z1 = 2.13f, x2 = -2.3f, y2 = 1.f, z2 = 34.21f; + vec3.setVec(x1,y1,z1); + vec3a.setVec(x2,y2,z2); + vec3b = vec3 - vec3a; + val1 = x1-x2; + val2 = y1-y2; + val3 = z1-z2; + ensure("2:operator- failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ])); + } + + template<> template<> + void v3math_object::test<15>() + { + F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f; + F32 val1, val2, val3; + LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2); + val1 = vec3 * vec3a; + val2 = x1*x2 + y1*y2 + z1*z2; + ensure_equals("1:operator* failed",val1,val2); + + vec3a.clearVec(); + F32 mulVal = 4.332f; + vec3a = vec3 * mulVal; + val1 = x1*mulVal; + val2 = y1*mulVal; + val3 = z1*mulVal; + ensure("2:operator* failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ])); + vec3a.clearVec(); + vec3a = mulVal * vec3; + ensure("3:operator* failed ", (val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ])); + } + + template<> template<> + void v3math_object::test<16>() + { + F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f; + F32 val1, val2, val3; + LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2), vec3b; + vec3b = vec3 % vec3a ; + val1 = y1*z2 - y2*z1; + val2 = z1*x2 -z2*x1; + val3 = x1*y2-x2*y1; + ensure("1:operator% failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ])); + + vec3.clearVec(); + vec3a.clearVec(); + vec3b.clearVec(); + x1 =112.f, y1 = 22.3f,z1 = 1.2f, x2 = -2.3f, y2 = 341.11f, z2 = 1234.234f; + vec3.setVec(x1,y1,z1); + vec3a.setVec(x2,y2,z2); + vec3b = vec3 % vec3a ; + val1 = y1*z2 - y2*z1; + val2 = z1*x2 -z2*x1; + val3 = x1*y2-x2*y1; + ensure("2:operator% failed ", (val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ])); + } + + template<> template<> + void v3math_object::test<17>() + { + F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, div = 3.2f; + F32 t = 1.f / div, val1, val2, val3; + LLVector3 vec3(x1,y1,z1), vec3a; + vec3a = vec3 / div; + val1 = x1 * t; + val2 = y1 * t; + val3 = z1 *t; + ensure("1:operator/ failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY]) && (val3 == vec3a.mV[VZ])); + + vec3a.clearVec(); + x1 = -.235f, y1 = -24.32f, z1 = .342f, div = -2.2f; + t = 1.f / div; + vec3.setVec(x1,y1,z1); + vec3a = vec3 / div; + val1 = x1 * t; + val2 = y1 * t; + val3 = z1 *t; + ensure("2:operator/ failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY]) && (val3 == vec3a.mV[VZ])); + } + + template<> template<> + void v3math_object::test<18>() + { + F32 x1 =1.f, y1 = 2.f,z1 = 1.2f; + LLVector3 vec3(x1,y1,z1), vec3a(x1,y1,z1); + ensure("1:operator== failed",(vec3 == vec3a)); + + vec3a.clearVec(); + x1 = -.235f, y1 = -24.32f, z1 = .342f; + vec3.clearVec(); + vec3a.clearVec(); + vec3.setVec(x1,y1,z1); + vec3a.setVec(x1,y1,z1); + ensure("2:operator== failed ", (vec3 == vec3a)); + } + + template<> template<> + void v3math_object::test<19>() + { + F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 =112.f, y2 = 2.234f,z2 = 11.2f;; + LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2); + ensure("1:operator!= failed",(vec3a != vec3)); + + vec3.clearVec(); + vec3.clearVec(); + vec3a.setVec(vec3); + ensure("2:operator!= failed", ( false == (vec3a != vec3))); + } + + template<> template<> + void v3math_object::test<20>() + { + F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 =112.f, y2 = 2.2f,z2 = 11.2f;; + LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2); + vec3a += vec3; + F32 val1, val2, val3; + val1 = x1+x2; + val2 = y1+y2; + val3 = z1+z2; + ensure("1:operator+= failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ])); + } + + template<> template<> + void v3math_object::test<21>() + { + F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 =112.f, y2 = 2.2f,z2 = 11.2f;; + LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2); + vec3a -= vec3; + F32 val1, val2, val3; + val1 = x2-x1; + val2 = y2-y1; + val3 = z2-z1; + ensure("1:operator-= failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ])); + } + + template<> template<> + void v3math_object::test<22>() + { + F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f; + F32 val1,val2,val3; + LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2); + vec3a *= vec3; + val1 = x1*x2; + val2 = y1*y2; + val3 = z1*z2; + ensure("1:operator*= failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ])); + + F32 mulVal = 4.332f; + vec3 *=mulVal; + val1 = x1*mulVal; + val2 = y1*mulVal; + val3 = z1*mulVal; + ensure("2:operator*= failed ", is_approx_equal(val1, vec3.mV[VX]) && is_approx_equal(val2, vec3.mV[VY]) && is_approx_equal(val3, vec3.mV[VZ])); + } + + template<> template<> + void v3math_object::test<23>() + { + F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f; + LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2),vec3b; + vec3b = vec3a % vec3; + vec3a %= vec3; + ensure_equals("1:operator%= failed",vec3a,vec3b); + } + + template<> template<> + void v3math_object::test<24>() + { + F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, div = 3.2f; + F32 t = 1.f / div, val1, val2, val3; + LLVector3 vec3a(x1,y1,z1); + vec3a /= div; + val1 = x1 * t; + val2 = y1 * t; + val3 = z1 *t; + ensure("1:operator/= failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY]) && (val3 == vec3a.mV[VZ])); + } + + template<> template<> + void v3math_object::test<25>() + { + F32 x1 =1.f, y1 = 2.f,z1 = 1.2f; + LLVector3 vec3(x1,y1,z1), vec3a; + vec3a = -vec3; + ensure("1:operator- failed",(-vec3a == vec3)); + } + + template<> template<> + void v3math_object::test<26>() + { + F32 x1 =1.f, y1 = 2.f,z1 = 1.2f; + std::ostringstream stream1, stream2; + LLVector3 vec3(x1,y1,z1), vec3a; + stream1 << vec3; + vec3a.setVec(x1,y1,z1); + stream2 << vec3a; + ensure("1:operator << failed",(stream1.str() == stream2.str())); + } + + template<> template<> + void v3math_object::test<27>() + { + F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 1.11f, z2 = 1234.234f; + LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2); + ensure("1:operator< failed", (true == (vec3 < vec3a))); + x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 2.f, z2 = 1234.234f; + vec3.setVec(x1,y1,z1); + vec3a.setVec(x2,y2,z2); + ensure("2:operator< failed ", (true == (vec3 < vec3a))); + x1 =2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, + vec3.setVec(x1,y1,z1); + vec3a.setVec(x2,y2,z2); + ensure("3:operator< failed ", (false == (vec3 < vec3a))); + } + + template<> template<> + void v3math_object::test<28>() + { + F32 x1 =1.23f, y1 = 2.f,z1 = 4.f; + std::string buf("1.23 2. 4"); + LLVector3 vec3, vec3a(x1,y1,z1); + LLVector3::parseVector3(buf, &vec3); + ensure_equals("1:parseVector3 failed", vec3, vec3a); + } + + template<> template<> + void v3math_object::test<29>() + { + F32 x1 =1.f, y1 = 2.f,z1 = 4.f; + LLVector3 vec3(x1,y1,z1),vec3a,vec3b; + vec3a.setVec(1,1,1); + vec3a.scaleVec(vec3); + ensure_equals("1:scaleVec failed", vec3, vec3a); + vec3a.clearVec(); + vec3a.setVec(x1,y1,z1); + vec3a.scaleVec(vec3); + ensure("2:scaleVec failed", ((1.f ==vec3a.mV[VX])&& (4.f ==vec3a.mV[VY]) && (16.f ==vec3a.mV[VZ]))); + } + + template<> template<> + void v3math_object::test<30>() + { + F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 1.11f, z2 = 1234.234f; + F32 val = 2.3f,val1,val2,val3; + val1 = x1 + (x2 - x1)* val; + val2 = y1 + (y2 - y1)* val; + val3 = z1 + (z2 - z1)* val; + LLVector3 vec3(x1,y1,z1),vec3a(x2,y2,z2); + LLVector3 vec3b = lerp(vec3,vec3a,val); + ensure("1:lerp failed", ((val1 ==vec3b.mV[VX])&& (val2 ==vec3b.mV[VY]) && (val3 ==vec3b.mV[VZ]))); + } + + template<> template<> + void v3math_object::test<31>() + { + F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 1.f, z2 = 1.f; + F32 val1,val2; + LLVector3 vec3(x1,y1,z1),vec3a(x2,y2,z2); + val1 = dist_vec(vec3,vec3a); + val2 = (F32) sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); + ensure_equals("1:dist_vec: Fail ",val2, val1); + val1 = dist_vec_squared(vec3,vec3a); + val2 =((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); + ensure_equals("2:dist_vec_squared: Fail ",val2, val1); + val1 = dist_vec_squared2D(vec3, vec3a); + val2 =(x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2); + ensure_equals("3:dist_vec_squared2D: Fail ",val2, val1); + } + + template<> template<> + void v3math_object::test<32>() + { + F32 x =12.3524f, y = -342.f,z = 4.126341f; + LLVector3 vec3(x,y,z); + F32 mag = vec3.normVec(); + mag = 1.f/ mag; + F32 val1 = x* mag, val2 = y* mag, val3 = z* mag; + ensure("1:normVec: Fail ", is_approx_equal(val1, vec3.mV[VX]) && is_approx_equal(val2, vec3.mV[VY]) && is_approx_equal(val3, vec3.mV[VZ])); + x = 0.000000001f, y = 0.f, z = 0.f; + vec3.clearVec(); + vec3.setVec(x,y,z); + mag = vec3.normVec(); + val1 = x* mag, val2 = y* mag, val3 = z* mag; + ensure("2:normVec: Fail ", (mag == 0.) && (0. == vec3.mV[VX]) && (0. == vec3.mV[VY])&& (0. == vec3.mV[VZ])); + } + + template<> template<> + void v3math_object::test<33>() + { + F32 x = -202.23412f, y = 123.2312f, z = -89.f; + LLVector3 vec(x,y,z); + vec.snap(2); + ensure("1:snap: Fail ", is_approx_equal(-202.23f, vec.mV[VX]) && is_approx_equal(123.23f, vec.mV[VY]) && is_approx_equal(-89.f, vec.mV[VZ])); + } + + template<> template<> + void v3math_object::test<34>() + { + F32 x = 10.f, y = 20.f, z = -15.f; + F32 x1, y1, z1; + F32 lowerxy = 0.f, upperxy = 1.0f, lowerz = -1.0f, upperz = 1.f; + LLVector3 vec3(x,y,z); + vec3.quantize16(lowerxy,upperxy,lowerz,upperz); + x1 = U16_to_F32(F32_to_U16(x, lowerxy, upperxy), lowerxy, upperxy); + y1 = U16_to_F32(F32_to_U16(y, lowerxy, upperxy), lowerxy, upperxy); + z1 = U16_to_F32(F32_to_U16(z, lowerz, upperz), lowerz, upperz); + ensure("1:quantize16: Fail ", is_approx_equal(x1, vec3.mV[VX]) && is_approx_equal(y1, vec3.mV[VY]) && is_approx_equal(z1, vec3.mV[VZ])); + LLVector3 vec3a(x,y,z); + vec3a.quantize8(lowerxy,upperxy,lowerz,upperz); + x1 = U8_to_F32(F32_to_U8(x, lowerxy, upperxy), lowerxy, upperxy); + y1 = U8_to_F32(F32_to_U8(y, lowerxy, upperxy), lowerxy, upperxy); + z1 = U8_to_F32(F32_to_U8(z, lowerz, upperz), lowerz, upperz); + ensure("2:quantize8: Fail ", is_approx_equal(x1, vec3a.mV[VX]) && is_approx_equal(y1, vec3a.mV[VY]) && is_approx_equal(z1, vec3a.mV[VZ])); + } + + template<> template<> + void v3math_object::test<35>() + { + LLSD sd = LLSD::emptyArray(); + sd[0] = 1.f; + + LLVector3 parsed_1(sd); + ensure("1:LLSD parse: Fail ", is_approx_equal(parsed_1.mV[VX], 1.f) && is_approx_equal(parsed_1.mV[VY], 0.f) && is_approx_equal(parsed_1.mV[VZ], 0.f)); + + sd[1] = 2.f; + LLVector3 parsed_2(sd); + ensure("2:LLSD parse: Fail ", is_approx_equal(parsed_2.mV[VX], 1.f) && is_approx_equal(parsed_2.mV[VY], 2.f) && is_approx_equal(parsed_2.mV[VZ], 0.f)); + + sd[2] = 3.f; + LLVector3 parsed_3(sd); + ensure("3:LLSD parse: Fail ", is_approx_equal(parsed_3.mV[VX], 1.f) && is_approx_equal(parsed_3.mV[VY], 2.f) && is_approx_equal(parsed_3.mV[VZ], 3.f)); + } } diff --git a/indra/llmath/tests/v4color_test.cpp b/indra/llmath/tests/v4color_test.cpp index d7eec3c87f..3b3adbda0d 100644 --- a/indra/llmath/tests/v4color_test.cpp +++ b/indra/llmath/tests/v4color_test.cpp @@ -7,21 +7,21 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,322 +38,322 @@ namespace tut { - struct v4color_data - { - }; - typedef test_group<v4color_data> v4color_test; - typedef v4color_test::object v4color_object; - tut::v4color_test v4color_testcase("v4color_h"); - - template<> template<> - void v4color_object::test<1>() - { - LLColor4 llcolor4; - ensure("1:LLColor4:Fail to initialize ", ((0 == llcolor4.mV[VX]) && (0 == llcolor4.mV[VY]) && (0 == llcolor4.mV[VZ])&& (1.0f == llcolor4.mV[VW]))); - - F32 r = 0x20, g = 0xFFFF, b = 0xFF, a = 0xAF; - LLColor4 llcolor4a(r,g,b); - ensure("2:LLColor4:Fail to initialize ", ((r == llcolor4a.mV[VX]) && (g == llcolor4a.mV[VY]) && (b == llcolor4a.mV[VZ])&& (1.0f == llcolor4a.mV[VW]))); - - LLColor4 llcolor4b(r,g,b,a); - ensure("3:LLColor4:Fail to initialize ", ((r == llcolor4b.mV[VX]) && (g == llcolor4b.mV[VY]) && (b == llcolor4b.mV[VZ])&& (a == llcolor4b.mV[VW]))); - - const F32 vec[4] = {.112f ,23.2f, -4.2f, -.0001f}; - LLColor4 llcolor4c(vec); - ensure("4:LLColor4:Fail to initialize ", ((vec[0] == llcolor4c.mV[VX]) && (vec[1] == llcolor4c.mV[VY]) && (vec[2] == llcolor4c.mV[VZ])&& (vec[3] == llcolor4c.mV[VW]))); - - LLColor3 llcolor3(-2.23f,1.01f,42.3f); - F32 val = -.1f; - LLColor4 llcolor4d(llcolor3,val); - ensure("5:LLColor4:Fail to initialize ", ((llcolor3.mV[VX] == llcolor4d.mV[VX]) && (llcolor3.mV[VY] == llcolor4d.mV[VY]) && (llcolor3.mV[VZ] == llcolor4d.mV[VZ])&& (val == llcolor4d.mV[VW]))); - - LLSD sd = llcolor4d.getValue(); - LLColor4 llcolor4e(sd); - ensure_equals("6:LLColor4:(LLSD) failed ", llcolor4d, llcolor4e); - - U8 r1 = 0xF2, g1 = 0xFA, b1 = 0xBF; - LLColor4U color4u(r1,g1,b1); - LLColor4 llcolor4g(color4u); - const F32 SCALE = 1.f/255.f; - F32 r2 = r1*SCALE, g2 = g1* SCALE, b2 = b1* SCALE; - ensure("7:LLColor4:Fail to initialize ", ((r2 == llcolor4g.mV[VX]) && (g2 == llcolor4g.mV[VY]) && (b2 == llcolor4g.mV[VZ]))); - } - - template<> template<> - void v4color_object::test<2>() - { - LLColor4 llcolor(1.0, 2.0, 3.0, 4.0); - LLSD llsd = llcolor.getValue(); - LLColor4 llcolor4(llsd), llcolor4a; - llcolor4a.setValue(llsd); - ensure("setValue: failed", (llcolor4 == llcolor4a)); - LLSD sd = llcolor4a.getValue(); - LLColor4 llcolor4b(sd); - ensure("getValue: Failed ", (llcolor4b == llcolor4a)); - } - - template<> template<> - void v4color_object::test<3>() - { - F32 r = 0x20, g = 0xFFFF, b = 0xFF,a = 0xAF; - LLColor4 llcolor4(r,g,b,a); - llcolor4.setToBlack(); - ensure("setToBlack:Fail to set the black ", ((0 == llcolor4.mV[VX]) && (0 == llcolor4.mV[VY]) && (0 == llcolor4.mV[VZ])&& (1.0f == llcolor4.mV[VW]))); - - llcolor4.setToWhite(); - ensure("setToWhite:Fail to set the white ", ((1.f == llcolor4.mV[VX]) && (1.f == llcolor4.mV[VY]) && (1.f == llcolor4.mV[VZ])&& (1.0f == llcolor4.mV[VW]))); - } - - template<> template<> - void v4color_object::test<4>() - { - F32 r = 0x20, g = 0xFFFF, b = 0xFF, a = 0xAF; - LLColor4 llcolor4; - llcolor4.setVec(r,g,b); - ensure("1:setVec:Fail to set the values ", ((r == llcolor4.mV[VX]) && (g == llcolor4.mV[VY]) && (b == llcolor4.mV[VZ])&& (1.f == llcolor4.mV[VW]))); - - llcolor4.setVec(r,g,b,a); - ensure("2:setVec:Fail to set the values ", ((r == llcolor4.mV[VX]) && (g == llcolor4.mV[VY]) && (b == llcolor4.mV[VZ])&& (a == llcolor4.mV[VW]))); - - LLColor4 llcolor4a; - llcolor4a.setVec(llcolor4); - ensure_equals("3:setVec:Fail to set the values ", llcolor4a,llcolor4); - - LLColor3 llcolor3(-2.23f,1.01f,42.3f); - llcolor4a.setVec(llcolor3); - ensure("4:setVec:Fail to set the values ", ((llcolor3.mV[VX] == llcolor4a.mV[VX]) && (llcolor3.mV[VY] == llcolor4a.mV[VY]) && (llcolor3.mV[VZ] == llcolor4a.mV[VZ]))); - - F32 val = -.33f; - llcolor4a.setVec(llcolor3,val); - ensure("4:setVec:Fail to set the values ", ((llcolor3.mV[VX] == llcolor4a.mV[VX]) && (llcolor3.mV[VY] == llcolor4a.mV[VY]) && (llcolor3.mV[VZ] == llcolor4a.mV[VZ]) && (val == llcolor4a.mV[VW]))); - - const F32 vec[4] = {.112f ,23.2f, -4.2f, -.0001f}; - LLColor4 llcolor4c; - llcolor4c.setVec(vec); - ensure("5:setVec:Fail to initialize ", ((vec[0] == llcolor4c.mV[VX]) && (vec[1] == llcolor4c.mV[VY]) && (vec[2] == llcolor4c.mV[VZ])&& (vec[3] == llcolor4c.mV[VW]))); - - U8 r1 = 0xF2, g1 = 0xFA, b1= 0xBF; - LLColor4U color4u(r1,g1,b1); - llcolor4.setVec(color4u); - const F32 SCALE = 1.f/255.f; - F32 r2 = r1*SCALE, g2 = g1* SCALE, b2 = b1* SCALE; - ensure("6:setVec:Fail to initialize ", ((r2 == llcolor4.mV[VX]) && (g2 == llcolor4.mV[VY]) && (b2 == llcolor4.mV[VZ]))); - } - - template<> template<> - void v4color_object::test<5>() - { - F32 alpha = 0xAF; - LLColor4 llcolor4; - llcolor4.setAlpha(alpha); - ensure("setAlpha:Fail to initialize ", (alpha == llcolor4.mV[VW])); - } - - template<> template<> - void v4color_object::test<6>() - { - F32 r = 0x20, g = 0xFFFF, b = 0xFF; - LLColor4 llcolor4(r,g,b); - ensure("magVecSquared:Fail ", is_approx_equal(llcolor4.magVecSquared(), (r*r + g*g + b*b))); - ensure("magVec:Fail ", is_approx_equal(llcolor4.magVec(), (F32) sqrt(r*r + g*g + b*b))); - } - - template<> template<> - void v4color_object::test<7>() - { - F32 r = 0x20, g = 0xFFFF, b = 0xFF; - LLColor4 llcolor4(r,g,b); - F32 vecMag = llcolor4.normVec(); - F32 mag = (F32) sqrt(r*r + g*g + b*b); - F32 oomag = 1.f / mag; - F32 val1 = r * oomag, val2 = g * oomag, val3 = b * oomag; - ensure("1:normVec failed ", (is_approx_equal(val1, llcolor4.mV[0]) && is_approx_equal(val2, llcolor4.mV[1]) && is_approx_equal(val3, llcolor4.mV[2]) && is_approx_equal(vecMag, mag))); - } - - template<> template<> - void v4color_object::test<8>() - { - LLColor4 llcolor4; - ensure("1:isOpaque failed ",(1 == llcolor4.isOpaque())); - F32 r = 0x20, g = 0xFFFF, b = 0xFF,a = 1.f; - llcolor4.setVec(r,g,b,a); - ensure("2:isOpaque failed ",(1 == llcolor4.isOpaque())); - a = 2.f; - llcolor4.setVec(r,g,b,a); - ensure("3:isOpaque failed ",(0 == llcolor4.isOpaque())); - } - - template<> template<> - void v4color_object::test<9>() - { - F32 r = 0x20, g = 0xFFFF, b = 0xFF; - LLColor4 llcolor4(r,g,b); - ensure("1:operator [] failed",( r == llcolor4[0])); - ensure("2:operator [] failed",( g == llcolor4[1])); - ensure("3:operator [] failed",( b == llcolor4[2])); - - r = 0xA20, g = 0xFBFF, b = 0xFFF; - llcolor4.setVec(r,g,b); - F32 &ref1 = llcolor4[0]; - ensure("4:operator [] failed",( ref1 == llcolor4[0])); - F32 &ref2 = llcolor4[1]; - ensure("5:operator [] failed",( ref2 == llcolor4[1])); - F32 &ref3 = llcolor4[2]; - ensure("6:operator [] failed",( ref3 == llcolor4[2])); - } - - template<> template<> - void v4color_object::test<10>() - { - F32 r = 0x20, g = 0xFFFF, b = 0xFF; - LLColor3 llcolor3(r,g,b); - LLColor4 llcolor4a,llcolor4b; - llcolor4a = llcolor3; - ensure("Operator=:Fail to initialize ", ((llcolor3.mV[0] == llcolor4a.mV[VX]) && (llcolor3.mV[1] == llcolor4a.mV[VY]) && (llcolor3.mV[2] == llcolor4a.mV[VZ]))); - LLSD sd = llcolor4a.getValue(); - llcolor4b = LLColor4(sd); - ensure_equals("Operator= LLSD:Fail ", llcolor4a, llcolor4b); - } - - template<> template<> - void v4color_object::test<11>() - { - F32 r = 0x20, g = 0xFFFF, b = 0xFF; - std::ostringstream stream1, stream2; - LLColor4 llcolor4a(r,g,b),llcolor4b; - stream1 << llcolor4a; - llcolor4b.setVec(r,g,b); - stream2 << llcolor4b; - ensure("operator << failed ", (stream1.str() == stream2.str())); - } - - template<> template<> - void v4color_object::test<12>() - { - F32 r1 = 0x20, g1 = 0xFFFF, b1 = 0xFF; - F32 r2 = 0xABF, g2 = 0xFB, b2 = 0xFFF; - LLColor4 llcolor4a(r1,g1,b1),llcolor4b(r2,g2,b2),llcolor4c; - llcolor4c = llcolor4b + llcolor4a; - ensure("operator+:Fail to Add the values ", (is_approx_equal(r1+r2,llcolor4c.mV[VX]) && is_approx_equal(g1+g2,llcolor4c.mV[VY]) && is_approx_equal(b1+b2,llcolor4c.mV[VZ]))); - - llcolor4b += llcolor4a; - ensure("operator+=:Fail to Add the values ", (is_approx_equal(r1+r2,llcolor4b.mV[VX]) && is_approx_equal(g1+g2,llcolor4b.mV[VY]) && is_approx_equal(b1+b2,llcolor4b.mV[VZ]))); - } - - template<> template<> - void v4color_object::test<13>() - { - F32 r1 = 0x20, g1 = 0xFFFF, b1 = 0xFF; - F32 r2 = 0xABF, g2 = 0xFB, b2 = 0xFFF; - LLColor4 llcolor4a(r1,g1,b1),llcolor4b(r2,g2,b2),llcolor4c; - llcolor4c = llcolor4a - llcolor4b; - ensure("operator-:Fail to subtract the values ", (is_approx_equal(r1-r2,llcolor4c.mV[VX]) && is_approx_equal(g1-g2,llcolor4c.mV[VY]) && is_approx_equal(b1-b2,llcolor4c.mV[VZ]))); - - llcolor4a -= llcolor4b; - ensure("operator-=:Fail to subtract the values ", (is_approx_equal(r1-r2,llcolor4a.mV[VX]) && is_approx_equal(g1-g2,llcolor4a.mV[VY]) && is_approx_equal(b1-b2,llcolor4a.mV[VZ]))); - } - - template<> template<> - void v4color_object::test<14>() - { - F32 r1 = 0x20, g1 = 0xFFFF, b1 = 0xFF; - F32 r2 = 0xABF, g2 = 0xFB, b2 = 0xFFF; - LLColor4 llcolor4a(r1,g1,b1),llcolor4b(r2,g2,b2),llcolor4c; - llcolor4c = llcolor4a * llcolor4b; - ensure("1:operator*:Fail to multiply the values", (is_approx_equal(r1*r2,llcolor4c.mV[VX]) && is_approx_equal(g1*g2,llcolor4c.mV[VY]) && is_approx_equal(b1*b2,llcolor4c.mV[VZ]))); - - F32 mulVal = 3.33f; - llcolor4c = llcolor4a * mulVal; - ensure("2:operator*:Fail ", (is_approx_equal(r1*mulVal,llcolor4c.mV[VX]) && is_approx_equal(g1*mulVal,llcolor4c.mV[VY]) && is_approx_equal(b1*mulVal,llcolor4c.mV[VZ]))); - llcolor4c = mulVal * llcolor4a; - ensure("3:operator*:Fail to multiply the values", (is_approx_equal(r1*mulVal,llcolor4c.mV[VX]) && is_approx_equal(g1*mulVal,llcolor4c.mV[VY]) && is_approx_equal(b1*mulVal,llcolor4c.mV[VZ]))); - - llcolor4a *= mulVal; - ensure("4:operator*=:Fail to multiply the values ", (is_approx_equal(r1*mulVal,llcolor4a.mV[VX]) && is_approx_equal(g1*mulVal,llcolor4a.mV[VY]) && is_approx_equal(b1*mulVal,llcolor4a.mV[VZ]))); - - LLColor4 llcolor4d(r1,g1,b1),llcolor4e(r2,g2,b2); - llcolor4e *= llcolor4d; - ensure("5:operator*=:Fail to multiply the values ", (is_approx_equal(r1*r2,llcolor4e.mV[VX]) && is_approx_equal(g1*g2,llcolor4e.mV[VY]) && is_approx_equal(b1*b2,llcolor4e.mV[VZ]))); - } - - template<> template<> - void v4color_object::test<15>() - { - F32 r = 0x20, g = 0xFFFF, b = 0xFF,a = 0x30; - F32 div = 12.345f; - LLColor4 llcolor4a(r,g,b,a),llcolor4b; - llcolor4b = llcolor4a % div;//chnage only alpha value nor r,g,b; - ensure("1operator%:Fail ", (is_approx_equal(r,llcolor4b.mV[VX]) && is_approx_equal(g,llcolor4b.mV[VY]) && is_approx_equal(b,llcolor4b.mV[VZ])&& is_approx_equal(div*a,llcolor4b.mV[VW]))); - - llcolor4b = div % llcolor4a; - ensure("2operator%:Fail ", (is_approx_equal(r,llcolor4b.mV[VX]) && is_approx_equal(g,llcolor4b.mV[VY]) && is_approx_equal(b,llcolor4b.mV[VZ])&& is_approx_equal(div*a,llcolor4b.mV[VW]))); - - llcolor4a %= div; - ensure("operator%=:Fail ", (is_approx_equal(a*div,llcolor4a.mV[VW]))); - } - - template<> template<> - void v4color_object::test<16>() - { - F32 r = 0x20, g = 0xFFFF, b = 0xFF,a = 0x30; - LLColor4 llcolor4a(r,g,b,a),llcolor4b; - llcolor4b = llcolor4a; - ensure("1:operator== failed to ensure the equality ", (llcolor4b == llcolor4a)); - F32 r1 = 0x2, g1 = 0xFF, b1 = 0xFA; - LLColor3 llcolor3(r1,g1,b1); - llcolor4b = llcolor3; - ensure("2:operator== failed to ensure the equality ", (llcolor4b == llcolor3)); - ensure("2:operator!= failed to ensure the equality ", (llcolor4a != llcolor3)); - } - - template<> template<> - void v4color_object::test<17>() - { - F32 r = 0x20, g = 0xFFFF, b = 0xFF; - LLColor4 llcolor4a(r,g,b),llcolor4b; - LLColor3 llcolor3 = vec4to3(llcolor4a); - ensure("vec4to3:Fail to convert vec4 to vec3 ", (is_approx_equal(llcolor3.mV[VX],llcolor4a.mV[VX]) && is_approx_equal(llcolor3.mV[VY],llcolor4a.mV[VY]) && is_approx_equal(llcolor3.mV[VZ],llcolor4a.mV[VZ]))); - llcolor4b = vec3to4(llcolor3); - ensure_equals("vec3to4:Fail to convert vec3 to vec4 ", llcolor4b, llcolor4a); - } - - template<> template<> - void v4color_object::test<18>() - { - F32 r1 = 0x20, g1 = 0xFFFF, b1 = 0xFF, val = 0x20; - F32 r2 = 0xABF, g2 = 0xFB, b2 = 0xFFF; - LLColor4 llcolor4a(r1,g1,b1),llcolor4b(r2,g2,b2),llcolor4c; - llcolor4c = lerp(llcolor4a,llcolor4b,val); - ensure("lerp:Fail ", (is_approx_equal(r1 + (r2 - r1)* val,llcolor4c.mV[VX]) && is_approx_equal(g1 + (g2 - g1)* val,llcolor4c.mV[VY]) && is_approx_equal(b1 + (b2 - b1)* val,llcolor4c.mV[VZ]))); - } - - template<> template<> - void v4color_object::test<19>() - { - F32 r = 12.0f, g = -2.3f, b = 1.32f, a = 5.0f; - LLColor4 llcolor4a(r,g,b,a),llcolor4b; - std::string color("red"); - LLColor4::parseColor(color, &llcolor4b); - ensure_equals("1:parseColor() failed to parse the color value ", llcolor4b, LLColor4::red); - - color = "12.0, -2.3, 1.32, 5.0"; - LLColor4::parseColor(color, &llcolor4b); - llcolor4a = llcolor4a * (1.f / 255.f); - ensure_equals("2:parseColor() failed to parse the color value ", llcolor4a,llcolor4b); - - color = "yellow5"; - llcolor4a.setVec(r,g,b); - LLColor4::parseColor(color, &llcolor4a); - ensure_equals("3:parseColor() failed to parse the color value ", llcolor4a, LLColor4::yellow5); - } - - template<> template<> - void v4color_object::test<20>() - { - F32 r = 12.0f, g = -2.3f, b = 1.32f, a = 5.0f; - LLColor4 llcolor4a(r,g,b,a),llcolor4b; - std::string color("12.0, -2.3, 1.32, 5.0"); - LLColor4::parseColor4(color, &llcolor4b); - ensure_equals("parseColor4() failed to parse the color value ", llcolor4a, llcolor4b); - } + struct v4color_data + { + }; + typedef test_group<v4color_data> v4color_test; + typedef v4color_test::object v4color_object; + tut::v4color_test v4color_testcase("v4color_h"); + + template<> template<> + void v4color_object::test<1>() + { + LLColor4 llcolor4; + ensure("1:LLColor4:Fail to initialize ", ((0 == llcolor4.mV[VX]) && (0 == llcolor4.mV[VY]) && (0 == llcolor4.mV[VZ])&& (1.0f == llcolor4.mV[VW]))); + + F32 r = 0x20, g = 0xFFFF, b = 0xFF, a = 0xAF; + LLColor4 llcolor4a(r,g,b); + ensure("2:LLColor4:Fail to initialize ", ((r == llcolor4a.mV[VX]) && (g == llcolor4a.mV[VY]) && (b == llcolor4a.mV[VZ])&& (1.0f == llcolor4a.mV[VW]))); + + LLColor4 llcolor4b(r,g,b,a); + ensure("3:LLColor4:Fail to initialize ", ((r == llcolor4b.mV[VX]) && (g == llcolor4b.mV[VY]) && (b == llcolor4b.mV[VZ])&& (a == llcolor4b.mV[VW]))); + + const F32 vec[4] = {.112f ,23.2f, -4.2f, -.0001f}; + LLColor4 llcolor4c(vec); + ensure("4:LLColor4:Fail to initialize ", ((vec[0] == llcolor4c.mV[VX]) && (vec[1] == llcolor4c.mV[VY]) && (vec[2] == llcolor4c.mV[VZ])&& (vec[3] == llcolor4c.mV[VW]))); + + LLColor3 llcolor3(-2.23f,1.01f,42.3f); + F32 val = -.1f; + LLColor4 llcolor4d(llcolor3,val); + ensure("5:LLColor4:Fail to initialize ", ((llcolor3.mV[VX] == llcolor4d.mV[VX]) && (llcolor3.mV[VY] == llcolor4d.mV[VY]) && (llcolor3.mV[VZ] == llcolor4d.mV[VZ])&& (val == llcolor4d.mV[VW]))); + + LLSD sd = llcolor4d.getValue(); + LLColor4 llcolor4e(sd); + ensure_equals("6:LLColor4:(LLSD) failed ", llcolor4d, llcolor4e); + + U8 r1 = 0xF2, g1 = 0xFA, b1 = 0xBF; + LLColor4U color4u(r1,g1,b1); + LLColor4 llcolor4g(color4u); + const F32 SCALE = 1.f/255.f; + F32 r2 = r1*SCALE, g2 = g1* SCALE, b2 = b1* SCALE; + ensure("7:LLColor4:Fail to initialize ", ((r2 == llcolor4g.mV[VX]) && (g2 == llcolor4g.mV[VY]) && (b2 == llcolor4g.mV[VZ]))); + } + + template<> template<> + void v4color_object::test<2>() + { + LLColor4 llcolor(1.0, 2.0, 3.0, 4.0); + LLSD llsd = llcolor.getValue(); + LLColor4 llcolor4(llsd), llcolor4a; + llcolor4a.setValue(llsd); + ensure("setValue: failed", (llcolor4 == llcolor4a)); + LLSD sd = llcolor4a.getValue(); + LLColor4 llcolor4b(sd); + ensure("getValue: Failed ", (llcolor4b == llcolor4a)); + } + + template<> template<> + void v4color_object::test<3>() + { + F32 r = 0x20, g = 0xFFFF, b = 0xFF,a = 0xAF; + LLColor4 llcolor4(r,g,b,a); + llcolor4.setToBlack(); + ensure("setToBlack:Fail to set the black ", ((0 == llcolor4.mV[VX]) && (0 == llcolor4.mV[VY]) && (0 == llcolor4.mV[VZ])&& (1.0f == llcolor4.mV[VW]))); + + llcolor4.setToWhite(); + ensure("setToWhite:Fail to set the white ", ((1.f == llcolor4.mV[VX]) && (1.f == llcolor4.mV[VY]) && (1.f == llcolor4.mV[VZ])&& (1.0f == llcolor4.mV[VW]))); + } + + template<> template<> + void v4color_object::test<4>() + { + F32 r = 0x20, g = 0xFFFF, b = 0xFF, a = 0xAF; + LLColor4 llcolor4; + llcolor4.setVec(r,g,b); + ensure("1:setVec:Fail to set the values ", ((r == llcolor4.mV[VX]) && (g == llcolor4.mV[VY]) && (b == llcolor4.mV[VZ])&& (1.f == llcolor4.mV[VW]))); + + llcolor4.setVec(r,g,b,a); + ensure("2:setVec:Fail to set the values ", ((r == llcolor4.mV[VX]) && (g == llcolor4.mV[VY]) && (b == llcolor4.mV[VZ])&& (a == llcolor4.mV[VW]))); + + LLColor4 llcolor4a; + llcolor4a.setVec(llcolor4); + ensure_equals("3:setVec:Fail to set the values ", llcolor4a,llcolor4); + + LLColor3 llcolor3(-2.23f,1.01f,42.3f); + llcolor4a.setVec(llcolor3); + ensure("4:setVec:Fail to set the values ", ((llcolor3.mV[VX] == llcolor4a.mV[VX]) && (llcolor3.mV[VY] == llcolor4a.mV[VY]) && (llcolor3.mV[VZ] == llcolor4a.mV[VZ]))); + + F32 val = -.33f; + llcolor4a.setVec(llcolor3,val); + ensure("4:setVec:Fail to set the values ", ((llcolor3.mV[VX] == llcolor4a.mV[VX]) && (llcolor3.mV[VY] == llcolor4a.mV[VY]) && (llcolor3.mV[VZ] == llcolor4a.mV[VZ]) && (val == llcolor4a.mV[VW]))); + + const F32 vec[4] = {.112f ,23.2f, -4.2f, -.0001f}; + LLColor4 llcolor4c; + llcolor4c.setVec(vec); + ensure("5:setVec:Fail to initialize ", ((vec[0] == llcolor4c.mV[VX]) && (vec[1] == llcolor4c.mV[VY]) && (vec[2] == llcolor4c.mV[VZ])&& (vec[3] == llcolor4c.mV[VW]))); + + U8 r1 = 0xF2, g1 = 0xFA, b1= 0xBF; + LLColor4U color4u(r1,g1,b1); + llcolor4.setVec(color4u); + const F32 SCALE = 1.f/255.f; + F32 r2 = r1*SCALE, g2 = g1* SCALE, b2 = b1* SCALE; + ensure("6:setVec:Fail to initialize ", ((r2 == llcolor4.mV[VX]) && (g2 == llcolor4.mV[VY]) && (b2 == llcolor4.mV[VZ]))); + } + + template<> template<> + void v4color_object::test<5>() + { + F32 alpha = 0xAF; + LLColor4 llcolor4; + llcolor4.setAlpha(alpha); + ensure("setAlpha:Fail to initialize ", (alpha == llcolor4.mV[VW])); + } + + template<> template<> + void v4color_object::test<6>() + { + F32 r = 0x20, g = 0xFFFF, b = 0xFF; + LLColor4 llcolor4(r,g,b); + ensure("magVecSquared:Fail ", is_approx_equal(llcolor4.magVecSquared(), (r*r + g*g + b*b))); + ensure("magVec:Fail ", is_approx_equal(llcolor4.magVec(), (F32) sqrt(r*r + g*g + b*b))); + } + + template<> template<> + void v4color_object::test<7>() + { + F32 r = 0x20, g = 0xFFFF, b = 0xFF; + LLColor4 llcolor4(r,g,b); + F32 vecMag = llcolor4.normVec(); + F32 mag = (F32) sqrt(r*r + g*g + b*b); + F32 oomag = 1.f / mag; + F32 val1 = r * oomag, val2 = g * oomag, val3 = b * oomag; + ensure("1:normVec failed ", (is_approx_equal(val1, llcolor4.mV[0]) && is_approx_equal(val2, llcolor4.mV[1]) && is_approx_equal(val3, llcolor4.mV[2]) && is_approx_equal(vecMag, mag))); + } + + template<> template<> + void v4color_object::test<8>() + { + LLColor4 llcolor4; + ensure("1:isOpaque failed ",(1 == llcolor4.isOpaque())); + F32 r = 0x20, g = 0xFFFF, b = 0xFF,a = 1.f; + llcolor4.setVec(r,g,b,a); + ensure("2:isOpaque failed ",(1 == llcolor4.isOpaque())); + a = 2.f; + llcolor4.setVec(r,g,b,a); + ensure("3:isOpaque failed ",(0 == llcolor4.isOpaque())); + } + + template<> template<> + void v4color_object::test<9>() + { + F32 r = 0x20, g = 0xFFFF, b = 0xFF; + LLColor4 llcolor4(r,g,b); + ensure("1:operator [] failed",( r == llcolor4[0])); + ensure("2:operator [] failed",( g == llcolor4[1])); + ensure("3:operator [] failed",( b == llcolor4[2])); + + r = 0xA20, g = 0xFBFF, b = 0xFFF; + llcolor4.setVec(r,g,b); + F32 &ref1 = llcolor4[0]; + ensure("4:operator [] failed",( ref1 == llcolor4[0])); + F32 &ref2 = llcolor4[1]; + ensure("5:operator [] failed",( ref2 == llcolor4[1])); + F32 &ref3 = llcolor4[2]; + ensure("6:operator [] failed",( ref3 == llcolor4[2])); + } + + template<> template<> + void v4color_object::test<10>() + { + F32 r = 0x20, g = 0xFFFF, b = 0xFF; + LLColor3 llcolor3(r,g,b); + LLColor4 llcolor4a,llcolor4b; + llcolor4a = llcolor3; + ensure("Operator=:Fail to initialize ", ((llcolor3.mV[0] == llcolor4a.mV[VX]) && (llcolor3.mV[1] == llcolor4a.mV[VY]) && (llcolor3.mV[2] == llcolor4a.mV[VZ]))); + LLSD sd = llcolor4a.getValue(); + llcolor4b = LLColor4(sd); + ensure_equals("Operator= LLSD:Fail ", llcolor4a, llcolor4b); + } + + template<> template<> + void v4color_object::test<11>() + { + F32 r = 0x20, g = 0xFFFF, b = 0xFF; + std::ostringstream stream1, stream2; + LLColor4 llcolor4a(r,g,b),llcolor4b; + stream1 << llcolor4a; + llcolor4b.setVec(r,g,b); + stream2 << llcolor4b; + ensure("operator << failed ", (stream1.str() == stream2.str())); + } + + template<> template<> + void v4color_object::test<12>() + { + F32 r1 = 0x20, g1 = 0xFFFF, b1 = 0xFF; + F32 r2 = 0xABF, g2 = 0xFB, b2 = 0xFFF; + LLColor4 llcolor4a(r1,g1,b1),llcolor4b(r2,g2,b2),llcolor4c; + llcolor4c = llcolor4b + llcolor4a; + ensure("operator+:Fail to Add the values ", (is_approx_equal(r1+r2,llcolor4c.mV[VX]) && is_approx_equal(g1+g2,llcolor4c.mV[VY]) && is_approx_equal(b1+b2,llcolor4c.mV[VZ]))); + + llcolor4b += llcolor4a; + ensure("operator+=:Fail to Add the values ", (is_approx_equal(r1+r2,llcolor4b.mV[VX]) && is_approx_equal(g1+g2,llcolor4b.mV[VY]) && is_approx_equal(b1+b2,llcolor4b.mV[VZ]))); + } + + template<> template<> + void v4color_object::test<13>() + { + F32 r1 = 0x20, g1 = 0xFFFF, b1 = 0xFF; + F32 r2 = 0xABF, g2 = 0xFB, b2 = 0xFFF; + LLColor4 llcolor4a(r1,g1,b1),llcolor4b(r2,g2,b2),llcolor4c; + llcolor4c = llcolor4a - llcolor4b; + ensure("operator-:Fail to subtract the values ", (is_approx_equal(r1-r2,llcolor4c.mV[VX]) && is_approx_equal(g1-g2,llcolor4c.mV[VY]) && is_approx_equal(b1-b2,llcolor4c.mV[VZ]))); + + llcolor4a -= llcolor4b; + ensure("operator-=:Fail to subtract the values ", (is_approx_equal(r1-r2,llcolor4a.mV[VX]) && is_approx_equal(g1-g2,llcolor4a.mV[VY]) && is_approx_equal(b1-b2,llcolor4a.mV[VZ]))); + } + + template<> template<> + void v4color_object::test<14>() + { + F32 r1 = 0x20, g1 = 0xFFFF, b1 = 0xFF; + F32 r2 = 0xABF, g2 = 0xFB, b2 = 0xFFF; + LLColor4 llcolor4a(r1,g1,b1),llcolor4b(r2,g2,b2),llcolor4c; + llcolor4c = llcolor4a * llcolor4b; + ensure("1:operator*:Fail to multiply the values", (is_approx_equal(r1*r2,llcolor4c.mV[VX]) && is_approx_equal(g1*g2,llcolor4c.mV[VY]) && is_approx_equal(b1*b2,llcolor4c.mV[VZ]))); + + F32 mulVal = 3.33f; + llcolor4c = llcolor4a * mulVal; + ensure("2:operator*:Fail ", (is_approx_equal(r1*mulVal,llcolor4c.mV[VX]) && is_approx_equal(g1*mulVal,llcolor4c.mV[VY]) && is_approx_equal(b1*mulVal,llcolor4c.mV[VZ]))); + llcolor4c = mulVal * llcolor4a; + ensure("3:operator*:Fail to multiply the values", (is_approx_equal(r1*mulVal,llcolor4c.mV[VX]) && is_approx_equal(g1*mulVal,llcolor4c.mV[VY]) && is_approx_equal(b1*mulVal,llcolor4c.mV[VZ]))); + + llcolor4a *= mulVal; + ensure("4:operator*=:Fail to multiply the values ", (is_approx_equal(r1*mulVal,llcolor4a.mV[VX]) && is_approx_equal(g1*mulVal,llcolor4a.mV[VY]) && is_approx_equal(b1*mulVal,llcolor4a.mV[VZ]))); + + LLColor4 llcolor4d(r1,g1,b1),llcolor4e(r2,g2,b2); + llcolor4e *= llcolor4d; + ensure("5:operator*=:Fail to multiply the values ", (is_approx_equal(r1*r2,llcolor4e.mV[VX]) && is_approx_equal(g1*g2,llcolor4e.mV[VY]) && is_approx_equal(b1*b2,llcolor4e.mV[VZ]))); + } + + template<> template<> + void v4color_object::test<15>() + { + F32 r = 0x20, g = 0xFFFF, b = 0xFF,a = 0x30; + F32 div = 12.345f; + LLColor4 llcolor4a(r,g,b,a),llcolor4b; + llcolor4b = llcolor4a % div;//chnage only alpha value nor r,g,b; + ensure("1operator%:Fail ", (is_approx_equal(r,llcolor4b.mV[VX]) && is_approx_equal(g,llcolor4b.mV[VY]) && is_approx_equal(b,llcolor4b.mV[VZ])&& is_approx_equal(div*a,llcolor4b.mV[VW]))); + + llcolor4b = div % llcolor4a; + ensure("2operator%:Fail ", (is_approx_equal(r,llcolor4b.mV[VX]) && is_approx_equal(g,llcolor4b.mV[VY]) && is_approx_equal(b,llcolor4b.mV[VZ])&& is_approx_equal(div*a,llcolor4b.mV[VW]))); + + llcolor4a %= div; + ensure("operator%=:Fail ", (is_approx_equal(a*div,llcolor4a.mV[VW]))); + } + + template<> template<> + void v4color_object::test<16>() + { + F32 r = 0x20, g = 0xFFFF, b = 0xFF,a = 0x30; + LLColor4 llcolor4a(r,g,b,a),llcolor4b; + llcolor4b = llcolor4a; + ensure("1:operator== failed to ensure the equality ", (llcolor4b == llcolor4a)); + F32 r1 = 0x2, g1 = 0xFF, b1 = 0xFA; + LLColor3 llcolor3(r1,g1,b1); + llcolor4b = llcolor3; + ensure("2:operator== failed to ensure the equality ", (llcolor4b == llcolor3)); + ensure("2:operator!= failed to ensure the equality ", (llcolor4a != llcolor3)); + } + + template<> template<> + void v4color_object::test<17>() + { + F32 r = 0x20, g = 0xFFFF, b = 0xFF; + LLColor4 llcolor4a(r,g,b),llcolor4b; + LLColor3 llcolor3 = vec4to3(llcolor4a); + ensure("vec4to3:Fail to convert vec4 to vec3 ", (is_approx_equal(llcolor3.mV[VX],llcolor4a.mV[VX]) && is_approx_equal(llcolor3.mV[VY],llcolor4a.mV[VY]) && is_approx_equal(llcolor3.mV[VZ],llcolor4a.mV[VZ]))); + llcolor4b = vec3to4(llcolor3); + ensure_equals("vec3to4:Fail to convert vec3 to vec4 ", llcolor4b, llcolor4a); + } + + template<> template<> + void v4color_object::test<18>() + { + F32 r1 = 0x20, g1 = 0xFFFF, b1 = 0xFF, val = 0x20; + F32 r2 = 0xABF, g2 = 0xFB, b2 = 0xFFF; + LLColor4 llcolor4a(r1,g1,b1),llcolor4b(r2,g2,b2),llcolor4c; + llcolor4c = lerp(llcolor4a,llcolor4b,val); + ensure("lerp:Fail ", (is_approx_equal(r1 + (r2 - r1)* val,llcolor4c.mV[VX]) && is_approx_equal(g1 + (g2 - g1)* val,llcolor4c.mV[VY]) && is_approx_equal(b1 + (b2 - b1)* val,llcolor4c.mV[VZ]))); + } + + template<> template<> + void v4color_object::test<19>() + { + F32 r = 12.0f, g = -2.3f, b = 1.32f, a = 5.0f; + LLColor4 llcolor4a(r,g,b,a),llcolor4b; + std::string color("red"); + LLColor4::parseColor(color, &llcolor4b); + ensure_equals("1:parseColor() failed to parse the color value ", llcolor4b, LLColor4::red); + + color = "12.0, -2.3, 1.32, 5.0"; + LLColor4::parseColor(color, &llcolor4b); + llcolor4a = llcolor4a * (1.f / 255.f); + ensure_equals("2:parseColor() failed to parse the color value ", llcolor4a,llcolor4b); + + color = "yellow5"; + llcolor4a.setVec(r,g,b); + LLColor4::parseColor(color, &llcolor4a); + ensure_equals("3:parseColor() failed to parse the color value ", llcolor4a, LLColor4::yellow5); + } + + template<> template<> + void v4color_object::test<20>() + { + F32 r = 12.0f, g = -2.3f, b = 1.32f, a = 5.0f; + LLColor4 llcolor4a(r,g,b,a),llcolor4b; + std::string color("12.0, -2.3, 1.32, 5.0"); + LLColor4::parseColor4(color, &llcolor4b); + ensure_equals("parseColor4() failed to parse the color value ", llcolor4a, llcolor4b); + } } diff --git a/indra/llmath/tests/v4coloru_test.cpp b/indra/llmath/tests/v4coloru_test.cpp index 1d3aa4c63d..55cef0fea1 100644 --- a/indra/llmath/tests/v4coloru_test.cpp +++ b/indra/llmath/tests/v4coloru_test.cpp @@ -7,21 +7,21 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -37,300 +37,300 @@ namespace tut { - struct v4coloru_data - { - }; - typedef test_group<v4coloru_data> v4coloru_test; - typedef v4coloru_test::object v4coloru_object; - tut::v4coloru_test v4coloru_testcase("v4coloru_h"); - - template<> template<> - void v4coloru_object::test<1>() - { - LLColor4U llcolor4u; - ensure("1:LLColor4u:Fail to initialize ", ((0 == llcolor4u.mV[VX]) && (0 == llcolor4u.mV[VY]) && (0 == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW]))); - - U8 r = 0x12, g = 0xFF, b = 0xAF, a = 0x23; - LLColor4U llcolor4u1(r,g,b); - ensure("2:LLColor4u:Fail to initialize ", ((r == llcolor4u1.mV[VX]) && (g == llcolor4u1.mV[VY]) && (b == llcolor4u1.mV[VZ])&& (255 == llcolor4u1.mV[VW]))); - - LLColor4U llcolor4u2(r,g,b,a); - ensure("3:LLColor4u:Fail to initialize ", ((r == llcolor4u2.mV[VX]) && (g == llcolor4u2.mV[VY]) && (b == llcolor4u2.mV[VZ])&& (a == llcolor4u2.mV[VW]))); - - const U8 vec[4] = {0x12,0xFF,0xAF,0x23}; - LLColor4U llcolor4u3(vec); - ensure("4:LLColor4u:Fail to initialize ", ((vec[0] == llcolor4u3.mV[VX]) && (vec[1] == llcolor4u3.mV[VY]) && (vec[2] == llcolor4u3.mV[VZ])&& (vec[3] == llcolor4u3.mV[VW]))); - - LLSD sd = llcolor4u3.getValue(); - LLColor4U llcolor4u4(sd); - ensure_equals("5:LLColor4u (LLSD) Failed ", llcolor4u4, llcolor4u3); - } - - template<> template<> - void v4coloru_object::test<2>() - { - LLColor4U llcolor4ua(1, 2, 3, 4); - LLSD sd = llcolor4ua.getValue(); - LLColor4U llcolor4u; - llcolor4u.setValue(sd); - ensure_equals("setValue(LLSD)/getValue Failed ", llcolor4u, llcolor4ua); - } - - template<> template<> - void v4coloru_object::test<3>() - { - U8 r = 0x12, g = 0xFF, b = 0xAF, a = 0x23; - LLColor4U llcolor4u(r,g,b,a); - llcolor4u.setToBlack(); - ensure("setToBlack:Fail to set black ", ((0 == llcolor4u.mV[VX]) && (0 == llcolor4u.mV[VY]) && (0 == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW]))); - - llcolor4u.setToWhite(); - ensure("setToWhite:Fail to white ", ((255 == llcolor4u.mV[VX]) && (255 == llcolor4u.mV[VY]) && (255 == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW]))); - } - - template<> template<> - void v4coloru_object::test<4>() - { - U8 r = 0x12, g = 0xFF, b = 0xAF, a = 0x23; - LLColor4U llcolor4ua(r,g,b,a); - LLSD sd = llcolor4ua.getValue(); - LLColor4U llcolor4u = (LLColor4U)sd; - ensure_equals("Operator=(LLSD) Failed ", llcolor4u, llcolor4ua); - } - - template<> template<> - void v4coloru_object::test<5>() - { - U8 r = 0x12, g = 0xFF, b = 0xAF, a = 0x23; - LLColor4U llcolor4u; - llcolor4u.setVec(r,g,b,a); - ensure("1:setVec:Fail to set the values ", ((r == llcolor4u.mV[VX]) && (g == llcolor4u.mV[VY]) && (b == llcolor4u.mV[VZ])&& (a == llcolor4u.mV[VW]))); - - llcolor4u.setToBlack(); - llcolor4u.setVec(r,g,b); - ensure("2:setVec:Fail to set the values ", ((r == llcolor4u.mV[VX]) && (g == llcolor4u.mV[VY]) && (b == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW]))); - - LLColor4U llcolor4u1; - llcolor4u1.setVec(llcolor4u); - ensure_equals("3:setVec:Fail to set the values ", llcolor4u1,llcolor4u); - - const U8 vec[4] = {0x12,0xFF,0xAF,0x23}; - LLColor4U llcolor4u2; - llcolor4u2.setVec(vec); - ensure("4:setVec:Fail to set the values ", ((vec[0] == llcolor4u2.mV[VX]) && (vec[1] == llcolor4u2.mV[VY]) && (vec[2] == llcolor4u2.mV[VZ])&& (vec[3] == llcolor4u2.mV[VW]))); - } - - template<> template<> - void v4coloru_object::test<6>() - { - U8 alpha = 0x12; - LLColor4U llcolor4u; - llcolor4u.setAlpha(alpha); - ensure("setAlpha:Fail to set alpha value ", (alpha == llcolor4u.mV[VW])); - } - - template<> template<> - void v4coloru_object::test<7>() - { - U8 r = 0x12, g = 0xFF, b = 0xAF; - LLColor4U llcolor4u(r,g,b); - ensure("magVecSquared:Fail ", is_approx_equal(llcolor4u.magVecSquared(), (F32)(r*r + g*g + b*b))); - ensure("magVec:Fail ", is_approx_equal(llcolor4u.magVec(), (F32) sqrt((F32) (r*r + g*g + b*b)))); - } - - template<> template<> - void v4coloru_object::test<8>() - { - U8 r = 0x12, g = 0xFF, b = 0xAF; - std::ostringstream stream1, stream2; - LLColor4U llcolor4u1(r,g,b),llcolor4u2; - stream1 << llcolor4u1; - llcolor4u2.setVec(r,g,b); - stream2 << llcolor4u2; - ensure("operator << failed ", (stream1.str() == stream2.str())); - } - - template<> template<> - void v4coloru_object::test<9>() - { - U8 r1 = 0x12, g1 = 0xFF, b1 = 0xAF; - U8 r2 = 0x1C, g2 = 0x9A, b2 = 0x1B; - LLColor4U llcolor4u1(r1,g1,b1), llcolor4u2(r2,g2,b2),llcolor4u3; - llcolor4u3 = llcolor4u1 + llcolor4u2; - ensure_equals( - "1a.operator+:Fail to Add the values ", - llcolor4u3.mV[VX], - (U8)(r1+r2)); - ensure_equals( - "1b.operator+:Fail to Add the values ", - llcolor4u3.mV[VY], - (U8)(g1+g2)); - ensure_equals( - "1c.operator+:Fail to Add the values ", - llcolor4u3.mV[VZ], - (U8)(b1+b2)); - - llcolor4u2 += llcolor4u1; - ensure_equals( - "2a.operator+=:Fail to Add the values ", - llcolor4u2.mV[VX], - (U8)(r1+r2)); - ensure_equals( - "2b.operator+=:Fail to Add the values ", - llcolor4u2.mV[VY], - (U8)(g1+g2)); - ensure_equals( - "2c.operator+=:Fail to Add the values ", - llcolor4u2.mV[VZ], - (U8)(b1+b2)); - } - - template<> template<> - void v4coloru_object::test<10>() - { - U8 r1 = 0x12, g1 = 0xFF, b1 = 0xAF; - U8 r2 = 0x1C, g2 = 0x9A, b2 = 0x1B; - LLColor4U llcolor4u1(r1,g1,b1), llcolor4u2(r2,g2,b2),llcolor4u3; - llcolor4u3 = llcolor4u1 - llcolor4u2; - ensure_equals( - "1a. operator-:Fail to Add the values ", - llcolor4u3.mV[VX], - (U8)(r1-r2)); - ensure_equals( - "1b. operator-:Fail to Add the values ", - llcolor4u3.mV[VY], - (U8)(g1-g2)); - ensure_equals( - "1c. operator-:Fail to Add the values ", - llcolor4u3.mV[VZ], - (U8)(b1-b2)); - - llcolor4u1 -= llcolor4u2; - ensure_equals( - "2a. operator-=:Fail to Add the values ", - llcolor4u1.mV[VX], - (U8)(r1-r2)); - ensure_equals( - "2b. operator-=:Fail to Add the values ", - llcolor4u1.mV[VY], - (U8)(g1-g2)); - ensure_equals( - "2c. operator-=:Fail to Add the values ", - llcolor4u1.mV[VZ], - (U8)(b1-b2)); - } - - template<> template<> - void v4coloru_object::test<11>() - { - U8 r1 = 0x12, g1 = 0xFF, b1 = 0xAF; - U8 r2 = 0x1C, g2 = 0x9A, b2 = 0x1B; - LLColor4U llcolor4u1(r1,g1,b1), llcolor4u2(r2,g2,b2),llcolor4u3; - llcolor4u3 = llcolor4u1 * llcolor4u2; - ensure_equals( - "1a. operator*:Fail to multiply the values", - llcolor4u3.mV[VX], - (U8)(r1*r2)); - ensure_equals( - "1b. operator*:Fail to multiply the values", - llcolor4u3.mV[VY], - (U8)(g1*g2)); - ensure_equals( - "1c. operator*:Fail to multiply the values", - llcolor4u3.mV[VZ], - (U8)(b1*b2)); - - U8 mulVal = 123; - llcolor4u1 *= mulVal; - ensure_equals( - "2a. operator*=:Fail to multiply the values", - llcolor4u1.mV[VX], - (U8)(r1*mulVal)); - ensure_equals( - "2b. operator*=:Fail to multiply the values", - llcolor4u1.mV[VY], - (U8)(g1*mulVal)); - ensure_equals( - "2c. operator*=:Fail to multiply the values", - llcolor4u1.mV[VZ], - (U8)(b1*mulVal)); - } - - template<> template<> - void v4coloru_object::test<12>() - { - U8 r = 0x12, g = 0xFF, b = 0xAF; - LLColor4U llcolor4u(r,g,b),llcolor4u1; - llcolor4u1 = llcolor4u; - ensure("operator== failed to ensure the equality ", (llcolor4u1 == llcolor4u)); - llcolor4u1.setToBlack(); - ensure("operator!= failed to ensure the equality ", (llcolor4u1 != llcolor4u)); - } - - template<> template<> - void v4coloru_object::test<13>() - { - U8 r = 0x12, g = 0xFF, b = 0xAF, a = 12; - LLColor4U llcolor4u(r,g,b,a); - U8 modVal = 45; - llcolor4u %= modVal; - ensure_equals("operator%=:Fail ", llcolor4u.mV[VW], (U8)(a * modVal)); - } - - template<> template<> - void v4coloru_object::test<14>() - { - U8 r = 0x12, g = 0xFF, b = 0xAF, a = 12; - LLColor4U llcolor4u1(r,g,b,a); - std::string color("12, 23, 132, 50"); - LLColor4U::parseColor4U(color, &llcolor4u1); - ensure("parseColor4U() failed to parse the color value ", ((12 == llcolor4u1.mV[VX]) && (23 == llcolor4u1.mV[VY]) && (132 == llcolor4u1.mV[VZ])&& (50 == llcolor4u1.mV[VW]))); - - color = "12, 23, 132"; - ensure("2:parseColor4U() failed to parse the color value ", (false == LLColor4U::parseColor4U(color, &llcolor4u1))); - - color = "12"; - ensure("2:parseColor4U() failed to parse the color value ", (false == LLColor4U::parseColor4U(color, &llcolor4u1))); - } - - template<> template<> - void v4coloru_object::test<15>() - { - U8 r = 12, g = 123, b = 3, a = 2; - LLColor4U llcolor4u(r,g,b,a),llcolor4u1; - const F32 fVal = 3.f; - llcolor4u1 = llcolor4u.multAll(fVal); - ensure("multAll:Fail to multiply ", (((U8)ll_round(r * fVal) == llcolor4u1.mV[VX]) && (U8)ll_round(g * fVal) == llcolor4u1.mV[VY] - && ((U8)ll_round(b * fVal) == llcolor4u1.mV[VZ])&& ((U8)ll_round(a * fVal) == llcolor4u1.mV[VW]))); - } - - template<> template<> - void v4coloru_object::test<16>() - { - U8 r1 = 12, g1 = 123, b1 = 3, a1 = 2; - U8 r2 = 23, g2 = 230, b2 = 124, a2 = 255; - LLColor4U llcolor4u(r1,g1,b1,a1),llcolor4u1(r2,g2,b2,a2); - llcolor4u1 = llcolor4u1.addClampMax(llcolor4u); - ensure("1:addClampMax():Fail to add the value ", ((r1+r2 == llcolor4u1.mV[VX]) && (255 == llcolor4u1.mV[VY]) && (b1+b2 == llcolor4u1.mV[VZ])&& (255 == llcolor4u1.mV[VW]))); - - r1 = 132, g1 = 3, b1 = 3, a1 = 2; - r2 = 123, g2 = 230, b2 = 154, a2 = 25; - LLColor4U llcolor4u2(r1,g1,b1,a1),llcolor4u3(r2,g2,b2,a2); - llcolor4u3 = llcolor4u3.addClampMax(llcolor4u2); - ensure("2:addClampMax():Fail to add the value ", ((255 == llcolor4u3.mV[VX]) && (g1+g2 == llcolor4u3.mV[VY]) && (b1+b2 == llcolor4u3.mV[VZ])&& (a1+a2 == llcolor4u3.mV[VW]))); - } - - template<> template<> - void v4coloru_object::test<17>() - { - F32 r = 23.f, g = 12.32f, b = -12.3f; - LLColor3 color3(r,g,b); - LLColor4U llcolor4u; - llcolor4u.setVecScaleClamp(color3); - const S32 MAX_COLOR = 255; - F32 color_scale_factor = MAX_COLOR/r; - S32 r2 = ll_round(r * color_scale_factor); - S32 g2 = ll_round(g * color_scale_factor); - ensure("setVecScaleClamp():Fail to add the value ", ((r2 == llcolor4u.mV[VX]) && (g2 == llcolor4u.mV[VY]) && (0 == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW]))); - } + struct v4coloru_data + { + }; + typedef test_group<v4coloru_data> v4coloru_test; + typedef v4coloru_test::object v4coloru_object; + tut::v4coloru_test v4coloru_testcase("v4coloru_h"); + + template<> template<> + void v4coloru_object::test<1>() + { + LLColor4U llcolor4u; + ensure("1:LLColor4u:Fail to initialize ", ((0 == llcolor4u.mV[VX]) && (0 == llcolor4u.mV[VY]) && (0 == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW]))); + + U8 r = 0x12, g = 0xFF, b = 0xAF, a = 0x23; + LLColor4U llcolor4u1(r,g,b); + ensure("2:LLColor4u:Fail to initialize ", ((r == llcolor4u1.mV[VX]) && (g == llcolor4u1.mV[VY]) && (b == llcolor4u1.mV[VZ])&& (255 == llcolor4u1.mV[VW]))); + + LLColor4U llcolor4u2(r,g,b,a); + ensure("3:LLColor4u:Fail to initialize ", ((r == llcolor4u2.mV[VX]) && (g == llcolor4u2.mV[VY]) && (b == llcolor4u2.mV[VZ])&& (a == llcolor4u2.mV[VW]))); + + const U8 vec[4] = {0x12,0xFF,0xAF,0x23}; + LLColor4U llcolor4u3(vec); + ensure("4:LLColor4u:Fail to initialize ", ((vec[0] == llcolor4u3.mV[VX]) && (vec[1] == llcolor4u3.mV[VY]) && (vec[2] == llcolor4u3.mV[VZ])&& (vec[3] == llcolor4u3.mV[VW]))); + + LLSD sd = llcolor4u3.getValue(); + LLColor4U llcolor4u4(sd); + ensure_equals("5:LLColor4u (LLSD) Failed ", llcolor4u4, llcolor4u3); + } + + template<> template<> + void v4coloru_object::test<2>() + { + LLColor4U llcolor4ua(1, 2, 3, 4); + LLSD sd = llcolor4ua.getValue(); + LLColor4U llcolor4u; + llcolor4u.setValue(sd); + ensure_equals("setValue(LLSD)/getValue Failed ", llcolor4u, llcolor4ua); + } + + template<> template<> + void v4coloru_object::test<3>() + { + U8 r = 0x12, g = 0xFF, b = 0xAF, a = 0x23; + LLColor4U llcolor4u(r,g,b,a); + llcolor4u.setToBlack(); + ensure("setToBlack:Fail to set black ", ((0 == llcolor4u.mV[VX]) && (0 == llcolor4u.mV[VY]) && (0 == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW]))); + + llcolor4u.setToWhite(); + ensure("setToWhite:Fail to white ", ((255 == llcolor4u.mV[VX]) && (255 == llcolor4u.mV[VY]) && (255 == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW]))); + } + + template<> template<> + void v4coloru_object::test<4>() + { + U8 r = 0x12, g = 0xFF, b = 0xAF, a = 0x23; + LLColor4U llcolor4ua(r,g,b,a); + LLSD sd = llcolor4ua.getValue(); + LLColor4U llcolor4u = (LLColor4U)sd; + ensure_equals("Operator=(LLSD) Failed ", llcolor4u, llcolor4ua); + } + + template<> template<> + void v4coloru_object::test<5>() + { + U8 r = 0x12, g = 0xFF, b = 0xAF, a = 0x23; + LLColor4U llcolor4u; + llcolor4u.setVec(r,g,b,a); + ensure("1:setVec:Fail to set the values ", ((r == llcolor4u.mV[VX]) && (g == llcolor4u.mV[VY]) && (b == llcolor4u.mV[VZ])&& (a == llcolor4u.mV[VW]))); + + llcolor4u.setToBlack(); + llcolor4u.setVec(r,g,b); + ensure("2:setVec:Fail to set the values ", ((r == llcolor4u.mV[VX]) && (g == llcolor4u.mV[VY]) && (b == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW]))); + + LLColor4U llcolor4u1; + llcolor4u1.setVec(llcolor4u); + ensure_equals("3:setVec:Fail to set the values ", llcolor4u1,llcolor4u); + + const U8 vec[4] = {0x12,0xFF,0xAF,0x23}; + LLColor4U llcolor4u2; + llcolor4u2.setVec(vec); + ensure("4:setVec:Fail to set the values ", ((vec[0] == llcolor4u2.mV[VX]) && (vec[1] == llcolor4u2.mV[VY]) && (vec[2] == llcolor4u2.mV[VZ])&& (vec[3] == llcolor4u2.mV[VW]))); + } + + template<> template<> + void v4coloru_object::test<6>() + { + U8 alpha = 0x12; + LLColor4U llcolor4u; + llcolor4u.setAlpha(alpha); + ensure("setAlpha:Fail to set alpha value ", (alpha == llcolor4u.mV[VW])); + } + + template<> template<> + void v4coloru_object::test<7>() + { + U8 r = 0x12, g = 0xFF, b = 0xAF; + LLColor4U llcolor4u(r,g,b); + ensure("magVecSquared:Fail ", is_approx_equal(llcolor4u.magVecSquared(), (F32)(r*r + g*g + b*b))); + ensure("magVec:Fail ", is_approx_equal(llcolor4u.magVec(), (F32) sqrt((F32) (r*r + g*g + b*b)))); + } + + template<> template<> + void v4coloru_object::test<8>() + { + U8 r = 0x12, g = 0xFF, b = 0xAF; + std::ostringstream stream1, stream2; + LLColor4U llcolor4u1(r,g,b),llcolor4u2; + stream1 << llcolor4u1; + llcolor4u2.setVec(r,g,b); + stream2 << llcolor4u2; + ensure("operator << failed ", (stream1.str() == stream2.str())); + } + + template<> template<> + void v4coloru_object::test<9>() + { + U8 r1 = 0x12, g1 = 0xFF, b1 = 0xAF; + U8 r2 = 0x1C, g2 = 0x9A, b2 = 0x1B; + LLColor4U llcolor4u1(r1,g1,b1), llcolor4u2(r2,g2,b2),llcolor4u3; + llcolor4u3 = llcolor4u1 + llcolor4u2; + ensure_equals( + "1a.operator+:Fail to Add the values ", + llcolor4u3.mV[VX], + (U8)(r1+r2)); + ensure_equals( + "1b.operator+:Fail to Add the values ", + llcolor4u3.mV[VY], + (U8)(g1+g2)); + ensure_equals( + "1c.operator+:Fail to Add the values ", + llcolor4u3.mV[VZ], + (U8)(b1+b2)); + + llcolor4u2 += llcolor4u1; + ensure_equals( + "2a.operator+=:Fail to Add the values ", + llcolor4u2.mV[VX], + (U8)(r1+r2)); + ensure_equals( + "2b.operator+=:Fail to Add the values ", + llcolor4u2.mV[VY], + (U8)(g1+g2)); + ensure_equals( + "2c.operator+=:Fail to Add the values ", + llcolor4u2.mV[VZ], + (U8)(b1+b2)); + } + + template<> template<> + void v4coloru_object::test<10>() + { + U8 r1 = 0x12, g1 = 0xFF, b1 = 0xAF; + U8 r2 = 0x1C, g2 = 0x9A, b2 = 0x1B; + LLColor4U llcolor4u1(r1,g1,b1), llcolor4u2(r2,g2,b2),llcolor4u3; + llcolor4u3 = llcolor4u1 - llcolor4u2; + ensure_equals( + "1a. operator-:Fail to Add the values ", + llcolor4u3.mV[VX], + (U8)(r1-r2)); + ensure_equals( + "1b. operator-:Fail to Add the values ", + llcolor4u3.mV[VY], + (U8)(g1-g2)); + ensure_equals( + "1c. operator-:Fail to Add the values ", + llcolor4u3.mV[VZ], + (U8)(b1-b2)); + + llcolor4u1 -= llcolor4u2; + ensure_equals( + "2a. operator-=:Fail to Add the values ", + llcolor4u1.mV[VX], + (U8)(r1-r2)); + ensure_equals( + "2b. operator-=:Fail to Add the values ", + llcolor4u1.mV[VY], + (U8)(g1-g2)); + ensure_equals( + "2c. operator-=:Fail to Add the values ", + llcolor4u1.mV[VZ], + (U8)(b1-b2)); + } + + template<> template<> + void v4coloru_object::test<11>() + { + U8 r1 = 0x12, g1 = 0xFF, b1 = 0xAF; + U8 r2 = 0x1C, g2 = 0x9A, b2 = 0x1B; + LLColor4U llcolor4u1(r1,g1,b1), llcolor4u2(r2,g2,b2),llcolor4u3; + llcolor4u3 = llcolor4u1 * llcolor4u2; + ensure_equals( + "1a. operator*:Fail to multiply the values", + llcolor4u3.mV[VX], + (U8)(r1*r2)); + ensure_equals( + "1b. operator*:Fail to multiply the values", + llcolor4u3.mV[VY], + (U8)(g1*g2)); + ensure_equals( + "1c. operator*:Fail to multiply the values", + llcolor4u3.mV[VZ], + (U8)(b1*b2)); + + U8 mulVal = 123; + llcolor4u1 *= mulVal; + ensure_equals( + "2a. operator*=:Fail to multiply the values", + llcolor4u1.mV[VX], + (U8)(r1*mulVal)); + ensure_equals( + "2b. operator*=:Fail to multiply the values", + llcolor4u1.mV[VY], + (U8)(g1*mulVal)); + ensure_equals( + "2c. operator*=:Fail to multiply the values", + llcolor4u1.mV[VZ], + (U8)(b1*mulVal)); + } + + template<> template<> + void v4coloru_object::test<12>() + { + U8 r = 0x12, g = 0xFF, b = 0xAF; + LLColor4U llcolor4u(r,g,b),llcolor4u1; + llcolor4u1 = llcolor4u; + ensure("operator== failed to ensure the equality ", (llcolor4u1 == llcolor4u)); + llcolor4u1.setToBlack(); + ensure("operator!= failed to ensure the equality ", (llcolor4u1 != llcolor4u)); + } + + template<> template<> + void v4coloru_object::test<13>() + { + U8 r = 0x12, g = 0xFF, b = 0xAF, a = 12; + LLColor4U llcolor4u(r,g,b,a); + U8 modVal = 45; + llcolor4u %= modVal; + ensure_equals("operator%=:Fail ", llcolor4u.mV[VW], (U8)(a * modVal)); + } + + template<> template<> + void v4coloru_object::test<14>() + { + U8 r = 0x12, g = 0xFF, b = 0xAF, a = 12; + LLColor4U llcolor4u1(r,g,b,a); + std::string color("12, 23, 132, 50"); + LLColor4U::parseColor4U(color, &llcolor4u1); + ensure("parseColor4U() failed to parse the color value ", ((12 == llcolor4u1.mV[VX]) && (23 == llcolor4u1.mV[VY]) && (132 == llcolor4u1.mV[VZ])&& (50 == llcolor4u1.mV[VW]))); + + color = "12, 23, 132"; + ensure("2:parseColor4U() failed to parse the color value ", (false == LLColor4U::parseColor4U(color, &llcolor4u1))); + + color = "12"; + ensure("2:parseColor4U() failed to parse the color value ", (false == LLColor4U::parseColor4U(color, &llcolor4u1))); + } + + template<> template<> + void v4coloru_object::test<15>() + { + U8 r = 12, g = 123, b = 3, a = 2; + LLColor4U llcolor4u(r,g,b,a),llcolor4u1; + const F32 fVal = 3.f; + llcolor4u1 = llcolor4u.multAll(fVal); + ensure("multAll:Fail to multiply ", (((U8)ll_round(r * fVal) == llcolor4u1.mV[VX]) && (U8)ll_round(g * fVal) == llcolor4u1.mV[VY] + && ((U8)ll_round(b * fVal) == llcolor4u1.mV[VZ])&& ((U8)ll_round(a * fVal) == llcolor4u1.mV[VW]))); + } + + template<> template<> + void v4coloru_object::test<16>() + { + U8 r1 = 12, g1 = 123, b1 = 3, a1 = 2; + U8 r2 = 23, g2 = 230, b2 = 124, a2 = 255; + LLColor4U llcolor4u(r1,g1,b1,a1),llcolor4u1(r2,g2,b2,a2); + llcolor4u1 = llcolor4u1.addClampMax(llcolor4u); + ensure("1:addClampMax():Fail to add the value ", ((r1+r2 == llcolor4u1.mV[VX]) && (255 == llcolor4u1.mV[VY]) && (b1+b2 == llcolor4u1.mV[VZ])&& (255 == llcolor4u1.mV[VW]))); + + r1 = 132, g1 = 3, b1 = 3, a1 = 2; + r2 = 123, g2 = 230, b2 = 154, a2 = 25; + LLColor4U llcolor4u2(r1,g1,b1,a1),llcolor4u3(r2,g2,b2,a2); + llcolor4u3 = llcolor4u3.addClampMax(llcolor4u2); + ensure("2:addClampMax():Fail to add the value ", ((255 == llcolor4u3.mV[VX]) && (g1+g2 == llcolor4u3.mV[VY]) && (b1+b2 == llcolor4u3.mV[VZ])&& (a1+a2 == llcolor4u3.mV[VW]))); + } + + template<> template<> + void v4coloru_object::test<17>() + { + F32 r = 23.f, g = 12.32f, b = -12.3f; + LLColor3 color3(r,g,b); + LLColor4U llcolor4u; + llcolor4u.setVecScaleClamp(color3); + const S32 MAX_COLOR = 255; + F32 color_scale_factor = MAX_COLOR/r; + S32 r2 = ll_round(r * color_scale_factor); + S32 g2 = ll_round(g * color_scale_factor); + ensure("setVecScaleClamp():Fail to add the value ", ((r2 == llcolor4u.mV[VX]) && (g2 == llcolor4u.mV[VY]) && (0 == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW]))); + } } diff --git a/indra/llmath/tests/v4math_test.cpp b/indra/llmath/tests/v4math_test.cpp index 5308e7efd4..236585f13b 100644 --- a/indra/llmath/tests/v4math_test.cpp +++ b/indra/llmath/tests/v4math_test.cpp @@ -7,25 +7,25 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ - + #include "linden_common.h" #include "../test/lltut.h" #include "llsd.h" @@ -36,348 +36,348 @@ namespace tut { - struct v4math_data - { - }; - typedef test_group<v4math_data> v4math_test; - typedef v4math_test::object v4math_object; - tut::v4math_test v4math_testcase("v4math_h"); + struct v4math_data + { + }; + typedef test_group<v4math_data> v4math_test; + typedef v4math_test::object v4math_object; + tut::v4math_test v4math_testcase("v4math_h"); - template<> template<> - void v4math_object::test<1>() - { - LLVector4 vec4; - ensure("1:LLVector4:Fail to initialize " ,((0 == vec4.mV[VX]) && (0 == vec4.mV[VY]) && (0 == vec4.mV[VZ])&& (1.0f == vec4.mV[VW]))); - F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f; - LLVector4 vec4a(x,y,z); - ensure("2:LLVector4:Fail to initialize " ,((x == vec4a.mV[VX]) && (y == vec4a.mV[VY]) && (z == vec4a.mV[VZ])&& (1.0f == vec4a.mV[VW]))); - LLVector4 vec4b(x,y,z,w); - ensure("3:LLVector4:Fail to initialize " ,((x == vec4b.mV[VX]) && (y == vec4b.mV[VY]) && (z == vec4b.mV[VZ])&& (w == vec4b.mV[VW]))); - const F32 vec[4] = {.112f ,23.2f, -4.2f, -.0001f}; - LLVector4 vec4c(vec); - ensure("4:LLVector4:Fail to initialize " ,((vec[0] == vec4c.mV[VX]) && (vec[1] == vec4c.mV[VY]) && (vec[2] == vec4c.mV[VZ])&& (vec[3] == vec4c.mV[VW]))); - LLVector3 vec3(-2.23f,1.01f,42.3f); - LLVector4 vec4d(vec3); - ensure("5:LLVector4:Fail to initialize " ,((vec3.mV[VX] == vec4d.mV[VX]) && (vec3.mV[VY] == vec4d.mV[VY]) && (vec3.mV[VZ] == vec4d.mV[VZ])&& (1.f == vec4d.mV[VW]))); - F32 w1 = -.234f; - LLVector4 vec4e(vec3,w1); - ensure("6:LLVector4:Fail to initialize " ,((vec3.mV[VX] == vec4e.mV[VX]) && (vec3.mV[VY] == vec4e.mV[VY]) && (vec3.mV[VZ] == vec4e.mV[VZ])&& (w1 == vec4e.mV[VW]))); - } + template<> template<> + void v4math_object::test<1>() + { + LLVector4 vec4; + ensure("1:LLVector4:Fail to initialize " ,((0 == vec4.mV[VX]) && (0 == vec4.mV[VY]) && (0 == vec4.mV[VZ])&& (1.0f == vec4.mV[VW]))); + F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f; + LLVector4 vec4a(x,y,z); + ensure("2:LLVector4:Fail to initialize " ,((x == vec4a.mV[VX]) && (y == vec4a.mV[VY]) && (z == vec4a.mV[VZ])&& (1.0f == vec4a.mV[VW]))); + LLVector4 vec4b(x,y,z,w); + ensure("3:LLVector4:Fail to initialize " ,((x == vec4b.mV[VX]) && (y == vec4b.mV[VY]) && (z == vec4b.mV[VZ])&& (w == vec4b.mV[VW]))); + const F32 vec[4] = {.112f ,23.2f, -4.2f, -.0001f}; + LLVector4 vec4c(vec); + ensure("4:LLVector4:Fail to initialize " ,((vec[0] == vec4c.mV[VX]) && (vec[1] == vec4c.mV[VY]) && (vec[2] == vec4c.mV[VZ])&& (vec[3] == vec4c.mV[VW]))); + LLVector3 vec3(-2.23f,1.01f,42.3f); + LLVector4 vec4d(vec3); + ensure("5:LLVector4:Fail to initialize " ,((vec3.mV[VX] == vec4d.mV[VX]) && (vec3.mV[VY] == vec4d.mV[VY]) && (vec3.mV[VZ] == vec4d.mV[VZ])&& (1.f == vec4d.mV[VW]))); + F32 w1 = -.234f; + LLVector4 vec4e(vec3,w1); + ensure("6:LLVector4:Fail to initialize " ,((vec3.mV[VX] == vec4e.mV[VX]) && (vec3.mV[VY] == vec4e.mV[VY]) && (vec3.mV[VZ] == vec4e.mV[VZ])&& (w1 == vec4e.mV[VW]))); + } - template<> template<> - void v4math_object::test<2>() - { - F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f; - LLVector4 vec4; - vec4.setVec(x,y,z); - ensure("1:setVec:Fail to initialize " ,((x == vec4.mV[VX]) && (y == vec4.mV[VY]) && (z == vec4.mV[VZ])&& (1.0f == vec4.mV[VW]))); - vec4.clearVec(); - ensure("2:clearVec:Fail " ,((0 == vec4.mV[VX]) && (0 == vec4.mV[VY]) && (0 == vec4.mV[VZ])&& (1.0f == vec4.mV[VW]))); - vec4.setVec(x,y,z,w); - ensure("3:setVec:Fail to initialize " ,((x == vec4.mV[VX]) && (y == vec4.mV[VY]) && (z == vec4.mV[VZ])&& (w == vec4.mV[VW]))); - vec4.zeroVec(); - ensure("4:zeroVec:Fail " ,((0 == vec4.mV[VX]) && (0 == vec4.mV[VY]) && (0 == vec4.mV[VZ])&& (0 == vec4.mV[VW]))); - LLVector3 vec3(-2.23f,1.01f,42.3f); - vec4.clearVec(); - vec4.setVec(vec3); - ensure("5:setVec:Fail to initialize " ,((vec3.mV[VX] == vec4.mV[VX]) && (vec3.mV[VY] == vec4.mV[VY]) && (vec3.mV[VZ] == vec4.mV[VZ])&& (1.f == vec4.mV[VW]))); - F32 w1 = -.234f; - vec4.zeroVec(); - vec4.setVec(vec3,w1); - ensure("6:setVec:Fail to initialize " ,((vec3.mV[VX] == vec4.mV[VX]) && (vec3.mV[VY] == vec4.mV[VY]) && (vec3.mV[VZ] == vec4.mV[VZ])&& (w1 == vec4.mV[VW]))); - const F32 vec[4] = {.112f ,23.2f, -4.2f, -.0001f}; - LLVector4 vec4a; - vec4a.setVec(vec); - ensure("7:setVec:Fail to initialize " ,((vec[0] == vec4a.mV[VX]) && (vec[1] == vec4a.mV[VY]) && (vec[2] == vec4a.mV[VZ])&& (vec[3] == vec4a.mV[VW]))); - } + template<> template<> + void v4math_object::test<2>() + { + F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f; + LLVector4 vec4; + vec4.setVec(x,y,z); + ensure("1:setVec:Fail to initialize " ,((x == vec4.mV[VX]) && (y == vec4.mV[VY]) && (z == vec4.mV[VZ])&& (1.0f == vec4.mV[VW]))); + vec4.clearVec(); + ensure("2:clearVec:Fail " ,((0 == vec4.mV[VX]) && (0 == vec4.mV[VY]) && (0 == vec4.mV[VZ])&& (1.0f == vec4.mV[VW]))); + vec4.setVec(x,y,z,w); + ensure("3:setVec:Fail to initialize " ,((x == vec4.mV[VX]) && (y == vec4.mV[VY]) && (z == vec4.mV[VZ])&& (w == vec4.mV[VW]))); + vec4.zeroVec(); + ensure("4:zeroVec:Fail " ,((0 == vec4.mV[VX]) && (0 == vec4.mV[VY]) && (0 == vec4.mV[VZ])&& (0 == vec4.mV[VW]))); + LLVector3 vec3(-2.23f,1.01f,42.3f); + vec4.clearVec(); + vec4.setVec(vec3); + ensure("5:setVec:Fail to initialize " ,((vec3.mV[VX] == vec4.mV[VX]) && (vec3.mV[VY] == vec4.mV[VY]) && (vec3.mV[VZ] == vec4.mV[VZ])&& (1.f == vec4.mV[VW]))); + F32 w1 = -.234f; + vec4.zeroVec(); + vec4.setVec(vec3,w1); + ensure("6:setVec:Fail to initialize " ,((vec3.mV[VX] == vec4.mV[VX]) && (vec3.mV[VY] == vec4.mV[VY]) && (vec3.mV[VZ] == vec4.mV[VZ])&& (w1 == vec4.mV[VW]))); + const F32 vec[4] = {.112f ,23.2f, -4.2f, -.0001f}; + LLVector4 vec4a; + vec4a.setVec(vec); + ensure("7:setVec:Fail to initialize " ,((vec[0] == vec4a.mV[VX]) && (vec[1] == vec4a.mV[VY]) && (vec[2] == vec4a.mV[VZ])&& (vec[3] == vec4a.mV[VW]))); + } - template<> template<> - void v4math_object::test<3>() - { - F32 x = 10.f, y = -2.3f, z = -.023f; - LLVector4 vec4(x,y,z); - ensure("magVec:Fail ", is_approx_equal(vec4.magVec(), (F32) sqrt(x*x + y*y + z*z))); - ensure("magVecSquared:Fail ", is_approx_equal(vec4.magVecSquared(), (x*x + y*y + z*z))); - } + template<> template<> + void v4math_object::test<3>() + { + F32 x = 10.f, y = -2.3f, z = -.023f; + LLVector4 vec4(x,y,z); + ensure("magVec:Fail ", is_approx_equal(vec4.magVec(), (F32) sqrt(x*x + y*y + z*z))); + ensure("magVecSquared:Fail ", is_approx_equal(vec4.magVecSquared(), (x*x + y*y + z*z))); + } - template<> template<> - void v4math_object::test<4>() - { - F32 x = 10.f, y = -2.3f, z = -.023f; - LLVector4 vec4(x,y,z); - F32 mag = vec4.normVec(); - mag = 1.f/ mag; - ensure("1:normVec: Fail " ,is_approx_equal(mag*x,vec4.mV[VX]) && is_approx_equal(mag*y, vec4.mV[VY])&& is_approx_equal(mag*z, vec4.mV[VZ])); - x = 0.000000001f, y = 0.000000001f, z = 0.000000001f; - vec4.clearVec(); - vec4.setVec(x,y,z); - mag = vec4.normVec(); - ensure("2:normVec: Fail " ,is_approx_equal(mag*x,vec4.mV[VX]) && is_approx_equal(mag*y, vec4.mV[VY])&& is_approx_equal(mag*z, vec4.mV[VZ])); - } + template<> template<> + void v4math_object::test<4>() + { + F32 x = 10.f, y = -2.3f, z = -.023f; + LLVector4 vec4(x,y,z); + F32 mag = vec4.normVec(); + mag = 1.f/ mag; + ensure("1:normVec: Fail " ,is_approx_equal(mag*x,vec4.mV[VX]) && is_approx_equal(mag*y, vec4.mV[VY])&& is_approx_equal(mag*z, vec4.mV[VZ])); + x = 0.000000001f, y = 0.000000001f, z = 0.000000001f; + vec4.clearVec(); + vec4.setVec(x,y,z); + mag = vec4.normVec(); + ensure("2:normVec: Fail " ,is_approx_equal(mag*x,vec4.mV[VX]) && is_approx_equal(mag*y, vec4.mV[VY])&& is_approx_equal(mag*z, vec4.mV[VZ])); + } - template<> template<> - void v4math_object::test<5>() - { - F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f; - LLVector4 vec4(x,y,z,w); - vec4.abs(); - ensure("abs:Fail " ,((x == vec4.mV[VX]) && (-y == vec4.mV[VY]) && (-z == vec4.mV[VZ])&& (-w == vec4.mV[VW]))); - vec4.clearVec(); - ensure("isExactlyClear:Fail " ,(true == vec4.isExactlyClear())); - vec4.zeroVec(); - ensure("isExactlyZero:Fail " ,(true == vec4.isExactlyZero())); - } + template<> template<> + void v4math_object::test<5>() + { + F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f; + LLVector4 vec4(x,y,z,w); + vec4.abs(); + ensure("abs:Fail " ,((x == vec4.mV[VX]) && (-y == vec4.mV[VY]) && (-z == vec4.mV[VZ])&& (-w == vec4.mV[VW]))); + vec4.clearVec(); + ensure("isExactlyClear:Fail " ,(true == vec4.isExactlyClear())); + vec4.zeroVec(); + ensure("isExactlyZero:Fail " ,(true == vec4.isExactlyZero())); + } - template<> template<> - void v4math_object::test<6>() - { - F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f; - LLVector4 vec4(x,y,z,w),vec4a; - vec4a = vec4.scaleVec(vec4); - ensure("scaleVec:Fail " ,(is_approx_equal(x*x, vec4a.mV[VX]) && is_approx_equal(y*y, vec4a.mV[VY]) && is_approx_equal(z*z, vec4a.mV[VZ])&& is_approx_equal(w*w, vec4a.mV[VW]))); - } + template<> template<> + void v4math_object::test<6>() + { + F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f; + LLVector4 vec4(x,y,z,w),vec4a; + vec4a = vec4.scaleVec(vec4); + ensure("scaleVec:Fail " ,(is_approx_equal(x*x, vec4a.mV[VX]) && is_approx_equal(y*y, vec4a.mV[VY]) && is_approx_equal(z*z, vec4a.mV[VZ])&& is_approx_equal(w*w, vec4a.mV[VW]))); + } - template<> template<> - void v4math_object::test<7>() - { - F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f; - LLVector4 vec4(x,y,z,w); - ensure("1:operator [] failed " ,( x == vec4[0])); - ensure("2:operator [] failed " ,( y == vec4[1])); - ensure("3:operator [] failed " ,( z == vec4[2])); - ensure("4:operator [] failed " ,( w == vec4[3])); - x = 23.f, y = -.2361f, z = 3.25; - vec4.setVec(x,y,z); - F32 &ref1 = vec4[0]; - ensure("5:operator [] failed " ,( ref1 == vec4[0])); - F32 &ref2 = vec4[1]; - ensure("6:operator [] failed " ,( ref2 == vec4[1])); - F32 &ref3 = vec4[2]; - ensure("7:operator [] failed " ,( ref3 == vec4[2])); - F32 &ref4 = vec4[3]; - ensure("8:operator [] failed " ,( ref4 == vec4[3])); - } + template<> template<> + void v4math_object::test<7>() + { + F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f; + LLVector4 vec4(x,y,z,w); + ensure("1:operator [] failed " ,( x == vec4[0])); + ensure("2:operator [] failed " ,( y == vec4[1])); + ensure("3:operator [] failed " ,( z == vec4[2])); + ensure("4:operator [] failed " ,( w == vec4[3])); + x = 23.f, y = -.2361f, z = 3.25; + vec4.setVec(x,y,z); + F32 &ref1 = vec4[0]; + ensure("5:operator [] failed " ,( ref1 == vec4[0])); + F32 &ref2 = vec4[1]; + ensure("6:operator [] failed " ,( ref2 == vec4[1])); + F32 &ref3 = vec4[2]; + ensure("7:operator [] failed " ,( ref3 == vec4[2])); + F32 &ref4 = vec4[3]; + ensure("8:operator [] failed " ,( ref4 == vec4[3])); + } - template<> template<> - void v4math_object::test<8>() - { - F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f; - const F32 val[16] = { + template<> template<> + void v4math_object::test<8>() + { + F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f; + const F32 val[16] = { 1.f, 2.f, 3.f, 0.f, .34f, .1f, -.5f, 0.f, 2.f, 1.23f, 1.234f, 0.f, .89f, 0.f, 0.f, 0.f }; - LLMatrix4 mat(val); - LLVector4 vec4(x,y,z,w),vec4a; - vec4.rotVec(mat); - vec4a.setVec(x,y,z,w); - vec4a.rotVec(mat); - ensure_equals("1:rotVec: Fail " ,vec4a, vec4); - F32 a = 2.32f, b = -23.2f, c = -34.1112f, d = 1.010112f; - LLQuaternion q(a,b,c,d); - LLVector4 vec4b(a,b,c,d),vec4c; - vec4b.rotVec(q); - vec4c.setVec(a, b, c, d); - vec4c.rotVec(q); - ensure_equals("2:rotVec: Fail " ,vec4b, vec4c); - } - - template<> template<> - void v4math_object::test<9>() - { - F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f; - LLVector4 vec4(x,y,z,w),vec4a;; - std::ostringstream stream1, stream2; - stream1 << vec4; - vec4a.setVec(x,y,z,w); - stream2 << vec4a; - ensure("operator << failed",(stream1.str() == stream2.str())); - } - - template<> template<> - void v4math_object::test<10>() - { - F32 x1 = 1.f, y1 = 2.f, z1 = -1.1f, w1 = .23f; - F32 x2 = 1.2f, y2 = 2.5f, z2 = 1.f, w2 = 1.3f; - LLVector4 vec4(x1,y1,z1,w1),vec4a(x2,y2,z2,w2),vec4b; - vec4b = vec4a + vec4; - ensure("1:operator+:Fail to initialize " ,(is_approx_equal(x1+x2,vec4b.mV[VX]) && is_approx_equal(y1+y2,vec4b.mV[VY]) && is_approx_equal(z1+z2,vec4b.mV[VZ]))); - x1 = -2.45f, y1 = 2.1f, z1 = 3.0f; - vec4.clearVec(); - vec4a.clearVec(); - vec4.setVec(x1,y1,z1); - vec4a +=vec4; - ensure_equals("2:operator+=: Fail to initialize", vec4a,vec4); - vec4a += vec4; - ensure("3:operator+=:Fail to initialize " ,(is_approx_equal(2*x1,vec4a.mV[VX]) && is_approx_equal(2*y1,vec4a.mV[VY]) && is_approx_equal(2*z1,vec4a.mV[VZ]))); - } - template<> template<> - void v4math_object::test<11>() - { - F32 x1 = 1.f, y1 = 2.f, z1 = -1.1f, w1 = .23f; - F32 x2 = 1.2f, y2 = 2.5f, z2 = 1.f, w2 = 1.3f; - LLVector4 vec4(x1,y1,z1,w1),vec4a(x2,y2,z2,w2),vec4b; - vec4b = vec4a - vec4; - ensure("1:operator-:Fail to initialize " ,(is_approx_equal(x2-x1,vec4b.mV[VX]) && is_approx_equal(y2-y1,vec4b.mV[VY]) && is_approx_equal(z2-z1,vec4b.mV[VZ]))); - x1 = -2.45f, y1 = 2.1f, z1 = 3.0f; - vec4.clearVec(); - vec4a.clearVec(); - vec4.setVec(x1,y1,z1); - vec4a -=vec4; - ensure_equals("2:operator-=: Fail to initialize" , vec4a,-vec4); - vec4a -=vec4; - ensure("3:operator-=:Fail to initialize " ,(is_approx_equal(-2*x1,vec4a.mV[VX]) && is_approx_equal(-2*y1,vec4a.mV[VY]) && is_approx_equal(-2*z1,vec4a.mV[VZ]))); - } + LLMatrix4 mat(val); + LLVector4 vec4(x,y,z,w),vec4a; + vec4.rotVec(mat); + vec4a.setVec(x,y,z,w); + vec4a.rotVec(mat); + ensure_equals("1:rotVec: Fail " ,vec4a, vec4); + F32 a = 2.32f, b = -23.2f, c = -34.1112f, d = 1.010112f; + LLQuaternion q(a,b,c,d); + LLVector4 vec4b(a,b,c,d),vec4c; + vec4b.rotVec(q); + vec4c.setVec(a, b, c, d); + vec4c.rotVec(q); + ensure_equals("2:rotVec: Fail " ,vec4b, vec4c); + } + + template<> template<> + void v4math_object::test<9>() + { + F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f; + LLVector4 vec4(x,y,z,w),vec4a;; + std::ostringstream stream1, stream2; + stream1 << vec4; + vec4a.setVec(x,y,z,w); + stream2 << vec4a; + ensure("operator << failed",(stream1.str() == stream2.str())); + } + + template<> template<> + void v4math_object::test<10>() + { + F32 x1 = 1.f, y1 = 2.f, z1 = -1.1f, w1 = .23f; + F32 x2 = 1.2f, y2 = 2.5f, z2 = 1.f, w2 = 1.3f; + LLVector4 vec4(x1,y1,z1,w1),vec4a(x2,y2,z2,w2),vec4b; + vec4b = vec4a + vec4; + ensure("1:operator+:Fail to initialize " ,(is_approx_equal(x1+x2,vec4b.mV[VX]) && is_approx_equal(y1+y2,vec4b.mV[VY]) && is_approx_equal(z1+z2,vec4b.mV[VZ]))); + x1 = -2.45f, y1 = 2.1f, z1 = 3.0f; + vec4.clearVec(); + vec4a.clearVec(); + vec4.setVec(x1,y1,z1); + vec4a +=vec4; + ensure_equals("2:operator+=: Fail to initialize", vec4a,vec4); + vec4a += vec4; + ensure("3:operator+=:Fail to initialize " ,(is_approx_equal(2*x1,vec4a.mV[VX]) && is_approx_equal(2*y1,vec4a.mV[VY]) && is_approx_equal(2*z1,vec4a.mV[VZ]))); + } + template<> template<> + void v4math_object::test<11>() + { + F32 x1 = 1.f, y1 = 2.f, z1 = -1.1f, w1 = .23f; + F32 x2 = 1.2f, y2 = 2.5f, z2 = 1.f, w2 = 1.3f; + LLVector4 vec4(x1,y1,z1,w1),vec4a(x2,y2,z2,w2),vec4b; + vec4b = vec4a - vec4; + ensure("1:operator-:Fail to initialize " ,(is_approx_equal(x2-x1,vec4b.mV[VX]) && is_approx_equal(y2-y1,vec4b.mV[VY]) && is_approx_equal(z2-z1,vec4b.mV[VZ]))); + x1 = -2.45f, y1 = 2.1f, z1 = 3.0f; + vec4.clearVec(); + vec4a.clearVec(); + vec4.setVec(x1,y1,z1); + vec4a -=vec4; + ensure_equals("2:operator-=: Fail to initialize" , vec4a,-vec4); + vec4a -=vec4; + ensure("3:operator-=:Fail to initialize " ,(is_approx_equal(-2*x1,vec4a.mV[VX]) && is_approx_equal(-2*y1,vec4a.mV[VY]) && is_approx_equal(-2*z1,vec4a.mV[VZ]))); + } - template<> template<> - void v4math_object::test<12>() - { - F32 x1 = 1.f, y1 = 2.f, z1 = -1.1f; - F32 x2 = 1.2f, y2 = 2.5f, z2 = 1.f; - LLVector4 vec4(x1,y1,z1),vec4a(x2,y2,z2); - F32 res = vec4 * vec4a; - ensure("1:operator* failed " ,is_approx_equal(res, x1*x2 + y1*y2 + z1*z2)); - vec4a.clearVec(); - F32 mulVal = 4.2f; - vec4a = vec4 * mulVal; - ensure("2:operator* failed " ,is_approx_equal(x1*mulVal,vec4a.mV[VX]) && is_approx_equal(y1*mulVal, vec4a.mV[VY])&& is_approx_equal(z1*mulVal, vec4a.mV[VZ])); - vec4a.clearVec(); - vec4a = mulVal * vec4 ; - ensure("3:operator* failed " ,is_approx_equal(x1*mulVal, vec4a.mV[VX]) && is_approx_equal(y1*mulVal, vec4a.mV[VY])&& is_approx_equal(z1*mulVal, vec4a.mV[VZ])); - vec4 *= mulVal; - ensure("4:operator*= failed " ,is_approx_equal(x1*mulVal, vec4.mV[VX]) && is_approx_equal(y1*mulVal, vec4.mV[VY])&& is_approx_equal(z1*mulVal, vec4.mV[VZ])); - } + template<> template<> + void v4math_object::test<12>() + { + F32 x1 = 1.f, y1 = 2.f, z1 = -1.1f; + F32 x2 = 1.2f, y2 = 2.5f, z2 = 1.f; + LLVector4 vec4(x1,y1,z1),vec4a(x2,y2,z2); + F32 res = vec4 * vec4a; + ensure("1:operator* failed " ,is_approx_equal(res, x1*x2 + y1*y2 + z1*z2)); + vec4a.clearVec(); + F32 mulVal = 4.2f; + vec4a = vec4 * mulVal; + ensure("2:operator* failed " ,is_approx_equal(x1*mulVal,vec4a.mV[VX]) && is_approx_equal(y1*mulVal, vec4a.mV[VY])&& is_approx_equal(z1*mulVal, vec4a.mV[VZ])); + vec4a.clearVec(); + vec4a = mulVal * vec4 ; + ensure("3:operator* failed " ,is_approx_equal(x1*mulVal, vec4a.mV[VX]) && is_approx_equal(y1*mulVal, vec4a.mV[VY])&& is_approx_equal(z1*mulVal, vec4a.mV[VZ])); + vec4 *= mulVal; + ensure("4:operator*= failed " ,is_approx_equal(x1*mulVal, vec4.mV[VX]) && is_approx_equal(y1*mulVal, vec4.mV[VY])&& is_approx_equal(z1*mulVal, vec4.mV[VZ])); + } - template<> template<> - void v4math_object::test<13>() - { - F32 x1 = 1.f, y1 = 2.f, z1 = -1.1f; - F32 x2 = 1.2f, y2 = 2.5f, z2 = 1.f; - LLVector4 vec4(x1,y1,z1),vec4a(x2,y2,z2),vec4b; - vec4b = vec4 % vec4a; - ensure("1:operator% failed " ,is_approx_equal(y1*z2 - y2*z1, vec4b.mV[VX]) && is_approx_equal(z1*x2 -z2*x1, vec4b.mV[VY]) && is_approx_equal(x1*y2-x2*y1, vec4b.mV[VZ])); - vec4 %= vec4a; - ensure_equals("operator%= failed " ,vec4,vec4b); - } + template<> template<> + void v4math_object::test<13>() + { + F32 x1 = 1.f, y1 = 2.f, z1 = -1.1f; + F32 x2 = 1.2f, y2 = 2.5f, z2 = 1.f; + LLVector4 vec4(x1,y1,z1),vec4a(x2,y2,z2),vec4b; + vec4b = vec4 % vec4a; + ensure("1:operator% failed " ,is_approx_equal(y1*z2 - y2*z1, vec4b.mV[VX]) && is_approx_equal(z1*x2 -z2*x1, vec4b.mV[VY]) && is_approx_equal(x1*y2-x2*y1, vec4b.mV[VZ])); + vec4 %= vec4a; + ensure_equals("operator%= failed " ,vec4,vec4b); + } - template<> template<> - void v4math_object::test<14>() - { - F32 x = 1.f, y = 2.f, z = -1.1f,div = 4.2f; - F32 t = 1.f / div; - LLVector4 vec4(x,y,z), vec4a; - vec4a = vec4/div; - ensure("1:operator/ failed " ,is_approx_equal(x*t, vec4a.mV[VX]) && is_approx_equal(y*t, vec4a.mV[VY])&& is_approx_equal(z*t, vec4a.mV[VZ])); - x = 1.23f, y = 4.f, z = -2.32f; - vec4.clearVec(); - vec4a.clearVec(); - vec4.setVec(x,y,z); - vec4a = vec4/div; - ensure("2:operator/ failed " ,is_approx_equal(x*t, vec4a.mV[VX]) && is_approx_equal(y*t, vec4a.mV[VY])&& is_approx_equal(z*t, vec4a.mV[VZ])); - vec4 /= div; - ensure("3:operator/ failed " ,is_approx_equal(x*t, vec4.mV[VX]) && is_approx_equal(y*t, vec4.mV[VY])&& is_approx_equal(z*t, vec4.mV[VZ])); - } + template<> template<> + void v4math_object::test<14>() + { + F32 x = 1.f, y = 2.f, z = -1.1f,div = 4.2f; + F32 t = 1.f / div; + LLVector4 vec4(x,y,z), vec4a; + vec4a = vec4/div; + ensure("1:operator/ failed " ,is_approx_equal(x*t, vec4a.mV[VX]) && is_approx_equal(y*t, vec4a.mV[VY])&& is_approx_equal(z*t, vec4a.mV[VZ])); + x = 1.23f, y = 4.f, z = -2.32f; + vec4.clearVec(); + vec4a.clearVec(); + vec4.setVec(x,y,z); + vec4a = vec4/div; + ensure("2:operator/ failed " ,is_approx_equal(x*t, vec4a.mV[VX]) && is_approx_equal(y*t, vec4a.mV[VY])&& is_approx_equal(z*t, vec4a.mV[VZ])); + vec4 /= div; + ensure("3:operator/ failed " ,is_approx_equal(x*t, vec4.mV[VX]) && is_approx_equal(y*t, vec4.mV[VY])&& is_approx_equal(z*t, vec4.mV[VZ])); + } - template<> template<> - void v4math_object::test<15>() - { - F32 x = 1.f, y = 2.f, z = -1.1f; - LLVector4 vec4(x,y,z), vec4a; - ensure("operator!= failed " ,(vec4 != vec4a)); - vec4a = vec4; - ensure("operator== failed " ,(vec4 ==vec4a)); - } + template<> template<> + void v4math_object::test<15>() + { + F32 x = 1.f, y = 2.f, z = -1.1f; + LLVector4 vec4(x,y,z), vec4a; + ensure("operator!= failed " ,(vec4 != vec4a)); + vec4a = vec4; + ensure("operator== failed " ,(vec4 ==vec4a)); + } - template<> template<> - void v4math_object::test<16>() - { - F32 x = 1.f, y = 2.f, z = -1.1f; - LLVector4 vec4(x,y,z), vec4a; - vec4a = - vec4; - ensure("operator- failed " , (vec4 == - vec4a)); - } + template<> template<> + void v4math_object::test<16>() + { + F32 x = 1.f, y = 2.f, z = -1.1f; + LLVector4 vec4(x,y,z), vec4a; + vec4a = - vec4; + ensure("operator- failed " , (vec4 == - vec4a)); + } - template<> template<> - void v4math_object::test<17>() - { - F32 x = 1.f, y = 2.f, z = -1.1f,epsilon = .23425f; - LLVector4 vec4(x,y,z), vec4a(x,y,z); - ensure("1:are_parallel: Fail " ,(true == are_parallel(vec4a,vec4,epsilon))); - x = 21.f, y = 12.f, z = -123.1f; - vec4a.clearVec(); - vec4a.setVec(x,y,z); - ensure("2:are_parallel: Fail " ,(false == are_parallel(vec4a,vec4,epsilon))); - } + template<> template<> + void v4math_object::test<17>() + { + F32 x = 1.f, y = 2.f, z = -1.1f,epsilon = .23425f; + LLVector4 vec4(x,y,z), vec4a(x,y,z); + ensure("1:are_parallel: Fail " ,(true == are_parallel(vec4a,vec4,epsilon))); + x = 21.f, y = 12.f, z = -123.1f; + vec4a.clearVec(); + vec4a.setVec(x,y,z); + ensure("2:are_parallel: Fail " ,(false == are_parallel(vec4a,vec4,epsilon))); + } - template<> template<> - void v4math_object::test<18>() - { - F32 x = 1.f, y = 2.f, z = -1.1f; - F32 angle1, angle2; - LLVector4 vec4(x,y,z), vec4a(x,y,z); - angle1 = angle_between(vec4, vec4a); - vec4.normVec(); - vec4a.normVec(); - angle2 = acos(vec4 * vec4a); - ensure_approximately_equals("1:angle_between: Fail " ,angle1,angle2,8); - F32 x1 = 21.f, y1 = 2.23f, z1 = -1.1f; - LLVector4 vec4b(x,y,z), vec4c(x1,y1,z1); - angle1 = angle_between(vec4b, vec4c); - vec4b.normVec(); - vec4c.normVec(); - angle2 = acos(vec4b * vec4c); - ensure_approximately_equals("2:angle_between: Fail " ,angle1,angle2,8); - } + template<> template<> + void v4math_object::test<18>() + { + F32 x = 1.f, y = 2.f, z = -1.1f; + F32 angle1, angle2; + LLVector4 vec4(x,y,z), vec4a(x,y,z); + angle1 = angle_between(vec4, vec4a); + vec4.normVec(); + vec4a.normVec(); + angle2 = acos(vec4 * vec4a); + ensure_approximately_equals("1:angle_between: Fail " ,angle1,angle2,8); + F32 x1 = 21.f, y1 = 2.23f, z1 = -1.1f; + LLVector4 vec4b(x,y,z), vec4c(x1,y1,z1); + angle1 = angle_between(vec4b, vec4c); + vec4b.normVec(); + vec4c.normVec(); + angle2 = acos(vec4b * vec4c); + ensure_approximately_equals("2:angle_between: Fail " ,angle1,angle2,8); + } - template<> template<> - void v4math_object::test<19>() - { - F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 1.f, z2 = 1.f; - F32 val1,val2; - LLVector4 vec4(x1,y1,z1),vec4a(x2,y2,z2); - val1 = dist_vec(vec4,vec4a); - val2 = (F32) sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); - ensure_equals("dist_vec: Fail ",val2, val1); - val1 = dist_vec_squared(vec4,vec4a); - val2 =((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); - ensure_equals("dist_vec_squared: Fail ",val2, val1); - } + template<> template<> + void v4math_object::test<19>() + { + F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 1.f, z2 = 1.f; + F32 val1,val2; + LLVector4 vec4(x1,y1,z1),vec4a(x2,y2,z2); + val1 = dist_vec(vec4,vec4a); + val2 = (F32) sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); + ensure_equals("dist_vec: Fail ",val2, val1); + val1 = dist_vec_squared(vec4,vec4a); + val2 =((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); + ensure_equals("dist_vec_squared: Fail ",val2, val1); + } - template<> template<> - void v4math_object::test<20>() - { - F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, w1 = -.23f, x2 = 1.3f, y2 = 1.f, z2 = 1.f,w2 = .12f; - F32 val = 2.3f,val1,val2,val3,val4; - LLVector4 vec4(x1,y1,z1,w1),vec4a(x2,y2,z2,w2); - val1 = x1 + (x2 - x1)* val; - val2 = y1 + (y2 - y1)* val; - val3 = z1 + (z2 - z1)* val; - val4 = w1 + (w2 - w1)* val; - LLVector4 vec4b = lerp(vec4,vec4a,val); - LLVector4 check(val1, val2, val3, val4); - ensure_equals("lerp failed", check, vec4b); - } + template<> template<> + void v4math_object::test<20>() + { + F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, w1 = -.23f, x2 = 1.3f, y2 = 1.f, z2 = 1.f,w2 = .12f; + F32 val = 2.3f,val1,val2,val3,val4; + LLVector4 vec4(x1,y1,z1,w1),vec4a(x2,y2,z2,w2); + val1 = x1 + (x2 - x1)* val; + val2 = y1 + (y2 - y1)* val; + val3 = z1 + (z2 - z1)* val; + val4 = w1 + (w2 - w1)* val; + LLVector4 vec4b = lerp(vec4,vec4a,val); + LLVector4 check(val1, val2, val3, val4); + ensure_equals("lerp failed", check, vec4b); + } - template<> template<> - void v4math_object::test<21>() - { - F32 x = 1.f, y = 2.f, z = -1.1f; - LLVector4 vec4(x,y,z); - LLVector3 vec3 = vec4to3(vec4); - ensure("vec4to3 failed", ((x == vec3.mV[VX])&& (y == vec3.mV[VY]) && (z == vec3.mV[VZ]))); - LLVector4 vec4a = vec3to4(vec3); - ensure_equals("vec3to4 failed",vec4a,vec4); - } + template<> template<> + void v4math_object::test<21>() + { + F32 x = 1.f, y = 2.f, z = -1.1f; + LLVector4 vec4(x,y,z); + LLVector3 vec3 = vec4to3(vec4); + ensure("vec4to3 failed", ((x == vec3.mV[VX])&& (y == vec3.mV[VY]) && (z == vec3.mV[VZ]))); + LLVector4 vec4a = vec3to4(vec3); + ensure_equals("vec3to4 failed",vec4a,vec4); + } - template<> template<> - void v4math_object::test<22>() - { - F32 x = 1.f, y = 2.f, z = -1.1f; - LLVector4 vec4(x,y,z); - LLSD llsd = vec4.getValue(); - LLVector3 vec3(llsd); - LLVector4 vec4a = vec3to4(vec3); - ensure_equals("getValue failed",vec4a,vec4); - } + template<> template<> + void v4math_object::test<22>() + { + F32 x = 1.f, y = 2.f, z = -1.1f; + LLVector4 vec4(x,y,z); + LLSD llsd = vec4.getValue(); + LLVector3 vec3(llsd); + LLVector4 vec4a = vec3to4(vec3); + ensure_equals("getValue failed",vec4a,vec4); + } } diff --git a/indra/llmath/tests/xform_test.cpp b/indra/llmath/tests/xform_test.cpp index 6348b3225c..6d6a64ec4c 100644 --- a/indra/llmath/tests/xform_test.cpp +++ b/indra/llmath/tests/xform_test.cpp @@ -1,27 +1,27 @@ -/** +/** * @file xform_test.cpp * @author Adroit - * @date March 2007 + * @date March 2007 * @brief Test cases for LLXform * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -33,213 +33,213 @@ namespace tut { - struct xform_test - { - }; - typedef test_group<xform_test> xform_test_t; - typedef xform_test_t::object xform_test_object_t; - tut::xform_test_t tut_xform_test("LLXForm"); - - //test case for init(), getParent(), getRotation(), getPositionW(), getWorldRotation() fns. - template<> template<> - void xform_test_object_t::test<1>() - { - LLXform xform_obj; - LLVector3 emptyVec(0.f,0.f,0.f); - LLVector3 initialScaleVec(1.f,1.f,1.f); - - ensure("LLXform empty constructor failed: ", !xform_obj.getParent() && !xform_obj.isChanged() && - xform_obj.getPosition() == emptyVec && - (xform_obj.getRotation()).isIdentity() && - xform_obj.getScale() == initialScaleVec && - xform_obj.getPositionW() == emptyVec && - (xform_obj.getWorldRotation()).isIdentity() && - !xform_obj.getScaleChildOffset()); - } - - // test cases for - // setScale(const LLVector3& scale) - // setScale(const F32 x, const F32 y, const F32 z) - // setRotation(const F32 x, const F32 y, const F32 z) - // setPosition(const F32 x, const F32 y, const F32 z) - // getLocalMat4(LLMatrix4 &mat) - template<> template<> - void xform_test_object_t::test<2>() - { - LLMatrix4 llmat4; - LLXform xform_obj; - - F32 x = 3.6f; - F32 y = 5.5f; - F32 z = 4.2f; - F32 w = 0.f; - F32 posz = z + 2.122f; - LLVector3 vec(x, y, z); - xform_obj.setScale(x, y, z); - xform_obj.setPosition(x, y, posz); - ensure("setScale failed: ", xform_obj.getScale() == vec); - - vec.setVec(x, y, posz); - ensure("getPosition failed: ", xform_obj.getPosition() == vec); - - x = x * 2.f; - y = y + 2.3f; - z = posz * 4.f; - vec.setVec(x, y, z); - xform_obj.setPositionX(x); - xform_obj.setPositionY(y); - xform_obj.setPositionZ(z); - ensure("setPositionX/Y/Z failed: ", xform_obj.getPosition() == vec); - - xform_obj.setScaleChildOffset(true); - ensure("setScaleChildOffset failed: ", xform_obj.getScaleChildOffset()); - - vec.setVec(x, y, z); - - xform_obj.addPosition(vec); - vec += vec; - ensure("addPosition failed: ", xform_obj.getPosition() == vec); - - xform_obj.setScale(vec); - ensure("setScale vector failed: ", xform_obj.getScale() == vec); - - LLQuaternion quat(x, y, z, w); - xform_obj.setRotation(quat); - ensure("setRotation quat failed: ", xform_obj.getRotation() == quat); - - xform_obj.setRotation(x, y, z, w); - ensure("getRotation 2 failed: ", xform_obj.getRotation() == quat); - - xform_obj.setRotation(x, y, z); - quat.setQuat(x,y,z); - ensure("setRotation xyz failed: ", xform_obj.getRotation() == quat); - - // LLXform::setRotation(const F32 x, const F32 y, const F32 z) - // Does normalization - // LLXform::setRotation(const F32 x, const F32 y, const F32 z, const F32 s) - // Simply copies the individual values - does not do any normalization. - // Is that the expected behavior? - } - - // test cases for inline bool setParent(LLXform *parent) and getParent() fn. - template<> template<> - void xform_test_object_t::test<3>() - { - LLXform xform_obj; - LLXform par; - LLXform grandpar; - xform_obj.setParent(&par); - par.setParent(&grandpar); - ensure("setParent/getParent failed: ", &par == xform_obj.getParent()); - ensure("getRoot failed: ", &grandpar == xform_obj.getRoot()); - ensure("isRoot failed: ", grandpar.isRoot() && !par.isRoot() && !xform_obj.isRoot()); - ensure("isRootEdit failed: ", grandpar.isRootEdit() && !par.isRootEdit() && !xform_obj.isRootEdit()); - } - - template<> template<> - void xform_test_object_t::test<4>() - { - LLXform xform_obj; - xform_obj.setChanged(LLXform::TRANSLATED | LLXform::ROTATED | LLXform::SCALED); - ensure("setChanged/isChanged failed: ", xform_obj.isChanged()); - - xform_obj.clearChanged(LLXform::TRANSLATED | LLXform::ROTATED | LLXform::SCALED); - ensure("clearChanged failed: ", !xform_obj.isChanged()); - - LLVector3 llvect3(12.4f, -5.6f, 0.34f); - xform_obj.setScale(llvect3); - ensure("setScale did not set SCALED flag: ", xform_obj.isChanged(LLXform::SCALED)); - xform_obj.setPosition(1.2f, 2.3f, 3.4f); - ensure("setScale did not set TRANSLATED flag: ", xform_obj.isChanged(LLXform::TRANSLATED)); - ensure("TRANSLATED reset SCALED flag: ", xform_obj.isChanged(LLXform::TRANSLATED | LLXform::SCALED)); - xform_obj.clearChanged(LLXform::SCALED); - ensure("reset SCALED failed: ", !xform_obj.isChanged(LLXform::SCALED)); - xform_obj.setRotation(1, 2, 3, 4); - ensure("ROTATION flag not set ", xform_obj.isChanged(LLXform::TRANSLATED | LLXform::ROTATED)); - xform_obj.setScale(llvect3); - ensure("ROTATION flag not set ", xform_obj.isChanged(LLXform::MOVED)); - } - - //to test init() and getWorldMatrix() fns. - template<> template<> - void xform_test_object_t::test<5>() - { - LLXformMatrix formMatrix_obj; - formMatrix_obj.init(); - LLMatrix4 mat4_obj; - - ensure("1. The value is not NULL", 1.f == formMatrix_obj.getWorldMatrix().mMatrix[0][0]); - ensure("2. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[0][1]); - ensure("3. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[0][2]); - ensure("4. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[0][3]); - ensure("5. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[1][0]); - ensure("6. The value is not NULL", 1.f == formMatrix_obj.getWorldMatrix().mMatrix[1][1]); - ensure("7. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[1][2]); - ensure("8. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[1][3]); - ensure("9. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[2][0]); - ensure("10. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[2][1]); - ensure("11. The value is not NULL", 1.f == formMatrix_obj.getWorldMatrix().mMatrix[2][2]); - ensure("12. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[2][3]); - ensure("13. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[3][0]); - ensure("14. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[3][1]); - ensure("15. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[3][2]); - ensure("16. The value is not NULL", 1.f == formMatrix_obj.getWorldMatrix().mMatrix[3][3]); - } - - //to test mMin.clearVec() and mMax.clearVec() fns - template<> template<> - void xform_test_object_t::test<6>() - { - LLXformMatrix formMatrix_obj; - formMatrix_obj.init(); - LLVector3 llmin_vec3; - LLVector3 llmax_vec3; - formMatrix_obj.getMinMax(llmin_vec3, llmax_vec3); - ensure("1. The value is not NULL", 0.f == llmin_vec3.mV[0]); - ensure("2. The value is not NULL", 0.f == llmin_vec3.mV[1]); - ensure("3. The value is not NULL", 0.f == llmin_vec3.mV[2]); - ensure("4. The value is not NULL", 0.f == llmin_vec3.mV[0]); - ensure("5. The value is not NULL", 0.f == llmin_vec3.mV[1]); - ensure("6. The value is not NULL", 0.f == llmin_vec3.mV[2]); - } - - //test case of update() fn. - template<> template<> - void xform_test_object_t::test<7>() - { - LLXformMatrix formMatrix_obj; - - LLXformMatrix parent; - LLVector3 llvecpos(1.0, 2.0, 3.0); - LLVector3 llvecpospar(10.0, 20.0, 30.0); - formMatrix_obj.setPosition(llvecpos); - parent.setPosition(llvecpospar); - - LLVector3 llvecparentscale(1.0, 2.0, 0); - parent.setScaleChildOffset(true); - parent.setScale(llvecparentscale); - - LLQuaternion quat(1, 2, 3, 4); - LLQuaternion quatparent(5, 6, 7, 8); - formMatrix_obj.setRotation(quat); - parent.setRotation(quatparent); - formMatrix_obj.setParent(&parent); - - parent.update(); - formMatrix_obj.update(); - - LLVector3 worldPos = llvecpos; - worldPos.scaleVec(llvecparentscale); - worldPos *= quatparent; - worldPos += llvecpospar; - - LLQuaternion worldRot = quat * quatparent; - - ensure("getWorldPosition failed: ", formMatrix_obj.getWorldPosition() == worldPos); - ensure("getWorldRotation failed: ", formMatrix_obj.getWorldRotation() == worldRot); - - ensure("getWorldPosition for parent failed: ", parent.getWorldPosition() == llvecpospar); - ensure("getWorldRotation for parent failed: ", parent.getWorldRotation() == quatparent); - } -} + struct xform_test + { + }; + typedef test_group<xform_test> xform_test_t; + typedef xform_test_t::object xform_test_object_t; + tut::xform_test_t tut_xform_test("LLXForm"); + + //test case for init(), getParent(), getRotation(), getPositionW(), getWorldRotation() fns. + template<> template<> + void xform_test_object_t::test<1>() + { + LLXform xform_obj; + LLVector3 emptyVec(0.f,0.f,0.f); + LLVector3 initialScaleVec(1.f,1.f,1.f); + + ensure("LLXform empty constructor failed: ", !xform_obj.getParent() && !xform_obj.isChanged() && + xform_obj.getPosition() == emptyVec && + (xform_obj.getRotation()).isIdentity() && + xform_obj.getScale() == initialScaleVec && + xform_obj.getPositionW() == emptyVec && + (xform_obj.getWorldRotation()).isIdentity() && + !xform_obj.getScaleChildOffset()); + } + + // test cases for + // setScale(const LLVector3& scale) + // setScale(const F32 x, const F32 y, const F32 z) + // setRotation(const F32 x, const F32 y, const F32 z) + // setPosition(const F32 x, const F32 y, const F32 z) + // getLocalMat4(LLMatrix4 &mat) + template<> template<> + void xform_test_object_t::test<2>() + { + LLMatrix4 llmat4; + LLXform xform_obj; + + F32 x = 3.6f; + F32 y = 5.5f; + F32 z = 4.2f; + F32 w = 0.f; + F32 posz = z + 2.122f; + LLVector3 vec(x, y, z); + xform_obj.setScale(x, y, z); + xform_obj.setPosition(x, y, posz); + ensure("setScale failed: ", xform_obj.getScale() == vec); + + vec.setVec(x, y, posz); + ensure("getPosition failed: ", xform_obj.getPosition() == vec); + + x = x * 2.f; + y = y + 2.3f; + z = posz * 4.f; + vec.setVec(x, y, z); + xform_obj.setPositionX(x); + xform_obj.setPositionY(y); + xform_obj.setPositionZ(z); + ensure("setPositionX/Y/Z failed: ", xform_obj.getPosition() == vec); + + xform_obj.setScaleChildOffset(true); + ensure("setScaleChildOffset failed: ", xform_obj.getScaleChildOffset()); + + vec.setVec(x, y, z); + + xform_obj.addPosition(vec); + vec += vec; + ensure("addPosition failed: ", xform_obj.getPosition() == vec); + + xform_obj.setScale(vec); + ensure("setScale vector failed: ", xform_obj.getScale() == vec); + + LLQuaternion quat(x, y, z, w); + xform_obj.setRotation(quat); + ensure("setRotation quat failed: ", xform_obj.getRotation() == quat); + + xform_obj.setRotation(x, y, z, w); + ensure("getRotation 2 failed: ", xform_obj.getRotation() == quat); + + xform_obj.setRotation(x, y, z); + quat.setQuat(x,y,z); + ensure("setRotation xyz failed: ", xform_obj.getRotation() == quat); + + // LLXform::setRotation(const F32 x, const F32 y, const F32 z) + // Does normalization + // LLXform::setRotation(const F32 x, const F32 y, const F32 z, const F32 s) + // Simply copies the individual values - does not do any normalization. + // Is that the expected behavior? + } + + // test cases for inline bool setParent(LLXform *parent) and getParent() fn. + template<> template<> + void xform_test_object_t::test<3>() + { + LLXform xform_obj; + LLXform par; + LLXform grandpar; + xform_obj.setParent(&par); + par.setParent(&grandpar); + ensure("setParent/getParent failed: ", &par == xform_obj.getParent()); + ensure("getRoot failed: ", &grandpar == xform_obj.getRoot()); + ensure("isRoot failed: ", grandpar.isRoot() && !par.isRoot() && !xform_obj.isRoot()); + ensure("isRootEdit failed: ", grandpar.isRootEdit() && !par.isRootEdit() && !xform_obj.isRootEdit()); + } + + template<> template<> + void xform_test_object_t::test<4>() + { + LLXform xform_obj; + xform_obj.setChanged(LLXform::TRANSLATED | LLXform::ROTATED | LLXform::SCALED); + ensure("setChanged/isChanged failed: ", xform_obj.isChanged()); + + xform_obj.clearChanged(LLXform::TRANSLATED | LLXform::ROTATED | LLXform::SCALED); + ensure("clearChanged failed: ", !xform_obj.isChanged()); + + LLVector3 llvect3(12.4f, -5.6f, 0.34f); + xform_obj.setScale(llvect3); + ensure("setScale did not set SCALED flag: ", xform_obj.isChanged(LLXform::SCALED)); + xform_obj.setPosition(1.2f, 2.3f, 3.4f); + ensure("setScale did not set TRANSLATED flag: ", xform_obj.isChanged(LLXform::TRANSLATED)); + ensure("TRANSLATED reset SCALED flag: ", xform_obj.isChanged(LLXform::TRANSLATED | LLXform::SCALED)); + xform_obj.clearChanged(LLXform::SCALED); + ensure("reset SCALED failed: ", !xform_obj.isChanged(LLXform::SCALED)); + xform_obj.setRotation(1, 2, 3, 4); + ensure("ROTATION flag not set ", xform_obj.isChanged(LLXform::TRANSLATED | LLXform::ROTATED)); + xform_obj.setScale(llvect3); + ensure("ROTATION flag not set ", xform_obj.isChanged(LLXform::MOVED)); + } + + //to test init() and getWorldMatrix() fns. + template<> template<> + void xform_test_object_t::test<5>() + { + LLXformMatrix formMatrix_obj; + formMatrix_obj.init(); + LLMatrix4 mat4_obj; + + ensure("1. The value is not NULL", 1.f == formMatrix_obj.getWorldMatrix().mMatrix[0][0]); + ensure("2. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[0][1]); + ensure("3. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[0][2]); + ensure("4. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[0][3]); + ensure("5. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[1][0]); + ensure("6. The value is not NULL", 1.f == formMatrix_obj.getWorldMatrix().mMatrix[1][1]); + ensure("7. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[1][2]); + ensure("8. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[1][3]); + ensure("9. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[2][0]); + ensure("10. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[2][1]); + ensure("11. The value is not NULL", 1.f == formMatrix_obj.getWorldMatrix().mMatrix[2][2]); + ensure("12. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[2][3]); + ensure("13. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[3][0]); + ensure("14. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[3][1]); + ensure("15. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[3][2]); + ensure("16. The value is not NULL", 1.f == formMatrix_obj.getWorldMatrix().mMatrix[3][3]); + } + + //to test mMin.clearVec() and mMax.clearVec() fns + template<> template<> + void xform_test_object_t::test<6>() + { + LLXformMatrix formMatrix_obj; + formMatrix_obj.init(); + LLVector3 llmin_vec3; + LLVector3 llmax_vec3; + formMatrix_obj.getMinMax(llmin_vec3, llmax_vec3); + ensure("1. The value is not NULL", 0.f == llmin_vec3.mV[0]); + ensure("2. The value is not NULL", 0.f == llmin_vec3.mV[1]); + ensure("3. The value is not NULL", 0.f == llmin_vec3.mV[2]); + ensure("4. The value is not NULL", 0.f == llmin_vec3.mV[0]); + ensure("5. The value is not NULL", 0.f == llmin_vec3.mV[1]); + ensure("6. The value is not NULL", 0.f == llmin_vec3.mV[2]); + } + + //test case of update() fn. + template<> template<> + void xform_test_object_t::test<7>() + { + LLXformMatrix formMatrix_obj; + + LLXformMatrix parent; + LLVector3 llvecpos(1.0, 2.0, 3.0); + LLVector3 llvecpospar(10.0, 20.0, 30.0); + formMatrix_obj.setPosition(llvecpos); + parent.setPosition(llvecpospar); + + LLVector3 llvecparentscale(1.0, 2.0, 0); + parent.setScaleChildOffset(true); + parent.setScale(llvecparentscale); + + LLQuaternion quat(1, 2, 3, 4); + LLQuaternion quatparent(5, 6, 7, 8); + formMatrix_obj.setRotation(quat); + parent.setRotation(quatparent); + formMatrix_obj.setParent(&parent); + + parent.update(); + formMatrix_obj.update(); + + LLVector3 worldPos = llvecpos; + worldPos.scaleVec(llvecparentscale); + worldPos *= quatparent; + worldPos += llvecpospar; + + LLQuaternion worldRot = quat * quatparent; + + ensure("getWorldPosition failed: ", formMatrix_obj.getWorldPosition() == worldPos); + ensure("getWorldRotation failed: ", formMatrix_obj.getWorldRotation() == worldRot); + + ensure("getWorldPosition for parent failed: ", parent.getWorldPosition() == llvecpospar); + ensure("getWorldRotation for parent failed: ", parent.getWorldRotation() == quatparent); + } +} diff --git a/indra/llmath/v2math.cpp b/indra/llmath/v2math.cpp index 22b37628d8..4649e13376 100644 --- a/indra/llmath/v2math.cpp +++ b/indra/llmath/v2math.cpp @@ -1,25 +1,25 @@ -/** +/** * @file v2math.cpp * @brief LLVector2 class implementation. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -45,82 +45,82 @@ LLVector2 LLVector2::zero(0,0); // Returns true if data changed bool LLVector2::abs() { - bool ret{ false }; + bool ret{ false }; + + if (mV[0] < 0.f) { mV[0] = -mV[0]; ret = true; } + if (mV[1] < 0.f) { mV[1] = -mV[1]; ret = true; } - if (mV[0] < 0.f) { mV[0] = -mV[0]; ret = true; } - if (mV[1] < 0.f) { mV[1] = -mV[1]; ret = true; } - - return ret; + return ret; } F32 angle_between(const LLVector2& a, const LLVector2& b) { - LLVector2 an = a; - LLVector2 bn = b; - an.normVec(); - bn.normVec(); - F32 cosine = an * bn; - F32 angle = (cosine >= 1.0f) ? 0.0f : - (cosine <= -1.0f) ? F_PI : - acos(cosine); - return angle; + LLVector2 an = a; + LLVector2 bn = b; + an.normVec(); + bn.normVec(); + F32 cosine = an * bn; + F32 angle = (cosine >= 1.0f) ? 0.0f : + (cosine <= -1.0f) ? F_PI : + acos(cosine); + return angle; } bool are_parallel(const LLVector2 &a, const LLVector2 &b, float epsilon) { - LLVector2 an = a; - LLVector2 bn = b; - an.normVec(); - bn.normVec(); - F32 dot = an * bn; - if ( (1.0f - fabs(dot)) < epsilon) - { - return true; - } - return false; + LLVector2 an = a; + LLVector2 bn = b; + an.normVec(); + bn.normVec(); + F32 dot = an * bn; + if ( (1.0f - fabs(dot)) < epsilon) + { + return true; + } + return false; } -F32 dist_vec(const LLVector2 &a, const LLVector2 &b) +F32 dist_vec(const LLVector2 &a, const LLVector2 &b) { - F32 x = a.mV[0] - b.mV[0]; - F32 y = a.mV[1] - b.mV[1]; - return (F32) sqrt( x*x + y*y ); + F32 x = a.mV[0] - b.mV[0]; + F32 y = a.mV[1] - b.mV[1]; + return (F32) sqrt( x*x + y*y ); } -F32 dist_vec_squared(const LLVector2 &a, const LLVector2 &b) +F32 dist_vec_squared(const LLVector2 &a, const LLVector2 &b) { - F32 x = a.mV[0] - b.mV[0]; - F32 y = a.mV[1] - b.mV[1]; - return x*x + y*y; + F32 x = a.mV[0] - b.mV[0]; + F32 y = a.mV[1] - b.mV[1]; + return x*x + y*y; } -F32 dist_vec_squared2D(const LLVector2 &a, const LLVector2 &b) +F32 dist_vec_squared2D(const LLVector2 &a, const LLVector2 &b) { - F32 x = a.mV[0] - b.mV[0]; - F32 y = a.mV[1] - b.mV[1]; - return x*x + y*y; + F32 x = a.mV[0] - b.mV[0]; + F32 y = a.mV[1] - b.mV[1]; + return x*x + y*y; } LLVector2 lerp(const LLVector2 &a, const LLVector2 &b, F32 u) { - return LLVector2( - a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u, - a.mV[VY] + (b.mV[VY] - a.mV[VY]) * u ); + return LLVector2( + a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u, + a.mV[VY] + (b.mV[VY] - a.mV[VY]) * u ); } LLSD LLVector2::getValue() const { - LLSD ret; - ret[0] = mV[0]; - ret[1] = mV[1]; - return ret; + LLSD ret; + ret[0] = mV[0]; + ret[1] = mV[1]; + return ret; } void LLVector2::setValue(const LLSD& sd) { - mV[0] = (F32) sd[0].asReal(); - mV[1] = (F32) sd[1].asReal(); + mV[0] = (F32) sd[0].asReal(); + mV[1] = (F32) sd[1].asReal(); } diff --git a/indra/llmath/v2math.h b/indra/llmath/v2math.h index b1ac0b3340..a61c946304 100644 --- a/indra/llmath/v2math.h +++ b/indra/llmath/v2math.h @@ -1,25 +1,25 @@ -/** +/** * @file v2math.h * @brief LLVector2 class header file. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -40,110 +40,110 @@ static const U32 LENGTHOFVECTOR2 = 2; class LLVector2 { - public: - F32 mV[LENGTHOFVECTOR2]; + public: + F32 mV[LENGTHOFVECTOR2]; - static LLVector2 zero; + static LLVector2 zero; - LLVector2(); // Initializes LLVector2 to (0, 0) - LLVector2(F32 x, F32 y); // Initializes LLVector2 to (x. y) - LLVector2(const F32 *vec); // Initializes LLVector2 to (vec[0]. vec[1]) + LLVector2(); // Initializes LLVector2 to (0, 0) + LLVector2(F32 x, F32 y); // Initializes LLVector2 to (x. y) + LLVector2(const F32 *vec); // Initializes LLVector2 to (vec[0]. vec[1]) explicit LLVector2(const LLVector3 &vec); // Initializes LLVector2 to (vec[0]. vec[1]) explicit LLVector2(const LLSD &sd); - - // Clears LLVector2 to (0, 0). DEPRECATED - prefer zeroVec. - void clear(); - void setZero(); - void clearVec(); // deprecated - void zeroVec(); // deprecated - - void set(F32 x, F32 y); // Sets LLVector2 to (x, y) - void set(const LLVector2 &vec); // Sets LLVector2 to vec - void set(const F32 *vec); // Sets LLVector2 to vec - - LLSD getValue() const; - void setValue(const LLSD& sd); - - void setVec(F32 x, F32 y); // deprecated - void setVec(const LLVector2 &vec); // deprecated - void setVec(const F32 *vec); // deprecated - - inline bool isFinite() const; // checks to see if all values of LLVector2 are finite - - F32 length() const; // Returns magnitude of LLVector2 - F32 lengthSquared() const; // Returns magnitude squared of LLVector2 - F32 normalize(); // Normalizes and returns the magnitude of LLVector2 - - F32 magVec() const; // deprecated - F32 magVecSquared() const; // deprecated - F32 normVec(); // deprecated - - bool abs(); // sets all values to absolute value of original value (first octant), returns true if changed - - const LLVector2& scaleVec(const LLVector2& vec); // scales per component by vec - - bool isNull(); // Returns true if vector has a _very_small_ length - bool isExactlyZero() const { return !mV[VX] && !mV[VY]; } - - F32 operator[](int idx) const { return mV[idx]; } - F32 &operator[](int idx) { return mV[idx]; } - - friend bool operator<(const LLVector2 &a, const LLVector2 &b); // For sorting. x is "more significant" than y - friend LLVector2 operator+(const LLVector2 &a, const LLVector2 &b); // Return vector a + b - friend LLVector2 operator-(const LLVector2 &a, const LLVector2 &b); // Return vector a minus b - friend F32 operator*(const LLVector2 &a, const LLVector2 &b); // Return a dot b - friend LLVector2 operator%(const LLVector2 &a, const LLVector2 &b); // Return a cross b - friend LLVector2 operator/(const LLVector2 &a, F32 k); // Return a divided by scaler k - friend LLVector2 operator*(const LLVector2 &a, F32 k); // Return a times scaler k - friend LLVector2 operator*(F32 k, const LLVector2 &a); // Return a times scaler k - friend bool operator==(const LLVector2 &a, const LLVector2 &b); // Return a == b - friend bool operator!=(const LLVector2 &a, const LLVector2 &b); // Return a != b - - friend const LLVector2& operator+=(LLVector2 &a, const LLVector2 &b); // Return vector a + b - friend const LLVector2& operator-=(LLVector2 &a, const LLVector2 &b); // Return vector a minus b - friend const LLVector2& operator%=(LLVector2 &a, const LLVector2 &b); // Return a cross b - friend const LLVector2& operator*=(LLVector2 &a, F32 k); // Return a times scaler k - friend const LLVector2& operator/=(LLVector2 &a, F32 k); // Return a divided by scaler k - - friend LLVector2 operator-(const LLVector2 &a); // Return vector -a - - friend std::ostream& operator<<(std::ostream& s, const LLVector2 &a); // Stream a + + // Clears LLVector2 to (0, 0). DEPRECATED - prefer zeroVec. + void clear(); + void setZero(); + void clearVec(); // deprecated + void zeroVec(); // deprecated + + void set(F32 x, F32 y); // Sets LLVector2 to (x, y) + void set(const LLVector2 &vec); // Sets LLVector2 to vec + void set(const F32 *vec); // Sets LLVector2 to vec + + LLSD getValue() const; + void setValue(const LLSD& sd); + + void setVec(F32 x, F32 y); // deprecated + void setVec(const LLVector2 &vec); // deprecated + void setVec(const F32 *vec); // deprecated + + inline bool isFinite() const; // checks to see if all values of LLVector2 are finite + + F32 length() const; // Returns magnitude of LLVector2 + F32 lengthSquared() const; // Returns magnitude squared of LLVector2 + F32 normalize(); // Normalizes and returns the magnitude of LLVector2 + + F32 magVec() const; // deprecated + F32 magVecSquared() const; // deprecated + F32 normVec(); // deprecated + + bool abs(); // sets all values to absolute value of original value (first octant), returns true if changed + + const LLVector2& scaleVec(const LLVector2& vec); // scales per component by vec + + bool isNull(); // Returns true if vector has a _very_small_ length + bool isExactlyZero() const { return !mV[VX] && !mV[VY]; } + + F32 operator[](int idx) const { return mV[idx]; } + F32 &operator[](int idx) { return mV[idx]; } + + friend bool operator<(const LLVector2 &a, const LLVector2 &b); // For sorting. x is "more significant" than y + friend LLVector2 operator+(const LLVector2 &a, const LLVector2 &b); // Return vector a + b + friend LLVector2 operator-(const LLVector2 &a, const LLVector2 &b); // Return vector a minus b + friend F32 operator*(const LLVector2 &a, const LLVector2 &b); // Return a dot b + friend LLVector2 operator%(const LLVector2 &a, const LLVector2 &b); // Return a cross b + friend LLVector2 operator/(const LLVector2 &a, F32 k); // Return a divided by scaler k + friend LLVector2 operator*(const LLVector2 &a, F32 k); // Return a times scaler k + friend LLVector2 operator*(F32 k, const LLVector2 &a); // Return a times scaler k + friend bool operator==(const LLVector2 &a, const LLVector2 &b); // Return a == b + friend bool operator!=(const LLVector2 &a, const LLVector2 &b); // Return a != b + + friend const LLVector2& operator+=(LLVector2 &a, const LLVector2 &b); // Return vector a + b + friend const LLVector2& operator-=(LLVector2 &a, const LLVector2 &b); // Return vector a minus b + friend const LLVector2& operator%=(LLVector2 &a, const LLVector2 &b); // Return a cross b + friend const LLVector2& operator*=(LLVector2 &a, F32 k); // Return a times scaler k + friend const LLVector2& operator/=(LLVector2 &a, F32 k); // Return a divided by scaler k + + friend LLVector2 operator-(const LLVector2 &a); // Return vector -a + + friend std::ostream& operator<<(std::ostream& s, const LLVector2 &a); // Stream a }; -// Non-member functions +// Non-member functions -F32 angle_between(const LLVector2 &a, const LLVector2 &b); // Returns angle (radians) between a and b -bool are_parallel(const LLVector2 &a, const LLVector2 &b, F32 epsilon=F_APPROXIMATELY_ZERO); // Returns true if a and b are very close to parallel -F32 dist_vec(const LLVector2 &a, const LLVector2 &b); // Returns distance between a and b -F32 dist_vec_squared(const LLVector2 &a, const LLVector2 &b);// Returns distance squared between a and b -F32 dist_vec_squared2D(const LLVector2 &a, const LLVector2 &b);// Returns distance squared between a and b ignoring Z component +F32 angle_between(const LLVector2 &a, const LLVector2 &b); // Returns angle (radians) between a and b +bool are_parallel(const LLVector2 &a, const LLVector2 &b, F32 epsilon=F_APPROXIMATELY_ZERO); // Returns true if a and b are very close to parallel +F32 dist_vec(const LLVector2 &a, const LLVector2 &b); // Returns distance between a and b +F32 dist_vec_squared(const LLVector2 &a, const LLVector2 &b);// Returns distance squared between a and b +F32 dist_vec_squared2D(const LLVector2 &a, const LLVector2 &b);// Returns distance squared between a and b ignoring Z component LLVector2 lerp(const LLVector2 &a, const LLVector2 &b, F32 u); // Returns a vector that is a linear interpolation between a and b // Constructors inline LLVector2::LLVector2(void) { - mV[VX] = 0.f; - mV[VY] = 0.f; + mV[VX] = 0.f; + mV[VY] = 0.f; } inline LLVector2::LLVector2(F32 x, F32 y) { - mV[VX] = x; - mV[VY] = y; + mV[VX] = x; + mV[VY] = y; } inline LLVector2::LLVector2(const F32 *vec) { - mV[VX] = vec[VX]; - mV[VY] = vec[VY]; + mV[VX] = vec[VX]; + mV[VY] = vec[VY]; } inline LLVector2::LLVector2(const LLVector3 &vec) { - mV[VX] = vec.mV[VX]; - mV[VY] = vec.mV[VY]; + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; } inline LLVector2::LLVector2(const LLSD &sd) @@ -153,70 +153,70 @@ inline LLVector2::LLVector2(const LLSD &sd) // Clear and Assignment Functions -inline void LLVector2::clear(void) +inline void LLVector2::clear(void) { - mV[VX] = 0.f; - mV[VY] = 0.f; + mV[VX] = 0.f; + mV[VY] = 0.f; } -inline void LLVector2::setZero(void) +inline void LLVector2::setZero(void) { - mV[VX] = 0.f; - mV[VY] = 0.f; + mV[VX] = 0.f; + mV[VY] = 0.f; } // deprecated -inline void LLVector2::clearVec(void) +inline void LLVector2::clearVec(void) { - mV[VX] = 0.f; - mV[VY] = 0.f; + mV[VX] = 0.f; + mV[VY] = 0.f; } // deprecated -inline void LLVector2::zeroVec(void) +inline void LLVector2::zeroVec(void) { - mV[VX] = 0.f; - mV[VY] = 0.f; + mV[VX] = 0.f; + mV[VY] = 0.f; } -inline void LLVector2::set(F32 x, F32 y) +inline void LLVector2::set(F32 x, F32 y) { - mV[VX] = x; - mV[VY] = y; + mV[VX] = x; + mV[VY] = y; } -inline void LLVector2::set(const LLVector2 &vec) +inline void LLVector2::set(const LLVector2 &vec) { - mV[VX] = vec.mV[VX]; - mV[VY] = vec.mV[VY]; + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; } -inline void LLVector2::set(const F32 *vec) +inline void LLVector2::set(const F32 *vec) { - mV[VX] = vec[VX]; - mV[VY] = vec[VY]; + mV[VX] = vec[VX]; + mV[VY] = vec[VY]; } // deprecated -inline void LLVector2::setVec(F32 x, F32 y) +inline void LLVector2::setVec(F32 x, F32 y) { - mV[VX] = x; - mV[VY] = y; + mV[VX] = x; + mV[VY] = y; } // deprecated -inline void LLVector2::setVec(const LLVector2 &vec) +inline void LLVector2::setVec(const LLVector2 &vec) { - mV[VX] = vec.mV[VX]; - mV[VY] = vec.mV[VY]; + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; } // deprecated -inline void LLVector2::setVec(const F32 *vec) +inline void LLVector2::setVec(const F32 *vec) { - mV[VX] = vec[VX]; - mV[VY] = vec[VY]; + mV[VX] = vec[VX]; + mV[VY] = vec[VY]; } @@ -224,217 +224,217 @@ inline void LLVector2::setVec(const F32 *vec) inline F32 LLVector2::length(void) const { - return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]); + return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]); } inline F32 LLVector2::lengthSquared(void) const { - return mV[0]*mV[0] + mV[1]*mV[1]; + return mV[0]*mV[0] + mV[1]*mV[1]; } inline F32 LLVector2::normalize(void) { - F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]); - F32 oomag; + F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]); + F32 oomag; - if (mag > FP_MAG_THRESHOLD) - { - oomag = 1.f/mag; - mV[0] *= oomag; - mV[1] *= oomag; - } - else - { - mV[0] = 0.f; - mV[1] = 0.f; - mag = 0; - } - return (mag); + if (mag > FP_MAG_THRESHOLD) + { + oomag = 1.f/mag; + mV[0] *= oomag; + mV[1] *= oomag; + } + else + { + mV[0] = 0.f; + mV[1] = 0.f; + mag = 0; + } + return (mag); } // checker inline bool LLVector2::isFinite() const { - return (llfinite(mV[VX]) && llfinite(mV[VY])); + return (llfinite(mV[VX]) && llfinite(mV[VY])); } // deprecated -inline F32 LLVector2::magVec(void) const +inline F32 LLVector2::magVec(void) const { - return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]); + return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]); } // deprecated -inline F32 LLVector2::magVecSquared(void) const +inline F32 LLVector2::magVecSquared(void) const { - return mV[0]*mV[0] + mV[1]*mV[1]; + return mV[0]*mV[0] + mV[1]*mV[1]; } // deprecated -inline F32 LLVector2::normVec(void) +inline F32 LLVector2::normVec(void) { - F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]); - F32 oomag; + F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]); + F32 oomag; - if (mag > FP_MAG_THRESHOLD) - { - oomag = 1.f/mag; - mV[0] *= oomag; - mV[1] *= oomag; - } - else - { - mV[0] = 0.f; - mV[1] = 0.f; - mag = 0; - } - return (mag); + if (mag > FP_MAG_THRESHOLD) + { + oomag = 1.f/mag; + mV[0] *= oomag; + mV[1] *= oomag; + } + else + { + mV[0] = 0.f; + mV[1] = 0.f; + mag = 0; + } + return (mag); } -inline const LLVector2& LLVector2::scaleVec(const LLVector2& vec) +inline const LLVector2& LLVector2::scaleVec(const LLVector2& vec) { - mV[VX] *= vec.mV[VX]; - mV[VY] *= vec.mV[VY]; + mV[VX] *= vec.mV[VX]; + mV[VY] *= vec.mV[VY]; - return *this; + return *this; } -inline bool LLVector2::isNull() +inline bool LLVector2::isNull() { - if ( F_APPROXIMATELY_ZERO > mV[VX]*mV[VX] + mV[VY]*mV[VY] ) - { - return true; - } - return false; + if ( F_APPROXIMATELY_ZERO > mV[VX]*mV[VX] + mV[VY]*mV[VY] ) + { + return true; + } + return false; } // LLVector2 Operators // For sorting. By convention, x is "more significant" than y. -inline bool operator<(const LLVector2 &a, const LLVector2 &b) +inline bool operator<(const LLVector2 &a, const LLVector2 &b) { - if( a.mV[VX] == b.mV[VX] ) - { - return a.mV[VY] < b.mV[VY]; - } - else - { - return a.mV[VX] < b.mV[VX]; - } + if( a.mV[VX] == b.mV[VX] ) + { + return a.mV[VY] < b.mV[VY]; + } + else + { + return a.mV[VX] < b.mV[VX]; + } } inline LLVector2 operator+(const LLVector2 &a, const LLVector2 &b) { - LLVector2 c(a); - return c += b; + LLVector2 c(a); + return c += b; } inline LLVector2 operator-(const LLVector2 &a, const LLVector2 &b) { - LLVector2 c(a); - return c -= b; + LLVector2 c(a); + return c -= b; } inline F32 operator*(const LLVector2 &a, const LLVector2 &b) { - return (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1]); + return (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1]); } inline LLVector2 operator%(const LLVector2 &a, const LLVector2 &b) { - return LLVector2(a.mV[0]*b.mV[1] - b.mV[0]*a.mV[1], a.mV[1]*b.mV[0] - b.mV[1]*a.mV[0]); + return LLVector2(a.mV[0]*b.mV[1] - b.mV[0]*a.mV[1], a.mV[1]*b.mV[0] - b.mV[1]*a.mV[0]); } inline LLVector2 operator/(const LLVector2 &a, F32 k) { - F32 t = 1.f / k; - return LLVector2( a.mV[0] * t, a.mV[1] * t ); + F32 t = 1.f / k; + return LLVector2( a.mV[0] * t, a.mV[1] * t ); } inline LLVector2 operator*(const LLVector2 &a, F32 k) { - return LLVector2( a.mV[0] * k, a.mV[1] * k ); + return LLVector2( a.mV[0] * k, a.mV[1] * k ); } inline LLVector2 operator*(F32 k, const LLVector2 &a) { - return LLVector2( a.mV[0] * k, a.mV[1] * k ); + return LLVector2( a.mV[0] * k, a.mV[1] * k ); } inline bool operator==(const LLVector2 &a, const LLVector2 &b) { - return ( (a.mV[0] == b.mV[0]) - &&(a.mV[1] == b.mV[1])); + return ( (a.mV[0] == b.mV[0]) + &&(a.mV[1] == b.mV[1])); } inline bool operator!=(const LLVector2 &a, const LLVector2 &b) { - return ( (a.mV[0] != b.mV[0]) - ||(a.mV[1] != b.mV[1])); + return ( (a.mV[0] != b.mV[0]) + ||(a.mV[1] != b.mV[1])); } inline const LLVector2& operator+=(LLVector2 &a, const LLVector2 &b) { - a.mV[0] += b.mV[0]; - a.mV[1] += b.mV[1]; - return a; + a.mV[0] += b.mV[0]; + a.mV[1] += b.mV[1]; + return a; } inline const LLVector2& operator-=(LLVector2 &a, const LLVector2 &b) { - a.mV[0] -= b.mV[0]; - a.mV[1] -= b.mV[1]; - return a; + a.mV[0] -= b.mV[0]; + a.mV[1] -= b.mV[1]; + return a; } inline const LLVector2& operator%=(LLVector2 &a, const LLVector2 &b) { - LLVector2 ret(a.mV[0]*b.mV[1] - b.mV[0]*a.mV[1], a.mV[1]*b.mV[0] - b.mV[1]*a.mV[0]); - a = ret; - return a; + LLVector2 ret(a.mV[0]*b.mV[1] - b.mV[0]*a.mV[1], a.mV[1]*b.mV[0] - b.mV[1]*a.mV[0]); + a = ret; + return a; } inline const LLVector2& operator*=(LLVector2 &a, F32 k) { - a.mV[0] *= k; - a.mV[1] *= k; - return a; + a.mV[0] *= k; + a.mV[1] *= k; + return a; } inline const LLVector2& operator/=(LLVector2 &a, F32 k) { - F32 t = 1.f / k; - a.mV[0] *= t; - a.mV[1] *= t; - return a; + F32 t = 1.f / k; + a.mV[0] *= t; + a.mV[1] *= t; + return a; } inline LLVector2 operator-(const LLVector2 &a) { - return LLVector2( -a.mV[0], -a.mV[1] ); + return LLVector2( -a.mV[0], -a.mV[1] ); } inline void update_min_max(LLVector2& min, LLVector2& max, const LLVector2& pos) { - for (U32 i = 0; i < 2; i++) - { - if (min.mV[i] > pos.mV[i]) - { - min.mV[i] = pos.mV[i]; - } - if (max.mV[i] < pos.mV[i]) - { - max.mV[i] = pos.mV[i]; - } - } + for (U32 i = 0; i < 2; i++) + { + if (min.mV[i] > pos.mV[i]) + { + min.mV[i] = pos.mV[i]; + } + if (max.mV[i] < pos.mV[i]) + { + max.mV[i] = pos.mV[i]; + } + } } -inline std::ostream& operator<<(std::ostream& s, const LLVector2 &a) +inline std::ostream& operator<<(std::ostream& s, const LLVector2 &a) { - s << "{ " << a.mV[VX] << ", " << a.mV[VY] << " }"; - return s; + s << "{ " << a.mV[VX] << ", " << a.mV[VY] << " }"; + return s; } #endif diff --git a/indra/llmath/v3color.cpp b/indra/llmath/v3color.cpp index d38f48b11e..9fe9c8d5e5 100644 --- a/indra/llmath/v3color.cpp +++ b/indra/llmath/v3color.cpp @@ -1,25 +1,25 @@ -/** +/** * @file v3color.cpp * @brief LLColor3 class implementation. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -36,118 +36,118 @@ LLColor3 LLColor3::grey (0.5f, 0.5f, 0.5f); LLColor3::LLColor3(const LLColor4 &a) { - mV[0] = a.mV[0]; - mV[1] = a.mV[1]; - mV[2] = a.mV[2]; + mV[0] = a.mV[0]; + mV[1] = a.mV[1]; + mV[2] = a.mV[2]; } LLColor3::LLColor3(const LLVector4 &a) { - mV[0] = a.mV[0]; - mV[1] = a.mV[1]; - mV[2] = a.mV[2]; + mV[0] = a.mV[0]; + mV[1] = a.mV[1]; + mV[2] = a.mV[2]; } LLColor3::LLColor3(const LLSD &sd) { - setValue(sd); + setValue(sd); } -const LLColor3& LLColor3::operator=(const LLColor4 &a) +const LLColor3& LLColor3::operator=(const LLColor4 &a) { - mV[0] = a.mV[0]; - mV[1] = a.mV[1]; - mV[2] = a.mV[2]; - return (*this); + mV[0] = a.mV[0]; + mV[1] = a.mV[1]; + mV[2] = a.mV[2]; + return (*this); } -std::ostream& operator<<(std::ostream& s, const LLColor3 &a) +std::ostream& operator<<(std::ostream& s, const LLColor3 &a) { - s << "{ " << a.mV[VX] << ", " << a.mV[VY] << ", " << a.mV[VZ] << " }"; - return s; + s << "{ " << a.mV[VX] << ", " << a.mV[VY] << ", " << a.mV[VZ] << " }"; + return s; } static F32 hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn ) { - if ( valHUeIn < 0.0f ) valHUeIn += 1.0f; - if ( valHUeIn > 1.0f ) valHUeIn -= 1.0f; - if ( ( 6.0f * valHUeIn ) < 1.0f ) return ( val1In + ( val2In - val1In ) * 6.0f * valHUeIn ); - if ( ( 2.0f * valHUeIn ) < 1.0f ) return ( val2In ); - if ( ( 3.0f * valHUeIn ) < 2.0f ) return ( val1In + ( val2In - val1In ) * ( ( 2.0f / 3.0f ) - valHUeIn ) * 6.0f ); - return ( val1In ); + if ( valHUeIn < 0.0f ) valHUeIn += 1.0f; + if ( valHUeIn > 1.0f ) valHUeIn -= 1.0f; + if ( ( 6.0f * valHUeIn ) < 1.0f ) return ( val1In + ( val2In - val1In ) * 6.0f * valHUeIn ); + if ( ( 2.0f * valHUeIn ) < 1.0f ) return ( val2In ); + if ( ( 3.0f * valHUeIn ) < 2.0f ) return ( val1In + ( val2In - val1In ) * ( ( 2.0f / 3.0f ) - valHUeIn ) * 6.0f ); + return ( val1In ); } void LLColor3::setHSL ( F32 hValIn, F32 sValIn, F32 lValIn) { - if ( sValIn < 0.00001f ) - { - mV[VRED] = lValIn; - mV[VGREEN] = lValIn; - mV[VBLUE] = lValIn; - } - else - { - F32 interVal1; - F32 interVal2; - - if ( lValIn < 0.5f ) - interVal2 = lValIn * ( 1.0f + sValIn ); - else - interVal2 = ( lValIn + sValIn ) - ( sValIn * lValIn ); - - interVal1 = 2.0f * lValIn - interVal2; - - mV[VRED] = hueToRgb ( interVal1, interVal2, hValIn + ( 1.f / 3.f ) ); - mV[VGREEN] = hueToRgb ( interVal1, interVal2, hValIn ); - mV[VBLUE] = hueToRgb ( interVal1, interVal2, hValIn - ( 1.f / 3.f ) ); - } + if ( sValIn < 0.00001f ) + { + mV[VRED] = lValIn; + mV[VGREEN] = lValIn; + mV[VBLUE] = lValIn; + } + else + { + F32 interVal1; + F32 interVal2; + + if ( lValIn < 0.5f ) + interVal2 = lValIn * ( 1.0f + sValIn ); + else + interVal2 = ( lValIn + sValIn ) - ( sValIn * lValIn ); + + interVal1 = 2.0f * lValIn - interVal2; + + mV[VRED] = hueToRgb ( interVal1, interVal2, hValIn + ( 1.f / 3.f ) ); + mV[VGREEN] = hueToRgb ( interVal1, interVal2, hValIn ); + mV[VBLUE] = hueToRgb ( interVal1, interVal2, hValIn - ( 1.f / 3.f ) ); + } } void LLColor3::calcHSL(F32* hue, F32* saturation, F32* luminance) const { - F32 var_R = mV[VRED]; - F32 var_G = mV[VGREEN]; - F32 var_B = mV[VBLUE]; - - F32 var_Min = ( var_R < ( var_G < var_B ? var_G : var_B ) ? var_R : ( var_G < var_B ? var_G : var_B ) ); - F32 var_Max = ( var_R > ( var_G > var_B ? var_G : var_B ) ? var_R : ( var_G > var_B ? var_G : var_B ) ); - - F32 del_Max = var_Max - var_Min; - - F32 L = ( var_Max + var_Min ) / 2.0f; - F32 H = 0.0f; - F32 S = 0.0f; - - if ( del_Max == 0.0f ) - { - H = 0.0f; - S = 0.0f; - } - else - { - if ( L < 0.5 ) - S = del_Max / ( var_Max + var_Min ); - else - S = del_Max / ( 2.0f - var_Max - var_Min ); - - F32 del_R = ( ( ( var_Max - var_R ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max; - F32 del_G = ( ( ( var_Max - var_G ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max; - F32 del_B = ( ( ( var_Max - var_B ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max; - - if ( var_R >= var_Max ) - H = del_B - del_G; - else - if ( var_G >= var_Max ) - H = ( 1.0f / 3.0f ) + del_R - del_B; - else - if ( var_B >= var_Max ) - H = ( 2.0f / 3.0f ) + del_G - del_R; - - if ( H < 0.0f ) H += 1.0f; - if ( H > 1.0f ) H -= 1.0f; - } - - if (hue) *hue = H; - if (saturation) *saturation = S; - if (luminance) *luminance = L; + F32 var_R = mV[VRED]; + F32 var_G = mV[VGREEN]; + F32 var_B = mV[VBLUE]; + + F32 var_Min = ( var_R < ( var_G < var_B ? var_G : var_B ) ? var_R : ( var_G < var_B ? var_G : var_B ) ); + F32 var_Max = ( var_R > ( var_G > var_B ? var_G : var_B ) ? var_R : ( var_G > var_B ? var_G : var_B ) ); + + F32 del_Max = var_Max - var_Min; + + F32 L = ( var_Max + var_Min ) / 2.0f; + F32 H = 0.0f; + F32 S = 0.0f; + + if ( del_Max == 0.0f ) + { + H = 0.0f; + S = 0.0f; + } + else + { + if ( L < 0.5 ) + S = del_Max / ( var_Max + var_Min ); + else + S = del_Max / ( 2.0f - var_Max - var_Min ); + + F32 del_R = ( ( ( var_Max - var_R ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max; + F32 del_G = ( ( ( var_Max - var_G ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max; + F32 del_B = ( ( ( var_Max - var_B ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max; + + if ( var_R >= var_Max ) + H = del_B - del_G; + else + if ( var_G >= var_Max ) + H = ( 1.0f / 3.0f ) + del_R - del_B; + else + if ( var_B >= var_Max ) + H = ( 2.0f / 3.0f ) + del_G - del_R; + + if ( H < 0.0f ) H += 1.0f; + if ( H > 1.0f ) H -= 1.0f; + } + + if (hue) *hue = H; + if (saturation) *saturation = S; + if (luminance) *luminance = L; } diff --git a/indra/llmath/v3color.h b/indra/llmath/v3color.h index d925f56e97..ea26e9eb76 100644 --- a/indra/llmath/v3color.h +++ b/indra/llmath/v3color.h @@ -1,25 +1,25 @@ -/** +/** * @file v3color.h * @brief LLColor3 class header file. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -43,52 +43,52 @@ static const U32 LENGTHOFCOLOR3 = 3; class LLColor3 { public: - F32 mV[LENGTHOFCOLOR3]; + F32 mV[LENGTHOFCOLOR3]; - static LLColor3 white; - static LLColor3 black; - static LLColor3 grey; + static LLColor3 white; + static LLColor3 black; + static LLColor3 grey; public: - LLColor3(); // Initializes LLColor3 to (0, 0, 0) - LLColor3(F32 r, F32 g, F32 b); // Initializes LLColor3 to (r, g, b) - LLColor3(const F32 *vec); // Initializes LLColor3 to (vec[0]. vec[1], vec[2]) - LLColor3(const char *color_string); // html format color ie "#FFDDEE" - explicit LLColor3(const LLColor4& color4); // "explicit" to avoid automatic conversion - explicit LLColor3(const LLVector4& vector4); // "explicit" to avoid automatic conversion - LLColor3(const LLSD& sd); - - - LLSD getValue() const - { - LLSD ret; - ret[0] = mV[0]; - ret[1] = mV[1]; - ret[2] = mV[2]; - return ret; - } - - void setValue(const LLSD& sd) - { - mV[0] = (F32) sd[0].asReal();; - mV[1] = (F32) sd[1].asReal();; - mV[2] = (F32) sd[2].asReal();; - } - - void setHSL(F32 hue, F32 saturation, F32 luminance); - void calcHSL(F32* hue, F32* saturation, F32* luminance) const; - - const LLColor3& setToBlack(); // Clears LLColor3 to (0, 0, 0) - const LLColor3& setToWhite(); // Zero LLColor3 to (0, 0, 0) - - const LLColor3& setVec(F32 x, F32 y, F32 z); // deprecated - const LLColor3& setVec(const LLColor3 &vec); // deprecated - const LLColor3& setVec(const F32 *vec); // deprecated - - const LLColor3& set(F32 x, F32 y, F32 z); // Sets LLColor3 to (x, y, z) - const LLColor3& set(const LLColor3 &vec); // Sets LLColor3 to vec - const LLColor3& set(const F32 *vec); // Sets LLColor3 to vec - + LLColor3(); // Initializes LLColor3 to (0, 0, 0) + LLColor3(F32 r, F32 g, F32 b); // Initializes LLColor3 to (r, g, b) + LLColor3(const F32 *vec); // Initializes LLColor3 to (vec[0]. vec[1], vec[2]) + LLColor3(const char *color_string); // html format color ie "#FFDDEE" + explicit LLColor3(const LLColor4& color4); // "explicit" to avoid automatic conversion + explicit LLColor3(const LLVector4& vector4); // "explicit" to avoid automatic conversion + LLColor3(const LLSD& sd); + + + LLSD getValue() const + { + LLSD ret; + ret[0] = mV[0]; + ret[1] = mV[1]; + ret[2] = mV[2]; + return ret; + } + + void setValue(const LLSD& sd) + { + mV[0] = (F32) sd[0].asReal();; + mV[1] = (F32) sd[1].asReal();; + mV[2] = (F32) sd[2].asReal();; + } + + void setHSL(F32 hue, F32 saturation, F32 luminance); + void calcHSL(F32* hue, F32* saturation, F32* luminance) const; + + const LLColor3& setToBlack(); // Clears LLColor3 to (0, 0, 0) + const LLColor3& setToWhite(); // Zero LLColor3 to (0, 0, 0) + + const LLColor3& setVec(F32 x, F32 y, F32 z); // deprecated + const LLColor3& setVec(const LLColor3 &vec); // deprecated + const LLColor3& setVec(const F32 *vec); // deprecated + + const LLColor3& set(F32 x, F32 y, F32 z); // Sets LLColor3 to (x, y, z) + const LLColor3& set(const LLColor3 &vec); // Sets LLColor3 to vec + const LLColor3& set(const F32 *vec); // Sets LLColor3 to vec + // set from a vector of unknown type and size // may leave some data unmodified template<typename T> @@ -99,18 +99,18 @@ public: template<typename T> void write(std::vector<T>& v) const; - F32 magVec() const; // deprecated - F32 magVecSquared() const; // deprecated - F32 normVec(); // deprecated + F32 magVec() const; // deprecated + F32 magVecSquared() const; // deprecated + F32 normVec(); // deprecated + + F32 length() const; // Returns magnitude of LLColor3 + F32 lengthSquared() const; // Returns magnitude squared of LLColor3 + F32 normalize(); // Normalizes and returns the magnitude of LLColor3 - F32 length() const; // Returns magnitude of LLColor3 - F32 lengthSquared() const; // Returns magnitude squared of LLColor3 - F32 normalize(); // Normalizes and returns the magnitude of LLColor3 + F32 brightness() const; // Returns brightness of LLColor3 - F32 brightness() const; // Returns brightness of LLColor3 + const LLColor3& operator=(const LLColor4 &a); - const LLColor3& operator=(const LLColor4 &a); - LL_FORCE_INLINE LLColor3 divide(const LLColor3 &col2) { return LLColor3( @@ -128,27 +128,27 @@ public: mV[2] / l ); } - friend std::ostream& operator<<(std::ostream& s, const LLColor3 &a); // Print a - friend LLColor3 operator+(const LLColor3 &a, const LLColor3 &b); // Return vector a + b - friend LLColor3 operator-(const LLColor3 &a, const LLColor3 &b); // Return vector a minus b + friend std::ostream& operator<<(std::ostream& s, const LLColor3 &a); // Print a + friend LLColor3 operator+(const LLColor3 &a, const LLColor3 &b); // Return vector a + b + friend LLColor3 operator-(const LLColor3 &a, const LLColor3 &b); // Return vector a minus b - friend const LLColor3& operator+=(LLColor3 &a, const LLColor3 &b); // Return vector a + b - friend const LLColor3& operator-=(LLColor3 &a, const LLColor3 &b); // Return vector a minus b - friend const LLColor3& operator*=(LLColor3 &a, const LLColor3 &b); + friend const LLColor3& operator+=(LLColor3 &a, const LLColor3 &b); // Return vector a + b + friend const LLColor3& operator-=(LLColor3 &a, const LLColor3 &b); // Return vector a minus b + friend const LLColor3& operator*=(LLColor3 &a, const LLColor3 &b); - friend LLColor3 operator*(const LLColor3 &a, const LLColor3 &b); // Return component wise a * b - friend LLColor3 operator*(const LLColor3 &a, F32 k); // Return a times scaler k - friend LLColor3 operator*(F32 k, const LLColor3 &a); // Return a times scaler k + friend LLColor3 operator*(const LLColor3 &a, const LLColor3 &b); // Return component wise a * b + friend LLColor3 operator*(const LLColor3 &a, F32 k); // Return a times scaler k + friend LLColor3 operator*(F32 k, const LLColor3 &a); // Return a times scaler k - friend bool operator==(const LLColor3 &a, const LLColor3 &b); // Return a == b - friend bool operator!=(const LLColor3 &a, const LLColor3 &b); // Return a != b + friend bool operator==(const LLColor3 &a, const LLColor3 &b); // Return a == b + friend bool operator!=(const LLColor3 &a, const LLColor3 &b); // Return a != b - friend const LLColor3& operator*=(LLColor3 &a, F32 k); // Return a times scaler k + friend const LLColor3& operator*=(LLColor3 &a, F32 k); // Return a times scaler k - friend LLColor3 operator-(const LLColor3 &a); // Return vector 1-rgb (inverse) + friend LLColor3 operator-(const LLColor3 &a); // Return vector 1-rgb (inverse) - inline void clamp(); - inline void exp(); // Do an exponential on the color + inline void clamp(); + inline void exp(); // Do an exponential on the color }; LLColor3 lerp(const LLColor3 &a, const LLColor3 &b, F32 u); @@ -156,343 +156,343 @@ LLColor3 lerp(const LLColor3 &a, const LLColor3 &b, F32 u); void LLColor3::clamp() { - // Clamp the color... - if (mV[0] < 0.f) - { - mV[0] = 0.f; - } - else if (mV[0] > 1.f) - { - mV[0] = 1.f; - } - if (mV[1] < 0.f) - { - mV[1] = 0.f; - } - else if (mV[1] > 1.f) - { - mV[1] = 1.f; - } - if (mV[2] < 0.f) - { - mV[2] = 0.f; - } - else if (mV[2] > 1.f) - { - mV[2] = 1.f; - } -} - -// Non-member functions -F32 distVec(const LLColor3 &a, const LLColor3 &b); // Returns distance between a and b -F32 distVec_squared(const LLColor3 &a, const LLColor3 &b);// Returns distance squared between a and b + // Clamp the color... + if (mV[0] < 0.f) + { + mV[0] = 0.f; + } + else if (mV[0] > 1.f) + { + mV[0] = 1.f; + } + if (mV[1] < 0.f) + { + mV[1] = 0.f; + } + else if (mV[1] > 1.f) + { + mV[1] = 1.f; + } + if (mV[2] < 0.f) + { + mV[2] = 0.f; + } + else if (mV[2] > 1.f) + { + mV[2] = 1.f; + } +} + +// Non-member functions +F32 distVec(const LLColor3 &a, const LLColor3 &b); // Returns distance between a and b +F32 distVec_squared(const LLColor3 &a, const LLColor3 &b);// Returns distance squared between a and b inline LLColor3::LLColor3(void) { - mV[0] = 0.f; - mV[1] = 0.f; - mV[2] = 0.f; + mV[0] = 0.f; + mV[1] = 0.f; + mV[2] = 0.f; } inline LLColor3::LLColor3(F32 r, F32 g, F32 b) { - mV[VX] = r; - mV[VY] = g; - mV[VZ] = b; + mV[VX] = r; + mV[VY] = g; + mV[VZ] = b; } inline LLColor3::LLColor3(const F32 *vec) { - mV[VX] = vec[VX]; - mV[VY] = vec[VY]; - mV[VZ] = vec[VZ]; + mV[VX] = vec[VX]; + mV[VY] = vec[VY]; + mV[VZ] = vec[VZ]; } #if LL_WINDOWS # pragma warning( disable : 4996 ) // strncpy teh sux0r #endif -inline LLColor3::LLColor3(const char* color_string) // takes a string of format "RRGGBB" where RR is hex 00..FF +inline LLColor3::LLColor3(const char* color_string) // takes a string of format "RRGGBB" where RR is hex 00..FF { - if (strlen(color_string) < 6) /* Flawfinder: ignore */ - { - mV[0] = 0.f; - mV[1] = 0.f; - mV[2] = 0.f; - return; - } + if (strlen(color_string) < 6) /* Flawfinder: ignore */ + { + mV[0] = 0.f; + mV[1] = 0.f; + mV[2] = 0.f; + return; + } - char tempstr[7]; - strncpy(tempstr,color_string,6); /* Flawfinder: ignore */ - tempstr[6] = '\0'; - mV[VZ] = (F32)strtol(&tempstr[4],NULL,16)/255.f; - tempstr[4] = '\0'; - mV[VY] = (F32)strtol(&tempstr[2],NULL,16)/255.f; - tempstr[2] = '\0'; - mV[VX] = (F32)strtol(&tempstr[0],NULL,16)/255.f; + char tempstr[7]; + strncpy(tempstr,color_string,6); /* Flawfinder: ignore */ + tempstr[6] = '\0'; + mV[VZ] = (F32)strtol(&tempstr[4],NULL,16)/255.f; + tempstr[4] = '\0'; + mV[VY] = (F32)strtol(&tempstr[2],NULL,16)/255.f; + tempstr[2] = '\0'; + mV[VX] = (F32)strtol(&tempstr[0],NULL,16)/255.f; } -inline const LLColor3& LLColor3::setToBlack(void) +inline const LLColor3& LLColor3::setToBlack(void) { - mV[0] = 0.f; - mV[1] = 0.f; - mV[2] = 0.f; - return (*this); + mV[0] = 0.f; + mV[1] = 0.f; + mV[2] = 0.f; + return (*this); } -inline const LLColor3& LLColor3::setToWhite(void) +inline const LLColor3& LLColor3::setToWhite(void) { - mV[0] = 1.f; - mV[1] = 1.f; - mV[2] = 1.f; - return (*this); + mV[0] = 1.f; + mV[1] = 1.f; + mV[2] = 1.f; + return (*this); } -inline const LLColor3& LLColor3::set(F32 r, F32 g, F32 b) +inline const LLColor3& LLColor3::set(F32 r, F32 g, F32 b) { - mV[0] = r; - mV[1] = g; - mV[2] = b; - return (*this); + mV[0] = r; + mV[1] = g; + mV[2] = b; + return (*this); } -inline const LLColor3& LLColor3::set(const LLColor3 &vec) +inline const LLColor3& LLColor3::set(const LLColor3 &vec) { - mV[0] = vec.mV[0]; - mV[1] = vec.mV[1]; - mV[2] = vec.mV[2]; - return (*this); + mV[0] = vec.mV[0]; + mV[1] = vec.mV[1]; + mV[2] = vec.mV[2]; + return (*this); } -inline const LLColor3& LLColor3::set(const F32 *vec) +inline const LLColor3& LLColor3::set(const F32 *vec) { - mV[0] = vec[0]; - mV[1] = vec[1]; - mV[2] = vec[2]; - return (*this); + mV[0] = vec[0]; + mV[1] = vec[1]; + mV[2] = vec[2]; + return (*this); } // deprecated -inline const LLColor3& LLColor3::setVec(F32 r, F32 g, F32 b) +inline const LLColor3& LLColor3::setVec(F32 r, F32 g, F32 b) { - mV[0] = r; - mV[1] = g; - mV[2] = b; - return (*this); + mV[0] = r; + mV[1] = g; + mV[2] = b; + return (*this); } // deprecated -inline const LLColor3& LLColor3::setVec(const LLColor3 &vec) +inline const LLColor3& LLColor3::setVec(const LLColor3 &vec) { - mV[0] = vec.mV[0]; - mV[1] = vec.mV[1]; - mV[2] = vec.mV[2]; - return (*this); + mV[0] = vec.mV[0]; + mV[1] = vec.mV[1]; + mV[2] = vec.mV[2]; + return (*this); } // deprecated -inline const LLColor3& LLColor3::setVec(const F32 *vec) +inline const LLColor3& LLColor3::setVec(const F32 *vec) { - mV[0] = vec[0]; - mV[1] = vec[1]; - mV[2] = vec[2]; - return (*this); + mV[0] = vec[0]; + mV[1] = vec[1]; + mV[2] = vec[2]; + return (*this); } -inline F32 LLColor3::brightness(void) const +inline F32 LLColor3::brightness(void) const { - return (mV[0] + mV[1] + mV[2]) / 3.0f; + return (mV[0] + mV[1] + mV[2]) / 3.0f; } -inline F32 LLColor3::length(void) const +inline F32 LLColor3::length(void) const { - return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); } -inline F32 LLColor3::lengthSquared(void) const +inline F32 LLColor3::lengthSquared(void) const { - return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]; + return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]; } -inline F32 LLColor3::normalize(void) +inline F32 LLColor3::normalize(void) { - F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); - F32 oomag; + F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + F32 oomag; - if (mag) - { - oomag = 1.f/mag; - mV[0] *= oomag; - mV[1] *= oomag; - mV[2] *= oomag; - } - return (mag); + if (mag) + { + oomag = 1.f/mag; + mV[0] *= oomag; + mV[1] *= oomag; + mV[2] *= oomag; + } + return (mag); } // deprecated -inline F32 LLColor3::magVec(void) const +inline F32 LLColor3::magVec(void) const { - return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); } // deprecated -inline F32 LLColor3::magVecSquared(void) const +inline F32 LLColor3::magVecSquared(void) const { - return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]; + return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]; } // deprecated -inline F32 LLColor3::normVec(void) +inline F32 LLColor3::normVec(void) { - F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); - F32 oomag; + F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + F32 oomag; - if (mag) - { - oomag = 1.f/mag; - mV[0] *= oomag; - mV[1] *= oomag; - mV[2] *= oomag; - } - return (mag); + if (mag) + { + oomag = 1.f/mag; + mV[0] *= oomag; + mV[1] *= oomag; + mV[2] *= oomag; + } + return (mag); } inline void LLColor3::exp() { #if 0 - mV[0] = ::exp(mV[0]); - mV[1] = ::exp(mV[1]); - mV[2] = ::exp(mV[2]); + mV[0] = ::exp(mV[0]); + mV[1] = ::exp(mV[1]); + mV[2] = ::exp(mV[2]); #else - mV[0] = (F32)LL_FAST_EXP(mV[0]); - mV[1] = (F32)LL_FAST_EXP(mV[1]); - mV[2] = (F32)LL_FAST_EXP(mV[2]); + mV[0] = (F32)LL_FAST_EXP(mV[0]); + mV[1] = (F32)LL_FAST_EXP(mV[1]); + mV[2] = (F32)LL_FAST_EXP(mV[2]); #endif } inline LLColor3 operator+(const LLColor3 &a, const LLColor3 &b) { - return LLColor3( - a.mV[0] + b.mV[0], - a.mV[1] + b.mV[1], - a.mV[2] + b.mV[2]); + return LLColor3( + a.mV[0] + b.mV[0], + a.mV[1] + b.mV[1], + a.mV[2] + b.mV[2]); } inline LLColor3 operator-(const LLColor3 &a, const LLColor3 &b) { - return LLColor3( - a.mV[0] - b.mV[0], - a.mV[1] - b.mV[1], - a.mV[2] - b.mV[2]); + return LLColor3( + a.mV[0] - b.mV[0], + a.mV[1] - b.mV[1], + a.mV[2] - b.mV[2]); } inline LLColor3 operator*(const LLColor3 &a, const LLColor3 &b) { - return LLColor3( - a.mV[0] * b.mV[0], - a.mV[1] * b.mV[1], - a.mV[2] * b.mV[2]); + return LLColor3( + a.mV[0] * b.mV[0], + a.mV[1] * b.mV[1], + a.mV[2] * b.mV[2]); } inline LLColor3 operator*(const LLColor3 &a, F32 k) { - return LLColor3( a.mV[0] * k, a.mV[1] * k, a.mV[2] * k ); + return LLColor3( a.mV[0] * k, a.mV[1] * k, a.mV[2] * k ); } inline LLColor3 operator*(F32 k, const LLColor3 &a) { - return LLColor3( a.mV[0] * k, a.mV[1] * k, a.mV[2] * k ); + return LLColor3( a.mV[0] * k, a.mV[1] * k, a.mV[2] * k ); } inline bool operator==(const LLColor3 &a, const LLColor3 &b) { - return ( (a.mV[0] == b.mV[0]) - &&(a.mV[1] == b.mV[1]) - &&(a.mV[2] == b.mV[2])); + return ( (a.mV[0] == b.mV[0]) + &&(a.mV[1] == b.mV[1]) + &&(a.mV[2] == b.mV[2])); } inline bool operator!=(const LLColor3 &a, const LLColor3 &b) { - return ( (a.mV[0] != b.mV[0]) - ||(a.mV[1] != b.mV[1]) - ||(a.mV[2] != b.mV[2])); + return ( (a.mV[0] != b.mV[0]) + ||(a.mV[1] != b.mV[1]) + ||(a.mV[2] != b.mV[2])); } inline const LLColor3 &operator*=(LLColor3 &a, const LLColor3 &b) { - a.mV[0] *= b.mV[0]; - a.mV[1] *= b.mV[1]; - a.mV[2] *= b.mV[2]; - return a; + a.mV[0] *= b.mV[0]; + a.mV[1] *= b.mV[1]; + a.mV[2] *= b.mV[2]; + return a; } inline const LLColor3& operator+=(LLColor3 &a, const LLColor3 &b) { - a.mV[0] += b.mV[0]; - a.mV[1] += b.mV[1]; - a.mV[2] += b.mV[2]; - return a; + a.mV[0] += b.mV[0]; + a.mV[1] += b.mV[1]; + a.mV[2] += b.mV[2]; + return a; } inline const LLColor3& operator-=(LLColor3 &a, const LLColor3 &b) { - a.mV[0] -= b.mV[0]; - a.mV[1] -= b.mV[1]; - a.mV[2] -= b.mV[2]; - return a; + a.mV[0] -= b.mV[0]; + a.mV[1] -= b.mV[1]; + a.mV[2] -= b.mV[2]; + return a; } inline const LLColor3& operator*=(LLColor3 &a, F32 k) { - a.mV[0] *= k; - a.mV[1] *= k; - a.mV[2] *= k; - return a; + a.mV[0] *= k; + a.mV[1] *= k; + a.mV[2] *= k; + return a; } inline LLColor3 operator-(const LLColor3 &a) { - return LLColor3( - 1.f - a.mV[0], - 1.f - a.mV[1], - 1.f - a.mV[2] ); + return LLColor3( + 1.f - a.mV[0], + 1.f - a.mV[1], + 1.f - a.mV[2] ); } // Non-member functions -inline F32 distVec(const LLColor3 &a, const LLColor3 &b) +inline F32 distVec(const LLColor3 &a, const LLColor3 &b) { - F32 x = a.mV[0] - b.mV[0]; - F32 y = a.mV[1] - b.mV[1]; - F32 z = a.mV[2] - b.mV[2]; - return (F32) sqrt( x*x + y*y + z*z ); + F32 x = a.mV[0] - b.mV[0]; + F32 y = a.mV[1] - b.mV[1]; + F32 z = a.mV[2] - b.mV[2]; + return (F32) sqrt( x*x + y*y + z*z ); } -inline F32 distVec_squared(const LLColor3 &a, const LLColor3 &b) +inline F32 distVec_squared(const LLColor3 &a, const LLColor3 &b) { - F32 x = a.mV[0] - b.mV[0]; - F32 y = a.mV[1] - b.mV[1]; - F32 z = a.mV[2] - b.mV[2]; - return x*x + y*y + z*z; + F32 x = a.mV[0] - b.mV[0]; + F32 y = a.mV[1] - b.mV[1]; + F32 z = a.mV[2] - b.mV[2]; + return x*x + y*y + z*z; } inline LLColor3 lerp(const LLColor3 &a, const LLColor3 &b, F32 u) { - return LLColor3( - a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u, - a.mV[VY] + (b.mV[VY] - a.mV[VY]) * u, - a.mV[VZ] + (b.mV[VZ] - a.mV[VZ]) * u); + return LLColor3( + a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u, + a.mV[VY] + (b.mV[VY] - a.mV[VY]) * u, + a.mV[VZ] + (b.mV[VZ] - a.mV[VZ]) * u); } inline const LLColor3 srgbColor3(const LLColor3 &a) { - LLColor3 srgbColor; - srgbColor.mV[0] = linearTosRGB(a.mV[0]); - srgbColor.mV[1] = linearTosRGB(a.mV[1]); - srgbColor.mV[2] = linearTosRGB(a.mV[2]); + LLColor3 srgbColor; + srgbColor.mV[0] = linearTosRGB(a.mV[0]); + srgbColor.mV[1] = linearTosRGB(a.mV[1]); + srgbColor.mV[2] = linearTosRGB(a.mV[2]); - return srgbColor; + return srgbColor; } inline const LLColor3 linearColor3p(const F32* v) { diff --git a/indra/llmath/v3colorutil.h b/indra/llmath/v3colorutil.h index 6d8cd9329b..62005f76a0 100644 --- a/indra/llmath/v3colorutil.h +++ b/indra/llmath/v3colorutil.h @@ -1,25 +1,25 @@ -/** +/** * @file v3color.h * @brief LLColor3 class header file. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ diff --git a/indra/llmath/v3dmath.cpp b/indra/llmath/v3dmath.cpp index cc7121da38..bb55c812b5 100644 --- a/indra/llmath/v3dmath.cpp +++ b/indra/llmath/v3dmath.cpp @@ -1,32 +1,32 @@ -/** +/** * @file v3dmath.cpp * @brief LLVector3d class implementation. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #include "linden_common.h" -//#include <sstream> // gcc 2.95.2 doesn't support sstream +//#include <sstream> // gcc 2.95.2 doesn't support sstream #include "v3dmath.h" @@ -39,8 +39,8 @@ // LLVector3d // WARNING: Don't use these for global const definitions! -// For example: -// const LLQuaternion(0.5f * F_PI, LLVector3d::zero); +// For example: +// const LLQuaternion(0.5f * F_PI, LLVector3d::zero); // at the top of a *.cpp file might not give you what you think. const LLVector3d LLVector3d::zero(0,0,0); const LLVector3d LLVector3d::x_axis(1, 0, 0); @@ -55,93 +55,93 @@ const LLVector3d LLVector3d::z_axis_neg(0, 0, -1); // Returns true if data changed. bool LLVector3d::clamp(F64 min, F64 max) { - bool ret{ false }; + bool ret{ false }; - if (mdV[0] < min) { mdV[0] = min; ret = true; } - if (mdV[1] < min) { mdV[1] = min; ret = true; } - if (mdV[2] < min) { mdV[2] = min; ret = true; } + if (mdV[0] < min) { mdV[0] = min; ret = true; } + if (mdV[1] < min) { mdV[1] = min; ret = true; } + if (mdV[2] < min) { mdV[2] = min; ret = true; } - if (mdV[0] > max) { mdV[0] = max; ret = true; } - if (mdV[1] > max) { mdV[1] = max; ret = true; } - if (mdV[2] > max) { mdV[2] = max; ret = true; } + if (mdV[0] > max) { mdV[0] = max; ret = true; } + if (mdV[1] > max) { mdV[1] = max; ret = true; } + if (mdV[2] > max) { mdV[2] = max; ret = true; } - return ret; + return ret; } // Sets all values to absolute value of their original values // Returns true if data changed bool LLVector3d::abs() { - bool ret{ false }; + bool ret{ false }; - if (mdV[0] < 0.0) { mdV[0] = -mdV[0]; ret = true; } - if (mdV[1] < 0.0) { mdV[1] = -mdV[1]; ret = true; } - if (mdV[2] < 0.0) { mdV[2] = -mdV[2]; ret = true; } + if (mdV[0] < 0.0) { mdV[0] = -mdV[0]; ret = true; } + if (mdV[1] < 0.0) { mdV[1] = -mdV[1]; ret = true; } + if (mdV[2] < 0.0) { mdV[2] = -mdV[2]; ret = true; } - return ret; + return ret; } -std::ostream& operator<<(std::ostream& s, const LLVector3d &a) +std::ostream& operator<<(std::ostream& s, const LLVector3d &a) { - s << "{ " << a.mdV[VX] << ", " << a.mdV[VY] << ", " << a.mdV[VZ] << " }"; - return s; + s << "{ " << a.mdV[VX] << ", " << a.mdV[VY] << ", " << a.mdV[VZ] << " }"; + return s; } -const LLVector3d& LLVector3d::operator=(const LLVector4 &a) +const LLVector3d& LLVector3d::operator=(const LLVector4 &a) { - mdV[0] = a.mV[0]; - mdV[1] = a.mV[1]; - mdV[2] = a.mV[2]; - return *this; + mdV[0] = a.mV[0]; + mdV[1] = a.mV[1]; + mdV[2] = a.mV[2]; + return *this; } -const LLVector3d& LLVector3d::rotVec(const LLMatrix3 &mat) +const LLVector3d& LLVector3d::rotVec(const LLMatrix3 &mat) { - *this = *this * mat; - return *this; + *this = *this * mat; + return *this; } -const LLVector3d& LLVector3d::rotVec(const LLQuaternion &q) +const LLVector3d& LLVector3d::rotVec(const LLQuaternion &q) { - *this = *this * q; - return *this; + *this = *this * q; + return *this; } -const LLVector3d& LLVector3d::rotVec(F64 angle, const LLVector3d &vec) +const LLVector3d& LLVector3d::rotVec(F64 angle, const LLVector3d &vec) { - if ( !vec.isExactlyZero() && angle ) - { - *this = *this * LLMatrix3((F32)angle, vec); - } - return *this; + if ( !vec.isExactlyZero() && angle ) + { + *this = *this * LLMatrix3((F32)angle, vec); + } + return *this; } -const LLVector3d& LLVector3d::rotVec(F64 angle, F64 x, F64 y, F64 z) +const LLVector3d& LLVector3d::rotVec(F64 angle, F64 x, F64 y, F64 z) { - LLVector3d vec(x, y, z); - if ( !vec.isExactlyZero() && angle ) - { - *this = *this * LLMatrix3((F32)angle, vec); - } - return *this; + LLVector3d vec(x, y, z); + if ( !vec.isExactlyZero() && angle ) + { + *this = *this * LLMatrix3((F32)angle, vec); + } + return *this; } bool LLVector3d::parseVector3d(const std::string& buf, LLVector3d* value) { - if( buf.empty() || value == nullptr) - { - return false; - } - - LLVector3d v; - S32 count = sscanf( buf.c_str(), "%lf %lf %lf", v.mdV + 0, v.mdV + 1, v.mdV + 2 ); - if( 3 == count ) - { - value->setVec( v ); - return true; - } - - return false; + if( buf.empty() || value == nullptr) + { + return false; + } + + LLVector3d v; + S32 count = sscanf( buf.c_str(), "%lf %lf %lf", v.mdV + 0, v.mdV + 1, v.mdV + 2 ); + if( 3 == count ) + { + value->setVec( v ); + return true; + } + + return false; } diff --git a/indra/llmath/v3dmath.h b/indra/llmath/v3dmath.h index 751d6d6228..ece8c54ea4 100644 --- a/indra/llmath/v3dmath.h +++ b/indra/llmath/v3dmath.h @@ -1,25 +1,25 @@ -/** +/** * @file v3dmath.h * @brief High precision 3 dimensional vector. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -32,101 +32,101 @@ class LLVector3d { - public: - F64 mdV[3]; - - const static LLVector3d zero; - const static LLVector3d x_axis; - const static LLVector3d y_axis; - const static LLVector3d z_axis; - const static LLVector3d x_axis_neg; - const static LLVector3d y_axis_neg; - const static LLVector3d z_axis_neg; - - inline LLVector3d(); // Initializes LLVector3d to (0, 0, 0) - inline LLVector3d(const F64 x, const F64 y, const F64 z); // Initializes LLVector3d to (x. y, z) - inline explicit LLVector3d(const F64 *vec); // Initializes LLVector3d to (vec[0]. vec[1], vec[2]) - inline explicit LLVector3d(const LLVector3 &vec); - explicit LLVector3d(const LLSD& sd) - { - setValue(sd); - } - - void setValue(const LLSD& sd) - { - mdV[0] = sd[0].asReal(); - mdV[1] = sd[1].asReal(); - mdV[2] = sd[2].asReal(); - } - - LLSD getValue() const - { - LLSD ret; - ret[0] = mdV[0]; - ret[1] = mdV[1]; - ret[2] = mdV[2]; - return ret; - } - - inline bool isFinite() const; // checks to see if all values of LLVector3d are finite - bool clamp(const F64 min, const F64 max); // Clamps all values to (min,max), returns true if data changed - bool abs(); // sets all values to absolute value of original value (first octant), returns true if changed - - inline const LLVector3d& clear(); // Clears LLVector3d to (0, 0, 0, 1) - inline const LLVector3d& clearVec(); // deprecated - inline const LLVector3d& setZero(); // Zero LLVector3d to (0, 0, 0, 0) - inline const LLVector3d& zeroVec(); // deprecated - inline const LLVector3d& set(const F64 x, const F64 y, const F64 z); // Sets LLVector3d to (x, y, z, 1) - inline const LLVector3d& set(const LLVector3d &vec); // Sets LLVector3d to vec - inline const LLVector3d& set(const F64 *vec); // Sets LLVector3d to vec - inline const LLVector3d& set(const LLVector3 &vec); - inline const LLVector3d& setVec(const F64 x, const F64 y, const F64 z); // deprecated - inline const LLVector3d& setVec(const LLVector3d &vec); // deprecated - inline const LLVector3d& setVec(const F64 *vec); // deprecated - inline const LLVector3d& setVec(const LLVector3 &vec); // deprecated - - F64 magVec() const; // deprecated - F64 magVecSquared() const; // deprecated - inline F64 normVec(); // deprecated - - F64 length() const; // Returns magnitude of LLVector3d - F64 lengthSquared() const; // Returns magnitude squared of LLVector3d - inline F64 normalize(); // Normalizes and returns the magnitude of LLVector3d - - const LLVector3d& rotVec(const F64 angle, const LLVector3d &vec); // Rotates about vec by angle radians - const LLVector3d& rotVec(const F64 angle, const F64 x, const F64 y, const F64 z); // Rotates about x,y,z by angle radians - const LLVector3d& rotVec(const LLMatrix3 &mat); // Rotates by LLMatrix4 mat - const LLVector3d& rotVec(const LLQuaternion &q); // Rotates by LLQuaternion q - - bool isNull() const; // Returns true if vector has a _very_small_ length - bool isExactlyZero() const { return !mdV[VX] && !mdV[VY] && !mdV[VZ]; } - - const LLVector3d& operator=(const LLVector4 &a); - - F64 operator[](int idx) const { return mdV[idx]; } - F64 &operator[](int idx) { return mdV[idx]; } - - friend LLVector3d operator+(const LLVector3d& a, const LLVector3d& b); // Return vector a + b - friend LLVector3d operator-(const LLVector3d& a, const LLVector3d& b); // Return vector a minus b - friend F64 operator*(const LLVector3d& a, const LLVector3d& b); // Return a dot b - friend LLVector3d operator%(const LLVector3d& a, const LLVector3d& b); // Return a cross b - friend LLVector3d operator*(const LLVector3d& a, const F64 k); // Return a times scaler k - friend LLVector3d operator/(const LLVector3d& a, const F64 k); // Return a divided by scaler k - friend LLVector3d operator*(const F64 k, const LLVector3d& a); // Return a times scaler k - friend bool operator==(const LLVector3d& a, const LLVector3d& b); // Return a == b - friend bool operator!=(const LLVector3d& a, const LLVector3d& b); // Return a != b - - friend const LLVector3d& operator+=(LLVector3d& a, const LLVector3d& b); // Return vector a + b - friend const LLVector3d& operator-=(LLVector3d& a, const LLVector3d& b); // Return vector a minus b - friend const LLVector3d& operator%=(LLVector3d& a, const LLVector3d& b); // Return a cross b - friend const LLVector3d& operator*=(LLVector3d& a, const F64 k); // Return a times scaler k - friend const LLVector3d& operator/=(LLVector3d& a, const F64 k); // Return a divided by scaler k - - friend LLVector3d operator-(const LLVector3d& a); // Return vector -a - - friend std::ostream& operator<<(std::ostream& s, const LLVector3d& a); // Stream a - - static bool parseVector3d(const std::string& buf, LLVector3d* value); + public: + F64 mdV[3]; + + const static LLVector3d zero; + const static LLVector3d x_axis; + const static LLVector3d y_axis; + const static LLVector3d z_axis; + const static LLVector3d x_axis_neg; + const static LLVector3d y_axis_neg; + const static LLVector3d z_axis_neg; + + inline LLVector3d(); // Initializes LLVector3d to (0, 0, 0) + inline LLVector3d(const F64 x, const F64 y, const F64 z); // Initializes LLVector3d to (x. y, z) + inline explicit LLVector3d(const F64 *vec); // Initializes LLVector3d to (vec[0]. vec[1], vec[2]) + inline explicit LLVector3d(const LLVector3 &vec); + explicit LLVector3d(const LLSD& sd) + { + setValue(sd); + } + + void setValue(const LLSD& sd) + { + mdV[0] = sd[0].asReal(); + mdV[1] = sd[1].asReal(); + mdV[2] = sd[2].asReal(); + } + + LLSD getValue() const + { + LLSD ret; + ret[0] = mdV[0]; + ret[1] = mdV[1]; + ret[2] = mdV[2]; + return ret; + } + + inline bool isFinite() const; // checks to see if all values of LLVector3d are finite + bool clamp(const F64 min, const F64 max); // Clamps all values to (min,max), returns true if data changed + bool abs(); // sets all values to absolute value of original value (first octant), returns true if changed + + inline const LLVector3d& clear(); // Clears LLVector3d to (0, 0, 0, 1) + inline const LLVector3d& clearVec(); // deprecated + inline const LLVector3d& setZero(); // Zero LLVector3d to (0, 0, 0, 0) + inline const LLVector3d& zeroVec(); // deprecated + inline const LLVector3d& set(const F64 x, const F64 y, const F64 z); // Sets LLVector3d to (x, y, z, 1) + inline const LLVector3d& set(const LLVector3d &vec); // Sets LLVector3d to vec + inline const LLVector3d& set(const F64 *vec); // Sets LLVector3d to vec + inline const LLVector3d& set(const LLVector3 &vec); + inline const LLVector3d& setVec(const F64 x, const F64 y, const F64 z); // deprecated + inline const LLVector3d& setVec(const LLVector3d &vec); // deprecated + inline const LLVector3d& setVec(const F64 *vec); // deprecated + inline const LLVector3d& setVec(const LLVector3 &vec); // deprecated + + F64 magVec() const; // deprecated + F64 magVecSquared() const; // deprecated + inline F64 normVec(); // deprecated + + F64 length() const; // Returns magnitude of LLVector3d + F64 lengthSquared() const; // Returns magnitude squared of LLVector3d + inline F64 normalize(); // Normalizes and returns the magnitude of LLVector3d + + const LLVector3d& rotVec(const F64 angle, const LLVector3d &vec); // Rotates about vec by angle radians + const LLVector3d& rotVec(const F64 angle, const F64 x, const F64 y, const F64 z); // Rotates about x,y,z by angle radians + const LLVector3d& rotVec(const LLMatrix3 &mat); // Rotates by LLMatrix4 mat + const LLVector3d& rotVec(const LLQuaternion &q); // Rotates by LLQuaternion q + + bool isNull() const; // Returns true if vector has a _very_small_ length + bool isExactlyZero() const { return !mdV[VX] && !mdV[VY] && !mdV[VZ]; } + + const LLVector3d& operator=(const LLVector4 &a); + + F64 operator[](int idx) const { return mdV[idx]; } + F64 &operator[](int idx) { return mdV[idx]; } + + friend LLVector3d operator+(const LLVector3d& a, const LLVector3d& b); // Return vector a + b + friend LLVector3d operator-(const LLVector3d& a, const LLVector3d& b); // Return vector a minus b + friend F64 operator*(const LLVector3d& a, const LLVector3d& b); // Return a dot b + friend LLVector3d operator%(const LLVector3d& a, const LLVector3d& b); // Return a cross b + friend LLVector3d operator*(const LLVector3d& a, const F64 k); // Return a times scaler k + friend LLVector3d operator/(const LLVector3d& a, const F64 k); // Return a divided by scaler k + friend LLVector3d operator*(const F64 k, const LLVector3d& a); // Return a times scaler k + friend bool operator==(const LLVector3d& a, const LLVector3d& b); // Return a == b + friend bool operator!=(const LLVector3d& a, const LLVector3d& b); // Return a != b + + friend const LLVector3d& operator+=(LLVector3d& a, const LLVector3d& b); // Return vector a + b + friend const LLVector3d& operator-=(LLVector3d& a, const LLVector3d& b); // Return vector a minus b + friend const LLVector3d& operator%=(LLVector3d& a, const LLVector3d& b); // Return a cross b + friend const LLVector3d& operator*=(LLVector3d& a, const F64 k); // Return a times scaler k + friend const LLVector3d& operator/=(LLVector3d& a, const F64 k); // Return a divided by scaler k + + friend LLVector3d operator-(const LLVector3d& a); // Return vector -a + + friend std::ostream& operator<<(std::ostream& s, const LLVector3d& a); // Stream a + + static bool parseVector3d(const std::string& buf, LLVector3d* value); }; @@ -134,55 +134,55 @@ typedef LLVector3d LLGlobalVec; inline const LLVector3d &LLVector3d::set(const LLVector3 &vec) { - mdV[0] = vec.mV[0]; - mdV[1] = vec.mV[1]; - mdV[2] = vec.mV[2]; - return *this; + mdV[0] = vec.mV[0]; + mdV[1] = vec.mV[1]; + mdV[2] = vec.mV[2]; + return *this; } inline const LLVector3d &LLVector3d::setVec(const LLVector3 &vec) { - mdV[0] = vec.mV[0]; - mdV[1] = vec.mV[1]; - mdV[2] = vec.mV[2]; - return *this; + mdV[0] = vec.mV[0]; + mdV[1] = vec.mV[1]; + mdV[2] = vec.mV[2]; + return *this; } inline LLVector3d::LLVector3d(void) { - mdV[0] = 0.f; - mdV[1] = 0.f; - mdV[2] = 0.f; + mdV[0] = 0.f; + mdV[1] = 0.f; + mdV[2] = 0.f; } inline LLVector3d::LLVector3d(const F64 x, const F64 y, const F64 z) { - mdV[VX] = x; - mdV[VY] = y; - mdV[VZ] = z; + mdV[VX] = x; + mdV[VY] = y; + mdV[VZ] = z; } inline LLVector3d::LLVector3d(const F64 *vec) { - mdV[VX] = vec[VX]; - mdV[VY] = vec[VY]; - mdV[VZ] = vec[VZ]; + mdV[VX] = vec[VX]; + mdV[VY] = vec[VY]; + mdV[VZ] = vec[VZ]; } inline LLVector3d::LLVector3d(const LLVector3 &vec) { - mdV[VX] = vec.mV[VX]; - mdV[VY] = vec.mV[VY]; - mdV[VZ] = vec.mV[VZ]; + mdV[VX] = vec.mV[VX]; + mdV[VY] = vec.mV[VY]; + mdV[VZ] = vec.mV[VZ]; } /* inline LLVector3d::LLVector3d(const LLVector3d ©) { - mdV[VX] = copy.mdV[VX]; - mdV[VY] = copy.mdV[VY]; - mdV[VZ] = copy.mdV[VZ]; + mdV[VX] = copy.mdV[VX]; + mdV[VY] = copy.mdV[VY]; + mdV[VZ] = copy.mdV[VZ]; } */ @@ -191,340 +191,340 @@ inline LLVector3d::LLVector3d(const LLVector3d ©) // checker inline bool LLVector3d::isFinite() const { - return (llfinite(mdV[VX]) && llfinite(mdV[VY]) && llfinite(mdV[VZ])); + return (llfinite(mdV[VX]) && llfinite(mdV[VY]) && llfinite(mdV[VZ])); } // Clear and Assignment Functions -inline const LLVector3d& LLVector3d::clear(void) +inline const LLVector3d& LLVector3d::clear(void) { - mdV[0] = 0.f; - mdV[1] = 0.f; - mdV[2]= 0.f; - return (*this); + mdV[0] = 0.f; + mdV[1] = 0.f; + mdV[2]= 0.f; + return (*this); } -inline const LLVector3d& LLVector3d::clearVec(void) +inline const LLVector3d& LLVector3d::clearVec(void) { - mdV[0] = 0.f; - mdV[1] = 0.f; - mdV[2]= 0.f; - return (*this); + mdV[0] = 0.f; + mdV[1] = 0.f; + mdV[2]= 0.f; + return (*this); } -inline const LLVector3d& LLVector3d::setZero(void) +inline const LLVector3d& LLVector3d::setZero(void) { - mdV[0] = 0.f; - mdV[1] = 0.f; - mdV[2] = 0.f; - return (*this); + mdV[0] = 0.f; + mdV[1] = 0.f; + mdV[2] = 0.f; + return (*this); } -inline const LLVector3d& LLVector3d::zeroVec(void) +inline const LLVector3d& LLVector3d::zeroVec(void) { - mdV[0] = 0.f; - mdV[1] = 0.f; - mdV[2] = 0.f; - return (*this); + mdV[0] = 0.f; + mdV[1] = 0.f; + mdV[2] = 0.f; + return (*this); } -inline const LLVector3d& LLVector3d::set(const F64 x, const F64 y, const F64 z) +inline const LLVector3d& LLVector3d::set(const F64 x, const F64 y, const F64 z) { - mdV[VX] = x; - mdV[VY] = y; - mdV[VZ] = z; - return (*this); + mdV[VX] = x; + mdV[VY] = y; + mdV[VZ] = z; + return (*this); } -inline const LLVector3d& LLVector3d::set(const LLVector3d &vec) +inline const LLVector3d& LLVector3d::set(const LLVector3d &vec) { - mdV[0] = vec.mdV[0]; - mdV[1] = vec.mdV[1]; - mdV[2] = vec.mdV[2]; - return (*this); + mdV[0] = vec.mdV[0]; + mdV[1] = vec.mdV[1]; + mdV[2] = vec.mdV[2]; + return (*this); } -inline const LLVector3d& LLVector3d::set(const F64 *vec) +inline const LLVector3d& LLVector3d::set(const F64 *vec) { - mdV[0] = vec[0]; - mdV[1] = vec[1]; - mdV[2] = vec[2]; - return (*this); + mdV[0] = vec[0]; + mdV[1] = vec[1]; + mdV[2] = vec[2]; + return (*this); } -inline const LLVector3d& LLVector3d::setVec(const F64 x, const F64 y, const F64 z) +inline const LLVector3d& LLVector3d::setVec(const F64 x, const F64 y, const F64 z) { - mdV[VX] = x; - mdV[VY] = y; - mdV[VZ] = z; - return (*this); + mdV[VX] = x; + mdV[VY] = y; + mdV[VZ] = z; + return (*this); } -inline const LLVector3d& LLVector3d::setVec(const LLVector3d &vec) +inline const LLVector3d& LLVector3d::setVec(const LLVector3d &vec) { - mdV[0] = vec.mdV[0]; - mdV[1] = vec.mdV[1]; - mdV[2] = vec.mdV[2]; - return (*this); + mdV[0] = vec.mdV[0]; + mdV[1] = vec.mdV[1]; + mdV[2] = vec.mdV[2]; + return (*this); } -inline const LLVector3d& LLVector3d::setVec(const F64 *vec) +inline const LLVector3d& LLVector3d::setVec(const F64 *vec) { - mdV[0] = vec[0]; - mdV[1] = vec[1]; - mdV[2] = vec[2]; - return (*this); + mdV[0] = vec[0]; + mdV[1] = vec[1]; + mdV[2] = vec[2]; + return (*this); } inline F64 LLVector3d::normVec(void) { - F64 mag = (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); - F64 oomag; - - if (mag > FP_MAG_THRESHOLD) - { - oomag = 1.f/mag; - mdV[0] *= oomag; - mdV[1] *= oomag; - mdV[2] *= oomag; - } - else - { - mdV[0] = 0.f; - mdV[1] = 0.f; - mdV[2] = 0.f; - mag = 0; - } - return (mag); + F64 mag = (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); + F64 oomag; + + if (mag > FP_MAG_THRESHOLD) + { + oomag = 1.f/mag; + mdV[0] *= oomag; + mdV[1] *= oomag; + mdV[2] *= oomag; + } + else + { + mdV[0] = 0.f; + mdV[1] = 0.f; + mdV[2] = 0.f; + mag = 0; + } + return (mag); } inline F64 LLVector3d::normalize(void) { - F64 mag = (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); - F64 oomag; - - if (mag > FP_MAG_THRESHOLD) - { - oomag = 1.f/mag; - mdV[0] *= oomag; - mdV[1] *= oomag; - mdV[2] *= oomag; - } - else - { - mdV[0] = 0.f; - mdV[1] = 0.f; - mdV[2] = 0.f; - mag = 0; - } - return (mag); + F64 mag = (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); + F64 oomag; + + if (mag > FP_MAG_THRESHOLD) + { + oomag = 1.f/mag; + mdV[0] *= oomag; + mdV[1] *= oomag; + mdV[2] *= oomag; + } + else + { + mdV[0] = 0.f; + mdV[1] = 0.f; + mdV[2] = 0.f; + mag = 0; + } + return (mag); } // LLVector3d Magnitude and Normalization Functions -inline F64 LLVector3d::magVec(void) const +inline F64 LLVector3d::magVec(void) const { - return (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); + return (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); } -inline F64 LLVector3d::magVecSquared(void) const +inline F64 LLVector3d::magVecSquared(void) const { - return mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]; + return mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]; } -inline F64 LLVector3d::length(void) const +inline F64 LLVector3d::length(void) const { - return (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); + return (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); } -inline F64 LLVector3d::lengthSquared(void) const +inline F64 LLVector3d::lengthSquared(void) const { - return mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]; + return mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]; } inline LLVector3d operator+(const LLVector3d& a, const LLVector3d& b) { - LLVector3d c(a); - return c += b; + LLVector3d c(a); + return c += b; } inline LLVector3d operator-(const LLVector3d& a, const LLVector3d& b) { - LLVector3d c(a); - return c -= b; + LLVector3d c(a); + return c -= b; } inline F64 operator*(const LLVector3d& a, const LLVector3d& b) { - return (a.mdV[0]*b.mdV[0] + a.mdV[1]*b.mdV[1] + a.mdV[2]*b.mdV[2]); + return (a.mdV[0]*b.mdV[0] + a.mdV[1]*b.mdV[1] + a.mdV[2]*b.mdV[2]); } inline LLVector3d operator%(const LLVector3d& a, const LLVector3d& b) { - return LLVector3d( a.mdV[1]*b.mdV[2] - b.mdV[1]*a.mdV[2], a.mdV[2]*b.mdV[0] - b.mdV[2]*a.mdV[0], a.mdV[0]*b.mdV[1] - b.mdV[0]*a.mdV[1] ); + return LLVector3d( a.mdV[1]*b.mdV[2] - b.mdV[1]*a.mdV[2], a.mdV[2]*b.mdV[0] - b.mdV[2]*a.mdV[0], a.mdV[0]*b.mdV[1] - b.mdV[0]*a.mdV[1] ); } inline LLVector3d operator/(const LLVector3d& a, const F64 k) { - F64 t = 1.f / k; - return LLVector3d( a.mdV[0] * t, a.mdV[1] * t, a.mdV[2] * t ); + F64 t = 1.f / k; + return LLVector3d( a.mdV[0] * t, a.mdV[1] * t, a.mdV[2] * t ); } inline LLVector3d operator*(const LLVector3d& a, const F64 k) { - return LLVector3d( a.mdV[0] * k, a.mdV[1] * k, a.mdV[2] * k ); + return LLVector3d( a.mdV[0] * k, a.mdV[1] * k, a.mdV[2] * k ); } inline LLVector3d operator*(F64 k, const LLVector3d& a) { - return LLVector3d( a.mdV[0] * k, a.mdV[1] * k, a.mdV[2] * k ); + return LLVector3d( a.mdV[0] * k, a.mdV[1] * k, a.mdV[2] * k ); } inline bool operator==(const LLVector3d& a, const LLVector3d& b) { - return ( (a.mdV[0] == b.mdV[0]) - &&(a.mdV[1] == b.mdV[1]) - &&(a.mdV[2] == b.mdV[2])); + return ( (a.mdV[0] == b.mdV[0]) + &&(a.mdV[1] == b.mdV[1]) + &&(a.mdV[2] == b.mdV[2])); } inline bool operator!=(const LLVector3d& a, const LLVector3d& b) { - return ( (a.mdV[0] != b.mdV[0]) - ||(a.mdV[1] != b.mdV[1]) - ||(a.mdV[2] != b.mdV[2])); + return ( (a.mdV[0] != b.mdV[0]) + ||(a.mdV[1] != b.mdV[1]) + ||(a.mdV[2] != b.mdV[2])); } inline const LLVector3d& operator+=(LLVector3d& a, const LLVector3d& b) { - a.mdV[0] += b.mdV[0]; - a.mdV[1] += b.mdV[1]; - a.mdV[2] += b.mdV[2]; - return a; + a.mdV[0] += b.mdV[0]; + a.mdV[1] += b.mdV[1]; + a.mdV[2] += b.mdV[2]; + return a; } inline const LLVector3d& operator-=(LLVector3d& a, const LLVector3d& b) { - a.mdV[0] -= b.mdV[0]; - a.mdV[1] -= b.mdV[1]; - a.mdV[2] -= b.mdV[2]; - return a; + a.mdV[0] -= b.mdV[0]; + a.mdV[1] -= b.mdV[1]; + a.mdV[2] -= b.mdV[2]; + return a; } inline const LLVector3d& operator%=(LLVector3d& a, const LLVector3d& b) { - LLVector3d ret( a.mdV[1]*b.mdV[2] - b.mdV[1]*a.mdV[2], a.mdV[2]*b.mdV[0] - b.mdV[2]*a.mdV[0], a.mdV[0]*b.mdV[1] - b.mdV[0]*a.mdV[1]); - a = ret; - return a; + LLVector3d ret( a.mdV[1]*b.mdV[2] - b.mdV[1]*a.mdV[2], a.mdV[2]*b.mdV[0] - b.mdV[2]*a.mdV[0], a.mdV[0]*b.mdV[1] - b.mdV[0]*a.mdV[1]); + a = ret; + return a; } inline const LLVector3d& operator*=(LLVector3d& a, const F64 k) { - a.mdV[0] *= k; - a.mdV[1] *= k; - a.mdV[2] *= k; - return a; + a.mdV[0] *= k; + a.mdV[1] *= k; + a.mdV[2] *= k; + return a; } inline const LLVector3d& operator/=(LLVector3d& a, const F64 k) { - F64 t = 1.f / k; - a.mdV[0] *= t; - a.mdV[1] *= t; - a.mdV[2] *= t; - return a; + F64 t = 1.f / k; + a.mdV[0] *= t; + a.mdV[1] *= t; + a.mdV[2] *= t; + return a; } inline LLVector3d operator-(const LLVector3d& a) { - return LLVector3d( -a.mdV[0], -a.mdV[1], -a.mdV[2] ); + return LLVector3d( -a.mdV[0], -a.mdV[1], -a.mdV[2] ); } -inline F64 dist_vec(const LLVector3d& a, const LLVector3d& b) +inline F64 dist_vec(const LLVector3d& a, const LLVector3d& b) { - F64 x = a.mdV[0] - b.mdV[0]; - F64 y = a.mdV[1] - b.mdV[1]; - F64 z = a.mdV[2] - b.mdV[2]; - return (F32) sqrt( x*x + y*y + z*z ); + F64 x = a.mdV[0] - b.mdV[0]; + F64 y = a.mdV[1] - b.mdV[1]; + F64 z = a.mdV[2] - b.mdV[2]; + return (F32) sqrt( x*x + y*y + z*z ); } -inline F64 dist_vec_squared(const LLVector3d& a, const LLVector3d& b) +inline F64 dist_vec_squared(const LLVector3d& a, const LLVector3d& b) { - F64 x = a.mdV[0] - b.mdV[0]; - F64 y = a.mdV[1] - b.mdV[1]; - F64 z = a.mdV[2] - b.mdV[2]; - return x*x + y*y + z*z; + F64 x = a.mdV[0] - b.mdV[0]; + F64 y = a.mdV[1] - b.mdV[1]; + F64 z = a.mdV[2] - b.mdV[2]; + return x*x + y*y + z*z; } -inline F64 dist_vec_squared2D(const LLVector3d& a, const LLVector3d& b) +inline F64 dist_vec_squared2D(const LLVector3d& a, const LLVector3d& b) { - F64 x = a.mdV[0] - b.mdV[0]; - F64 y = a.mdV[1] - b.mdV[1]; - return x*x + y*y; + F64 x = a.mdV[0] - b.mdV[0]; + F64 y = a.mdV[1] - b.mdV[1]; + return x*x + y*y; } inline LLVector3d lerp(const LLVector3d& a, const LLVector3d& b, const F64 u) { - return LLVector3d( - a.mdV[VX] + (b.mdV[VX] - a.mdV[VX]) * u, - a.mdV[VY] + (b.mdV[VY] - a.mdV[VY]) * u, - a.mdV[VZ] + (b.mdV[VZ] - a.mdV[VZ]) * u); + return LLVector3d( + a.mdV[VX] + (b.mdV[VX] - a.mdV[VX]) * u, + a.mdV[VY] + (b.mdV[VY] - a.mdV[VY]) * u, + a.mdV[VZ] + (b.mdV[VZ] - a.mdV[VZ]) * u); } -inline bool LLVector3d::isNull() const +inline bool LLVector3d::isNull() const { - if ( F_APPROXIMATELY_ZERO > mdV[VX]*mdV[VX] + mdV[VY]*mdV[VY] + mdV[VZ]*mdV[VZ] ) - { - return true; - } - return false; + if ( F_APPROXIMATELY_ZERO > mdV[VX]*mdV[VX] + mdV[VY]*mdV[VY] + mdV[VZ]*mdV[VZ] ) + { + return true; + } + return false; } inline F64 angle_between(const LLVector3d& a, const LLVector3d& b) { - LLVector3d an = a; - LLVector3d bn = b; - an.normalize(); - bn.normalize(); - F64 cosine = an * bn; - F64 angle = (cosine >= 1.0f) ? 0.0f : - (cosine <= -1.0f) ? F_PI : - acos(cosine); - return angle; + LLVector3d an = a; + LLVector3d bn = b; + an.normalize(); + bn.normalize(); + F64 cosine = an * bn; + F64 angle = (cosine >= 1.0f) ? 0.0f : + (cosine <= -1.0f) ? F_PI : + acos(cosine); + return angle; } inline bool are_parallel(const LLVector3d& a, const LLVector3d& b, const F64 epsilon) { - LLVector3d an = a; - LLVector3d bn = b; - an.normalize(); - bn.normalize(); - F64 dot = an * bn; - if ( (1.0f - fabs(dot)) < epsilon) - { - return true; - } - return false; + LLVector3d an = a; + LLVector3d bn = b; + an.normalize(); + bn.normalize(); + F64 dot = an * bn; + if ( (1.0f - fabs(dot)) < epsilon) + { + return true; + } + return false; } inline LLVector3d projected_vec(const LLVector3d& a, const LLVector3d& b) { - LLVector3d project_axis = b; - project_axis.normalize(); - return project_axis * (a * project_axis); + LLVector3d project_axis = b; + project_axis.normalize(); + return project_axis * (a * project_axis); } inline LLVector3d inverse_projected_vec(const LLVector3d& a, const LLVector3d& b) { - LLVector3d normalized_a = a; - normalized_a.normalize(); - LLVector3d normalized_b = b; - F64 b_length = normalized_b.normalize(); + LLVector3d normalized_a = a; + normalized_a.normalize(); + LLVector3d normalized_b = b; + F64 b_length = normalized_b.normalize(); - F64 dot_product = normalized_a * normalized_b; - return normalized_a * (b_length / dot_product); + F64 dot_product = normalized_a * normalized_b; + return normalized_a * (b_length / dot_product); } #endif // LL_V3DMATH_H diff --git a/indra/llmath/v3math.cpp b/indra/llmath/v3math.cpp index 72e73a79ec..73ad2a4ed6 100644 --- a/indra/llmath/v3math.cpp +++ b/indra/llmath/v3math.cpp @@ -1,25 +1,25 @@ -/** +/** * @file v3math.cpp * @brief LLVector3 class implementation. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -39,8 +39,8 @@ // LLVector3 // WARNING: Don't use these for global const definitions! -// For example: -// const LLQuaternion(0.5f * F_PI, LLVector3::zero); +// For example: +// const LLQuaternion(0.5f * F_PI, LLVector3::zero); // at the top of a *.cpp file might not give you what you think. const LLVector3 LLVector3::zero(0,0,0); const LLVector3 LLVector3::x_axis(1.f, 0, 0); @@ -56,97 +56,97 @@ const LLVector3 LLVector3::all_one(1.f,1.f,1.f); // Returns true if data changed. bool LLVector3::clamp(F32 min, F32 max) { - bool ret{ false }; + bool ret{ false }; - if (mV[0] < min) { mV[0] = min; ret = true; } - if (mV[1] < min) { mV[1] = min; ret = true; } - if (mV[2] < min) { mV[2] = min; ret = true; } + if (mV[0] < min) { mV[0] = min; ret = true; } + if (mV[1] < min) { mV[1] = min; ret = true; } + if (mV[2] < min) { mV[2] = min; ret = true; } - if (mV[0] > max) { mV[0] = max; ret = true; } - if (mV[1] > max) { mV[1] = max; ret = true; } - if (mV[2] > max) { mV[2] = max; ret = true; } + if (mV[0] > max) { mV[0] = max; ret = true; } + if (mV[1] > max) { mV[1] = max; ret = true; } + if (mV[2] > max) { mV[2] = max; ret = true; } - return ret; + return ret; } -// Clamps length to an upper limit. +// Clamps length to an upper limit. // Returns true if the data changed bool LLVector3::clampLength( F32 length_limit ) { - bool changed{ false }; - - F32 len = length(); - if (llfinite(len)) - { - if ( len > length_limit) - { - normalize(); - if (length_limit < 0.f) - { - length_limit = 0.f; - } - mV[0] *= length_limit; - mV[1] *= length_limit; - mV[2] *= length_limit; - changed = true; - } - } - else - { // this vector may still be salvagable - F32 max_abs_component = 0.f; - for (S32 i = 0; i < 3; ++i) - { - F32 abs_component = fabs(mV[i]); - if (llfinite(abs_component)) - { - if (abs_component > max_abs_component) - { - max_abs_component = abs_component; - } - } - else - { - // no it can't be salvaged --> clear it - clear(); - changed = true; - break; - } - } - if (!changed) - { - // yes it can be salvaged --> - // bring the components down before we normalize - mV[0] /= max_abs_component; - mV[1] /= max_abs_component; - mV[2] /= max_abs_component; - normalize(); - - if (length_limit < 0.f) - { - length_limit = 0.f; - } - mV[0] *= length_limit; - mV[1] *= length_limit; - mV[2] *= length_limit; - } - } - - return changed; + bool changed{ false }; + + F32 len = length(); + if (llfinite(len)) + { + if ( len > length_limit) + { + normalize(); + if (length_limit < 0.f) + { + length_limit = 0.f; + } + mV[0] *= length_limit; + mV[1] *= length_limit; + mV[2] *= length_limit; + changed = true; + } + } + else + { // this vector may still be salvagable + F32 max_abs_component = 0.f; + for (S32 i = 0; i < 3; ++i) + { + F32 abs_component = fabs(mV[i]); + if (llfinite(abs_component)) + { + if (abs_component > max_abs_component) + { + max_abs_component = abs_component; + } + } + else + { + // no it can't be salvaged --> clear it + clear(); + changed = true; + break; + } + } + if (!changed) + { + // yes it can be salvaged --> + // bring the components down before we normalize + mV[0] /= max_abs_component; + mV[1] /= max_abs_component; + mV[2] /= max_abs_component; + normalize(); + + if (length_limit < 0.f) + { + length_limit = 0.f; + } + mV[0] *= length_limit; + mV[1] *= length_limit; + mV[2] *= length_limit; + } + } + + return changed; } bool LLVector3::clamp(const LLVector3 &min_vec, const LLVector3 &max_vec) { - bool ret{ false }; + bool ret{ false }; - if (mV[0] < min_vec[0]) { mV[0] = min_vec[0]; ret = true; } - if (mV[1] < min_vec[1]) { mV[1] = min_vec[1]; ret = true; } - if (mV[2] < min_vec[2]) { mV[2] = min_vec[2]; ret = true; } + if (mV[0] < min_vec[0]) { mV[0] = min_vec[0]; ret = true; } + if (mV[1] < min_vec[1]) { mV[1] = min_vec[1]; ret = true; } + if (mV[2] < min_vec[2]) { mV[2] = min_vec[2]; ret = true; } - if (mV[0] > max_vec[0]) { mV[0] = max_vec[0]; ret = true; } - if (mV[1] > max_vec[1]) { mV[1] = max_vec[1]; ret = true; } - if (mV[2] > max_vec[2]) { mV[2] = max_vec[2]; ret = true; } + if (mV[0] > max_vec[0]) { mV[0] = max_vec[0]; ret = true; } + if (mV[1] > max_vec[1]) { mV[1] = max_vec[1]; ret = true; } + if (mV[2] > max_vec[2]) { mV[2] = max_vec[2]; ret = true; } - return ret; + return ret; } @@ -154,166 +154,166 @@ bool LLVector3::clamp(const LLVector3 &min_vec, const LLVector3 &max_vec) // Returns true if data changed bool LLVector3::abs() { - bool ret{ false }; + bool ret{ false }; - if (mV[0] < 0.f) { mV[0] = -mV[0]; ret = true; } - if (mV[1] < 0.f) { mV[1] = -mV[1]; ret = true; } - if (mV[2] < 0.f) { mV[2] = -mV[2]; ret = true; } + if (mV[0] < 0.f) { mV[0] = -mV[0]; ret = true; } + if (mV[1] < 0.f) { mV[1] = -mV[1]; ret = true; } + if (mV[2] < 0.f) { mV[2] = -mV[2]; ret = true; } - return ret; + return ret; } // Quatizations -void LLVector3::quantize16(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz) +void LLVector3::quantize16(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz) { - F32 x = mV[VX]; - F32 y = mV[VY]; - F32 z = mV[VZ]; + F32 x = mV[VX]; + F32 y = mV[VY]; + F32 z = mV[VZ]; - x = U16_to_F32(F32_to_U16(x, lowerxy, upperxy), lowerxy, upperxy); - y = U16_to_F32(F32_to_U16(y, lowerxy, upperxy), lowerxy, upperxy); - z = U16_to_F32(F32_to_U16(z, lowerz, upperz), lowerz, upperz); + x = U16_to_F32(F32_to_U16(x, lowerxy, upperxy), lowerxy, upperxy); + y = U16_to_F32(F32_to_U16(y, lowerxy, upperxy), lowerxy, upperxy); + z = U16_to_F32(F32_to_U16(z, lowerz, upperz), lowerz, upperz); - mV[VX] = x; - mV[VY] = y; - mV[VZ] = z; + mV[VX] = x; + mV[VY] = y; + mV[VZ] = z; } -void LLVector3::quantize8(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz) +void LLVector3::quantize8(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz) { - mV[VX] = U8_to_F32(F32_to_U8(mV[VX], lowerxy, upperxy), lowerxy, upperxy);; - mV[VY] = U8_to_F32(F32_to_U8(mV[VY], lowerxy, upperxy), lowerxy, upperxy); - mV[VZ] = U8_to_F32(F32_to_U8(mV[VZ], lowerz, upperz), lowerz, upperz); + mV[VX] = U8_to_F32(F32_to_U8(mV[VX], lowerxy, upperxy), lowerxy, upperxy);; + mV[VY] = U8_to_F32(F32_to_U8(mV[VY], lowerxy, upperxy), lowerxy, upperxy); + mV[VZ] = U8_to_F32(F32_to_U8(mV[VZ], lowerz, upperz), lowerz, upperz); } -void LLVector3::snap(S32 sig_digits) +void LLVector3::snap(S32 sig_digits) { - mV[VX] = snap_to_sig_figs(mV[VX], sig_digits); - mV[VY] = snap_to_sig_figs(mV[VY], sig_digits); - mV[VZ] = snap_to_sig_figs(mV[VZ], sig_digits); + mV[VX] = snap_to_sig_figs(mV[VX], sig_digits); + mV[VY] = snap_to_sig_figs(mV[VY], sig_digits); + mV[VZ] = snap_to_sig_figs(mV[VZ], sig_digits); } -const LLVector3& LLVector3::rotVec(const LLMatrix3 &mat) +const LLVector3& LLVector3::rotVec(const LLMatrix3 &mat) { - *this = *this * mat; - return *this; + *this = *this * mat; + return *this; } -const LLVector3& LLVector3::rotVec(const LLQuaternion &q) +const LLVector3& LLVector3::rotVec(const LLQuaternion &q) { - *this = *this * q; - return *this; + *this = *this * q; + return *this; } const LLVector3& LLVector3::transVec(const LLMatrix4& mat) { - setVec( - mV[VX] * mat.mMatrix[VX][VX] + - mV[VY] * mat.mMatrix[VX][VY] + - mV[VZ] * mat.mMatrix[VX][VZ] + - mat.mMatrix[VX][VW], - - mV[VX] * mat.mMatrix[VY][VX] + - mV[VY] * mat.mMatrix[VY][VY] + - mV[VZ] * mat.mMatrix[VY][VZ] + - mat.mMatrix[VY][VW], - - mV[VX] * mat.mMatrix[VZ][VX] + - mV[VY] * mat.mMatrix[VZ][VY] + - mV[VZ] * mat.mMatrix[VZ][VZ] + - mat.mMatrix[VZ][VW]); - - return *this; + setVec( + mV[VX] * mat.mMatrix[VX][VX] + + mV[VY] * mat.mMatrix[VX][VY] + + mV[VZ] * mat.mMatrix[VX][VZ] + + mat.mMatrix[VX][VW], + + mV[VX] * mat.mMatrix[VY][VX] + + mV[VY] * mat.mMatrix[VY][VY] + + mV[VZ] * mat.mMatrix[VY][VZ] + + mat.mMatrix[VY][VW], + + mV[VX] * mat.mMatrix[VZ][VX] + + mV[VY] * mat.mMatrix[VZ][VY] + + mV[VZ] * mat.mMatrix[VZ][VZ] + + mat.mMatrix[VZ][VW]); + + return *this; } -const LLVector3& LLVector3::rotVec(F32 angle, const LLVector3 &vec) +const LLVector3& LLVector3::rotVec(F32 angle, const LLVector3 &vec) { - if ( !vec.isExactlyZero() && angle ) - { - *this = *this * LLQuaternion(angle, vec); - } - return *this; + if ( !vec.isExactlyZero() && angle ) + { + *this = *this * LLQuaternion(angle, vec); + } + return *this; } -const LLVector3& LLVector3::rotVec(F32 angle, F32 x, F32 y, F32 z) +const LLVector3& LLVector3::rotVec(F32 angle, F32 x, F32 y, F32 z) { - LLVector3 vec(x, y, z); - if ( !vec.isExactlyZero() && angle ) - { - *this = *this * LLQuaternion(angle, vec); - } - return *this; + LLVector3 vec(x, y, z); + if ( !vec.isExactlyZero() && angle ) + { + *this = *this * LLQuaternion(angle, vec); + } + return *this; } -const LLVector3& LLVector3::scaleVec(const LLVector3& vec) +const LLVector3& LLVector3::scaleVec(const LLVector3& vec) { - mV[VX] *= vec.mV[VX]; - mV[VY] *= vec.mV[VY]; - mV[VZ] *= vec.mV[VZ]; + mV[VX] *= vec.mV[VX]; + mV[VY] *= vec.mV[VY]; + mV[VZ] *= vec.mV[VZ]; - return *this; + return *this; } -LLVector3 LLVector3::scaledVec(const LLVector3& vec) const +LLVector3 LLVector3::scaledVec(const LLVector3& vec) const { - LLVector3 ret = LLVector3(*this); - ret.scaleVec(vec); - return ret; + LLVector3 ret = LLVector3(*this); + ret.scaleVec(vec); + return ret; } -const LLVector3& LLVector3::set(const LLVector3d &vec) +const LLVector3& LLVector3::set(const LLVector3d &vec) { - mV[0] = (F32)vec.mdV[0]; - mV[1] = (F32)vec.mdV[1]; - mV[2] = (F32)vec.mdV[2]; - return (*this); + mV[0] = (F32)vec.mdV[0]; + mV[1] = (F32)vec.mdV[1]; + mV[2] = (F32)vec.mdV[2]; + return (*this); } -const LLVector3& LLVector3::set(const LLVector4 &vec) +const LLVector3& LLVector3::set(const LLVector4 &vec) { - mV[0] = vec.mV[0]; - mV[1] = vec.mV[1]; - mV[2] = vec.mV[2]; - return (*this); + mV[0] = vec.mV[0]; + mV[1] = vec.mV[1]; + mV[2] = vec.mV[2]; + return (*this); } -const LLVector3& LLVector3::setVec(const LLVector3d &vec) +const LLVector3& LLVector3::setVec(const LLVector3d &vec) { - mV[0] = (F32)vec.mdV[0]; - mV[1] = (F32)vec.mdV[1]; - mV[2] = (F32)vec.mdV[2]; - return (*this); + mV[0] = (F32)vec.mdV[0]; + mV[1] = (F32)vec.mdV[1]; + mV[2] = (F32)vec.mdV[2]; + return (*this); } -const LLVector3& LLVector3::setVec(const LLVector4 &vec) +const LLVector3& LLVector3::setVec(const LLVector4 &vec) { - mV[0] = vec.mV[0]; - mV[1] = vec.mV[1]; - mV[2] = vec.mV[2]; - return (*this); + mV[0] = vec.mV[0]; + mV[1] = vec.mV[1]; + mV[2] = vec.mV[2]; + return (*this); } LLVector3::LLVector3(const LLVector2 &vec) { - mV[VX] = (F32)vec.mV[VX]; - mV[VY] = (F32)vec.mV[VY]; - mV[VZ] = 0; + mV[VX] = (F32)vec.mV[VX]; + mV[VY] = (F32)vec.mV[VY]; + mV[VZ] = 0; } LLVector3::LLVector3(const LLVector3d &vec) { - mV[VX] = (F32)vec.mdV[VX]; - mV[VY] = (F32)vec.mdV[VY]; - mV[VZ] = (F32)vec.mdV[VZ]; + mV[VX] = (F32)vec.mdV[VX]; + mV[VY] = (F32)vec.mdV[VY]; + mV[VZ] = (F32)vec.mdV[VZ]; } LLVector3::LLVector3(const LLVector4 &vec) { - mV[VX] = (F32)vec.mV[VX]; - mV[VY] = (F32)vec.mV[VY]; - mV[VZ] = (F32)vec.mV[VZ]; + mV[VX] = (F32)vec.mV[VX]; + mV[VY] = (F32)vec.mV[VY]; + mV[VZ] = (F32)vec.mV[VZ]; } LLVector3::LLVector3(const LLVector4a& vec) @@ -324,23 +324,23 @@ LLVector3::LLVector3(const LLVector4a& vec) LLVector3::LLVector3(const LLSD& sd) { - setValue(sd); + setValue(sd); } LLSD LLVector3::getValue() const { - LLSD ret; - ret[0] = mV[0]; - ret[1] = mV[1]; - ret[2] = mV[2]; - return ret; + LLSD ret; + ret[0] = mV[0]; + ret[1] = mV[1]; + ret[2] = mV[2]; + return ret; } void LLVector3::setValue(const LLSD& sd) { - mV[0] = (F32) sd[0].asReal(); - mV[1] = (F32) sd[1].asReal(); - mV[2] = (F32) sd[2].asReal(); + mV[0] = (F32) sd[0].asReal(); + mV[1] = (F32) sd[1].asReal(); + mV[2] = (F32) sd[2].asReal(); } const LLVector3& operator*=(LLVector3 &a, const LLQuaternion &rot) @@ -349,31 +349,31 @@ const LLVector3& operator*=(LLVector3 &a, const LLQuaternion &rot) const F32 rx = rot.mQ[VW] * a.mV[VX] + rot.mQ[VY] * a.mV[VZ] - rot.mQ[VZ] * a.mV[VY]; const F32 ry = rot.mQ[VW] * a.mV[VY] + rot.mQ[VZ] * a.mV[VX] - rot.mQ[VX] * a.mV[VZ]; const F32 rz = rot.mQ[VW] * a.mV[VZ] + rot.mQ[VX] * a.mV[VY] - rot.mQ[VY] * a.mV[VX]; - + a.mV[VX] = - rw * rot.mQ[VX] + rx * rot.mQ[VW] - ry * rot.mQ[VZ] + rz * rot.mQ[VY]; a.mV[VY] = - rw * rot.mQ[VY] + ry * rot.mQ[VW] - rz * rot.mQ[VX] + rx * rot.mQ[VZ]; a.mV[VZ] = - rw * rot.mQ[VZ] + rz * rot.mQ[VW] - rx * rot.mQ[VY] + ry * rot.mQ[VX]; - return a; + return a; } -// static +// static bool LLVector3::parseVector3(const std::string& buf, LLVector3* value) { - if( buf.empty() || value == nullptr) - { - return false; - } - - LLVector3 v; - S32 count = sscanf( buf.c_str(), "%f %f %f", v.mV + 0, v.mV + 1, v.mV + 2 ); - if( 3 == count ) - { - value->setVec( v ); - return true; - } - - return false; + if( buf.empty() || value == nullptr) + { + return false; + } + + LLVector3 v; + S32 count = sscanf( buf.c_str(), "%f %f %f", v.mV + 0, v.mV + 1, v.mV + 2 ); + if( 3 == count ) + { + value->setVec( v ); + return true; + } + + return false; } // Displacement from query point to nearest neighbor point on bounding box. diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h index fa6ad06008..d063b15c74 100644 --- a/indra/llmath/v3math.h +++ b/indra/llmath/v3math.h @@ -5,21 +5,21 @@ * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -45,122 +45,122 @@ static const U32 LENGTHOFVECTOR3 = 3; class LLVector3 { - public: - F32 mV[LENGTHOFVECTOR3]; - - static const LLVector3 zero; - static const LLVector3 x_axis; - static const LLVector3 y_axis; - static const LLVector3 z_axis; - static const LLVector3 x_axis_neg; - static const LLVector3 y_axis_neg; - static const LLVector3 z_axis_neg; - static const LLVector3 all_one; - - inline LLVector3(); // Initializes LLVector3 to (0, 0, 0) - inline LLVector3(const F32 x, const F32 y, const F32 z); // Initializes LLVector3 to (x. y, z) - inline explicit LLVector3(const F32 *vec); // Initializes LLVector3 to (vec[0]. vec[1], vec[2]) - explicit LLVector3(const LLVector2 &vec); // Initializes LLVector3 to (vec[0]. vec[1], 0) - explicit LLVector3(const LLVector3d &vec); // Initializes LLVector3 to (vec[0]. vec[1], vec[2]) - explicit LLVector3(const LLVector4 &vec); // Initializes LLVector4 to (vec[0]. vec[1], vec[2]) + public: + F32 mV[LENGTHOFVECTOR3]; + + static const LLVector3 zero; + static const LLVector3 x_axis; + static const LLVector3 y_axis; + static const LLVector3 z_axis; + static const LLVector3 x_axis_neg; + static const LLVector3 y_axis_neg; + static const LLVector3 z_axis_neg; + static const LLVector3 all_one; + + inline LLVector3(); // Initializes LLVector3 to (0, 0, 0) + inline LLVector3(const F32 x, const F32 y, const F32 z); // Initializes LLVector3 to (x. y, z) + inline explicit LLVector3(const F32 *vec); // Initializes LLVector3 to (vec[0]. vec[1], vec[2]) + explicit LLVector3(const LLVector2 &vec); // Initializes LLVector3 to (vec[0]. vec[1], 0) + explicit LLVector3(const LLVector3d &vec); // Initializes LLVector3 to (vec[0]. vec[1], vec[2]) + explicit LLVector3(const LLVector4 &vec); // Initializes LLVector4 to (vec[0]. vec[1], vec[2]) explicit LLVector3(const LLVector4a& vec); // Initializes LLVector4 to (vec[0]. vec[1], vec[2]) explicit LLVector3(const LLSD& sd); - - - LLSD getValue() const; - - void setValue(const LLSD& sd); - - inline bool isFinite() const; // checks to see if all values of LLVector3 are finite - bool clamp(F32 min, F32 max); // Clamps all values to (min,max), returns true if data changed - bool clamp(const LLVector3 &min_vec, const LLVector3 &max_vec); // Scales vector by another vector - bool clampLength( F32 length_limit ); // Scales vector to limit length to a value - - void quantize16(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz); // changes the vector to reflect quatization - void quantize8(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz); // changes the vector to reflect quatization - void snap(S32 sig_digits); // snaps x,y,z to sig_digits decimal places - - bool abs(); // sets all values to absolute value of original value (first octant), returns true if changed - - inline void clear(); // Clears LLVector3 to (0, 0, 0) - inline void setZero(); // Clears LLVector3 to (0, 0, 0) - inline void clearVec(); // deprecated - inline void zeroVec(); // deprecated - - inline void set(F32 x, F32 y, F32 z); // Sets LLVector3 to (x, y, z, 1) - inline void set(const LLVector3 &vec); // Sets LLVector3 to vec - inline void set(const F32 *vec); // Sets LLVector3 to vec - const LLVector3& set(const LLVector4 &vec); - const LLVector3& set(const LLVector3d &vec);// Sets LLVector3 to vec - - inline void setVec(F32 x, F32 y, F32 z); // deprecated - inline void setVec(const LLVector3 &vec); // deprecated - inline void setVec(const F32 *vec); // deprecated - - const LLVector3& setVec(const LLVector4 &vec); // deprecated - const LLVector3& setVec(const LLVector3d &vec); // deprecated - - F32 length() const; // Returns magnitude of LLVector3 - F32 lengthSquared() const; // Returns magnitude squared of LLVector3 - F32 magVec() const; // deprecated - F32 magVecSquared() const; // deprecated - - inline F32 normalize(); // Normalizes and returns the magnitude of LLVector3 - inline F32 normVec(); // deprecated - - inline bool inRange( F32 min, F32 max ) const; // Returns true if all values of the vector are between min and max - - const LLVector3& rotVec(F32 angle, const LLVector3 &vec); // Rotates about vec by angle radians - const LLVector3& rotVec(F32 angle, F32 x, F32 y, F32 z); // Rotates about x,y,z by angle radians - const LLVector3& rotVec(const LLMatrix3 &mat); // Rotates by LLMatrix4 mat - const LLVector3& rotVec(const LLQuaternion &q); // Rotates by LLQuaternion q - const LLVector3& transVec(const LLMatrix4& mat); // Transforms by LLMatrix4 mat (mat * v) - - const LLVector3& scaleVec(const LLVector3& vec); // scales per component by vec - LLVector3 scaledVec(const LLVector3& vec) const; // get a copy of this vector scaled by vec - - bool isNull() const; // Returns true if vector has a _very_small_ length - bool isExactlyZero() const { return !mV[VX] && !mV[VY] && !mV[VZ]; } - - F32 operator[](int idx) const { return mV[idx]; } - F32 &operator[](int idx) { return mV[idx]; } - - friend LLVector3 operator+(const LLVector3 &a, const LLVector3 &b); // Return vector a + b - friend LLVector3 operator-(const LLVector3 &a, const LLVector3 &b); // Return vector a minus b - friend F32 operator*(const LLVector3 &a, const LLVector3 &b); // Return a dot b - friend LLVector3 operator%(const LLVector3 &a, const LLVector3 &b); // Return a cross b - friend LLVector3 operator*(const LLVector3 &a, F32 k); // Return a times scaler k - friend LLVector3 operator/(const LLVector3 &a, F32 k); // Return a divided by scaler k - friend LLVector3 operator*(F32 k, const LLVector3 &a); // Return a times scaler k - friend bool operator==(const LLVector3 &a, const LLVector3 &b); // Return a == b - friend bool operator!=(const LLVector3 &a, const LLVector3 &b); // Return a != b - // less than operator useful for using vectors as std::map keys - friend bool operator<(const LLVector3 &a, const LLVector3 &b); // Return a < b - - friend const LLVector3& operator+=(LLVector3 &a, const LLVector3 &b); // Return vector a + b - friend const LLVector3& operator-=(LLVector3 &a, const LLVector3 &b); // Return vector a minus b - friend const LLVector3& operator%=(LLVector3 &a, const LLVector3 &b); // Return a cross b - friend const LLVector3& operator*=(LLVector3 &a, const LLVector3 &b); // Returns a * b; - friend const LLVector3& operator*=(LLVector3 &a, F32 k); // Return a times scaler k - friend const LLVector3& operator/=(LLVector3 &a, F32 k); // Return a divided by scaler k - friend const LLVector3& operator*=(LLVector3 &a, const LLQuaternion &b); // Returns a * b; - - friend LLVector3 operator-(const LLVector3 &a); // Return vector -a - - friend std::ostream& operator<<(std::ostream& s, const LLVector3 &a); // Stream a - - static bool parseVector3(const std::string& buf, LLVector3* value); + + + LLSD getValue() const; + + void setValue(const LLSD& sd); + + inline bool isFinite() const; // checks to see if all values of LLVector3 are finite + bool clamp(F32 min, F32 max); // Clamps all values to (min,max), returns true if data changed + bool clamp(const LLVector3 &min_vec, const LLVector3 &max_vec); // Scales vector by another vector + bool clampLength( F32 length_limit ); // Scales vector to limit length to a value + + void quantize16(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz); // changes the vector to reflect quatization + void quantize8(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz); // changes the vector to reflect quatization + void snap(S32 sig_digits); // snaps x,y,z to sig_digits decimal places + + bool abs(); // sets all values to absolute value of original value (first octant), returns true if changed + + inline void clear(); // Clears LLVector3 to (0, 0, 0) + inline void setZero(); // Clears LLVector3 to (0, 0, 0) + inline void clearVec(); // deprecated + inline void zeroVec(); // deprecated + + inline void set(F32 x, F32 y, F32 z); // Sets LLVector3 to (x, y, z, 1) + inline void set(const LLVector3 &vec); // Sets LLVector3 to vec + inline void set(const F32 *vec); // Sets LLVector3 to vec + const LLVector3& set(const LLVector4 &vec); + const LLVector3& set(const LLVector3d &vec);// Sets LLVector3 to vec + + inline void setVec(F32 x, F32 y, F32 z); // deprecated + inline void setVec(const LLVector3 &vec); // deprecated + inline void setVec(const F32 *vec); // deprecated + + const LLVector3& setVec(const LLVector4 &vec); // deprecated + const LLVector3& setVec(const LLVector3d &vec); // deprecated + + F32 length() const; // Returns magnitude of LLVector3 + F32 lengthSquared() const; // Returns magnitude squared of LLVector3 + F32 magVec() const; // deprecated + F32 magVecSquared() const; // deprecated + + inline F32 normalize(); // Normalizes and returns the magnitude of LLVector3 + inline F32 normVec(); // deprecated + + inline bool inRange( F32 min, F32 max ) const; // Returns true if all values of the vector are between min and max + + const LLVector3& rotVec(F32 angle, const LLVector3 &vec); // Rotates about vec by angle radians + const LLVector3& rotVec(F32 angle, F32 x, F32 y, F32 z); // Rotates about x,y,z by angle radians + const LLVector3& rotVec(const LLMatrix3 &mat); // Rotates by LLMatrix4 mat + const LLVector3& rotVec(const LLQuaternion &q); // Rotates by LLQuaternion q + const LLVector3& transVec(const LLMatrix4& mat); // Transforms by LLMatrix4 mat (mat * v) + + const LLVector3& scaleVec(const LLVector3& vec); // scales per component by vec + LLVector3 scaledVec(const LLVector3& vec) const; // get a copy of this vector scaled by vec + + bool isNull() const; // Returns true if vector has a _very_small_ length + bool isExactlyZero() const { return !mV[VX] && !mV[VY] && !mV[VZ]; } + + F32 operator[](int idx) const { return mV[idx]; } + F32 &operator[](int idx) { return mV[idx]; } + + friend LLVector3 operator+(const LLVector3 &a, const LLVector3 &b); // Return vector a + b + friend LLVector3 operator-(const LLVector3 &a, const LLVector3 &b); // Return vector a minus b + friend F32 operator*(const LLVector3 &a, const LLVector3 &b); // Return a dot b + friend LLVector3 operator%(const LLVector3 &a, const LLVector3 &b); // Return a cross b + friend LLVector3 operator*(const LLVector3 &a, F32 k); // Return a times scaler k + friend LLVector3 operator/(const LLVector3 &a, F32 k); // Return a divided by scaler k + friend LLVector3 operator*(F32 k, const LLVector3 &a); // Return a times scaler k + friend bool operator==(const LLVector3 &a, const LLVector3 &b); // Return a == b + friend bool operator!=(const LLVector3 &a, const LLVector3 &b); // Return a != b + // less than operator useful for using vectors as std::map keys + friend bool operator<(const LLVector3 &a, const LLVector3 &b); // Return a < b + + friend const LLVector3& operator+=(LLVector3 &a, const LLVector3 &b); // Return vector a + b + friend const LLVector3& operator-=(LLVector3 &a, const LLVector3 &b); // Return vector a minus b + friend const LLVector3& operator%=(LLVector3 &a, const LLVector3 &b); // Return a cross b + friend const LLVector3& operator*=(LLVector3 &a, const LLVector3 &b); // Returns a * b; + friend const LLVector3& operator*=(LLVector3 &a, F32 k); // Return a times scaler k + friend const LLVector3& operator/=(LLVector3 &a, F32 k); // Return a divided by scaler k + friend const LLVector3& operator*=(LLVector3 &a, const LLQuaternion &b); // Returns a * b; + + friend LLVector3 operator-(const LLVector3 &a); // Return vector -a + + friend std::ostream& operator<<(std::ostream& s, const LLVector3 &a); // Stream a + + static bool parseVector3(const std::string& buf, LLVector3* value); }; typedef LLVector3 LLSimLocalVec; -// Non-member functions +// Non-member functions -F32 angle_between(const LLVector3 &a, const LLVector3 &b); // Returns angle (radians) between a and b -bool are_parallel(const LLVector3 &a, const LLVector3 &b, F32 epsilon=F_APPROXIMATELY_ZERO); // Returns true if a and b are very close to parallel -F32 dist_vec(const LLVector3 &a, const LLVector3 &b); // Returns distance between a and b -F32 dist_vec_squared(const LLVector3 &a, const LLVector3 &b);// Returns distance squared between a and b -F32 dist_vec_squared2D(const LLVector3 &a, const LLVector3 &b);// Returns distance squared between a and b ignoring Z component +F32 angle_between(const LLVector3 &a, const LLVector3 &b); // Returns angle (radians) between a and b +bool are_parallel(const LLVector3 &a, const LLVector3 &b, F32 epsilon=F_APPROXIMATELY_ZERO); // Returns true if a and b are very close to parallel +F32 dist_vec(const LLVector3 &a, const LLVector3 &b); // Returns distance between a and b +F32 dist_vec_squared(const LLVector3 &a, const LLVector3 &b);// Returns distance squared between a and b +F32 dist_vec_squared2D(const LLVector3 &a, const LLVector3 &b);// Returns distance squared between a and b ignoring Z component LLVector3 projected_vec(const LLVector3 &a, const LLVector3 &b); // Returns vector a projected on vector b LLVector3 inverse_projected_vec(const LLVector3 &a, const LLVector3 &b); // Returns vector a scaled such that projected_vec(inverse_projected_vec(a, b), b) == b; LLVector3 parallel_component(const LLVector3 &a, const LLVector3 &b); // Returns vector a projected on vector b (same as projected_vec) @@ -171,31 +171,31 @@ bool box_valid_and_non_zero(const LLVector3* box); inline LLVector3::LLVector3(void) { - mV[0] = 0.f; - mV[1] = 0.f; - mV[2] = 0.f; + mV[0] = 0.f; + mV[1] = 0.f; + mV[2] = 0.f; } inline LLVector3::LLVector3(const F32 x, const F32 y, const F32 z) { - mV[VX] = x; - mV[VY] = y; - mV[VZ] = z; + mV[VX] = x; + mV[VY] = y; + mV[VZ] = z; } inline LLVector3::LLVector3(const F32 *vec) { - mV[VX] = vec[VX]; - mV[VY] = vec[VY]; - mV[VZ] = vec[VZ]; + mV[VX] = vec[VX]; + mV[VY] = vec[VY]; + mV[VZ] = vec[VZ]; } /* inline LLVector3::LLVector3(const LLVector3 ©) { - mV[VX] = copy.mV[VX]; - mV[VY] = copy.mV[VY]; - mV[VZ] = copy.mV[VZ]; + mV[VX] = copy.mV[VX]; + mV[VY] = copy.mV[VY]; + mV[VZ] = copy.mV[VZ]; } */ @@ -204,409 +204,409 @@ inline LLVector3::LLVector3(const LLVector3 ©) // checker inline bool LLVector3::isFinite() const { - return (llfinite(mV[VX]) && llfinite(mV[VY]) && llfinite(mV[VZ])); + return (llfinite(mV[VX]) && llfinite(mV[VY]) && llfinite(mV[VZ])); } // Clear and Assignment Functions -inline void LLVector3::clear(void) +inline void LLVector3::clear(void) { - mV[0] = 0.f; - mV[1] = 0.f; - mV[2] = 0.f; + mV[0] = 0.f; + mV[1] = 0.f; + mV[2] = 0.f; } -inline void LLVector3::setZero(void) +inline void LLVector3::setZero(void) { - mV[0] = 0.f; - mV[1] = 0.f; - mV[2] = 0.f; + mV[0] = 0.f; + mV[1] = 0.f; + mV[2] = 0.f; } -inline void LLVector3::clearVec(void) +inline void LLVector3::clearVec(void) { - mV[0] = 0.f; - mV[1] = 0.f; - mV[2] = 0.f; + mV[0] = 0.f; + mV[1] = 0.f; + mV[2] = 0.f; } -inline void LLVector3::zeroVec(void) +inline void LLVector3::zeroVec(void) { - mV[0] = 0.f; - mV[1] = 0.f; - mV[2] = 0.f; + mV[0] = 0.f; + mV[1] = 0.f; + mV[2] = 0.f; } -inline void LLVector3::set(F32 x, F32 y, F32 z) +inline void LLVector3::set(F32 x, F32 y, F32 z) { - mV[VX] = x; - mV[VY] = y; - mV[VZ] = z; + mV[VX] = x; + mV[VY] = y; + mV[VZ] = z; } -inline void LLVector3::set(const LLVector3 &vec) +inline void LLVector3::set(const LLVector3 &vec) { - mV[0] = vec.mV[0]; - mV[1] = vec.mV[1]; - mV[2] = vec.mV[2]; + mV[0] = vec.mV[0]; + mV[1] = vec.mV[1]; + mV[2] = vec.mV[2]; } -inline void LLVector3::set(const F32 *vec) +inline void LLVector3::set(const F32 *vec) { - mV[0] = vec[0]; - mV[1] = vec[1]; - mV[2] = vec[2]; + mV[0] = vec[0]; + mV[1] = vec[1]; + mV[2] = vec[2]; } // deprecated -inline void LLVector3::setVec(F32 x, F32 y, F32 z) +inline void LLVector3::setVec(F32 x, F32 y, F32 z) { - mV[VX] = x; - mV[VY] = y; - mV[VZ] = z; + mV[VX] = x; + mV[VY] = y; + mV[VZ] = z; } // deprecated -inline void LLVector3::setVec(const LLVector3 &vec) +inline void LLVector3::setVec(const LLVector3 &vec) { - mV[0] = vec.mV[0]; - mV[1] = vec.mV[1]; - mV[2] = vec.mV[2]; + mV[0] = vec.mV[0]; + mV[1] = vec.mV[1]; + mV[2] = vec.mV[2]; } // deprecated -inline void LLVector3::setVec(const F32 *vec) +inline void LLVector3::setVec(const F32 *vec) { - mV[0] = vec[0]; - mV[1] = vec[1]; - mV[2] = vec[2]; + mV[0] = vec[0]; + mV[1] = vec[1]; + mV[2] = vec[2]; } inline F32 LLVector3::normalize(void) { - F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); - F32 oomag; - - if (mag > FP_MAG_THRESHOLD) - { - oomag = 1.f/mag; - mV[0] *= oomag; - mV[1] *= oomag; - mV[2] *= oomag; - } - else - { - mV[0] = 0.f; - mV[1] = 0.f; - mV[2] = 0.f; - mag = 0; - } - return (mag); + F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + F32 oomag; + + if (mag > FP_MAG_THRESHOLD) + { + oomag = 1.f/mag; + mV[0] *= oomag; + mV[1] *= oomag; + mV[2] *= oomag; + } + else + { + mV[0] = 0.f; + mV[1] = 0.f; + mV[2] = 0.f; + mag = 0; + } + return (mag); } // deprecated inline F32 LLVector3::normVec(void) { - F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); - F32 oomag; - - if (mag > FP_MAG_THRESHOLD) - { - oomag = 1.f/mag; - mV[0] *= oomag; - mV[1] *= oomag; - mV[2] *= oomag; - } - else - { - mV[0] = 0.f; - mV[1] = 0.f; - mV[2] = 0.f; - mag = 0; - } - return (mag); + F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + F32 oomag; + + if (mag > FP_MAG_THRESHOLD) + { + oomag = 1.f/mag; + mV[0] *= oomag; + mV[1] *= oomag; + mV[2] *= oomag; + } + else + { + mV[0] = 0.f; + mV[1] = 0.f; + mV[2] = 0.f; + mag = 0; + } + return (mag); } // LLVector3 Magnitude and Normalization Functions -inline F32 LLVector3::length(void) const +inline F32 LLVector3::length(void) const { - return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); } -inline F32 LLVector3::lengthSquared(void) const +inline F32 LLVector3::lengthSquared(void) const { - return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]; + return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]; } -inline F32 LLVector3::magVec(void) const +inline F32 LLVector3::magVec(void) const { - return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); } -inline F32 LLVector3::magVecSquared(void) const +inline F32 LLVector3::magVecSquared(void) const { - return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]; + return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]; } inline bool LLVector3::inRange( F32 min, F32 max ) const { - return mV[0] >= min && mV[0] <= max && - mV[1] >= min && mV[1] <= max && - mV[2] >= min && mV[2] <= max; + return mV[0] >= min && mV[0] <= max && + mV[1] >= min && mV[1] <= max && + mV[2] >= min && mV[2] <= max; } inline LLVector3 operator+(const LLVector3 &a, const LLVector3 &b) { - LLVector3 c(a); - return c += b; + LLVector3 c(a); + return c += b; } inline LLVector3 operator-(const LLVector3 &a, const LLVector3 &b) { - LLVector3 c(a); - return c -= b; + LLVector3 c(a); + return c -= b; } inline F32 operator*(const LLVector3 &a, const LLVector3 &b) { - return (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1] + a.mV[2]*b.mV[2]); + return (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1] + a.mV[2]*b.mV[2]); } inline LLVector3 operator%(const LLVector3 &a, const LLVector3 &b) { - return LLVector3( a.mV[1]*b.mV[2] - b.mV[1]*a.mV[2], a.mV[2]*b.mV[0] - b.mV[2]*a.mV[0], a.mV[0]*b.mV[1] - b.mV[0]*a.mV[1] ); + return LLVector3( a.mV[1]*b.mV[2] - b.mV[1]*a.mV[2], a.mV[2]*b.mV[0] - b.mV[2]*a.mV[0], a.mV[0]*b.mV[1] - b.mV[0]*a.mV[1] ); } inline LLVector3 operator/(const LLVector3 &a, F32 k) { - F32 t = 1.f / k; - return LLVector3( a.mV[0] * t, a.mV[1] * t, a.mV[2] * t ); + F32 t = 1.f / k; + return LLVector3( a.mV[0] * t, a.mV[1] * t, a.mV[2] * t ); } inline LLVector3 operator*(const LLVector3 &a, F32 k) { - return LLVector3( a.mV[0] * k, a.mV[1] * k, a.mV[2] * k ); + return LLVector3( a.mV[0] * k, a.mV[1] * k, a.mV[2] * k ); } inline LLVector3 operator*(F32 k, const LLVector3 &a) { - return LLVector3( a.mV[0] * k, a.mV[1] * k, a.mV[2] * k ); + return LLVector3( a.mV[0] * k, a.mV[1] * k, a.mV[2] * k ); } inline bool operator==(const LLVector3 &a, const LLVector3 &b) { - return ( (a.mV[0] == b.mV[0]) - &&(a.mV[1] == b.mV[1]) - &&(a.mV[2] == b.mV[2])); + return ( (a.mV[0] == b.mV[0]) + &&(a.mV[1] == b.mV[1]) + &&(a.mV[2] == b.mV[2])); } inline bool operator!=(const LLVector3 &a, const LLVector3 &b) { - return ( (a.mV[0] != b.mV[0]) - ||(a.mV[1] != b.mV[1]) - ||(a.mV[2] != b.mV[2])); + return ( (a.mV[0] != b.mV[0]) + ||(a.mV[1] != b.mV[1]) + ||(a.mV[2] != b.mV[2])); } inline bool operator<(const LLVector3 &a, const LLVector3 &b) { - return (a.mV[0] < b.mV[0] - || (a.mV[0] == b.mV[0] - && (a.mV[1] < b.mV[1] - || ((a.mV[1] == b.mV[1]) - && a.mV[2] < b.mV[2])))); + return (a.mV[0] < b.mV[0] + || (a.mV[0] == b.mV[0] + && (a.mV[1] < b.mV[1] + || ((a.mV[1] == b.mV[1]) + && a.mV[2] < b.mV[2])))); } inline const LLVector3& operator+=(LLVector3 &a, const LLVector3 &b) { - a.mV[0] += b.mV[0]; - a.mV[1] += b.mV[1]; - a.mV[2] += b.mV[2]; - return a; + a.mV[0] += b.mV[0]; + a.mV[1] += b.mV[1]; + a.mV[2] += b.mV[2]; + return a; } inline const LLVector3& operator-=(LLVector3 &a, const LLVector3 &b) { - a.mV[0] -= b.mV[0]; - a.mV[1] -= b.mV[1]; - a.mV[2] -= b.mV[2]; - return a; + a.mV[0] -= b.mV[0]; + a.mV[1] -= b.mV[1]; + a.mV[2] -= b.mV[2]; + return a; } inline const LLVector3& operator%=(LLVector3 &a, const LLVector3 &b) { - LLVector3 ret( a.mV[1]*b.mV[2] - b.mV[1]*a.mV[2], a.mV[2]*b.mV[0] - b.mV[2]*a.mV[0], a.mV[0]*b.mV[1] - b.mV[0]*a.mV[1]); - a = ret; - return a; + LLVector3 ret( a.mV[1]*b.mV[2] - b.mV[1]*a.mV[2], a.mV[2]*b.mV[0] - b.mV[2]*a.mV[0], a.mV[0]*b.mV[1] - b.mV[0]*a.mV[1]); + a = ret; + return a; } inline const LLVector3& operator*=(LLVector3 &a, F32 k) { - a.mV[0] *= k; - a.mV[1] *= k; - a.mV[2] *= k; - return a; + a.mV[0] *= k; + a.mV[1] *= k; + a.mV[2] *= k; + return a; } inline const LLVector3& operator*=(LLVector3 &a, const LLVector3 &b) { - a.mV[0] *= b.mV[0]; - a.mV[1] *= b.mV[1]; - a.mV[2] *= b.mV[2]; - return a; + a.mV[0] *= b.mV[0]; + a.mV[1] *= b.mV[1]; + a.mV[2] *= b.mV[2]; + return a; } inline const LLVector3& operator/=(LLVector3 &a, F32 k) { - F32 t = 1.f / k; - a.mV[0] *= t; - a.mV[1] *= t; - a.mV[2] *= t; - return a; + F32 t = 1.f / k; + a.mV[0] *= t; + a.mV[1] *= t; + a.mV[2] *= t; + return a; } inline LLVector3 operator-(const LLVector3 &a) { - return LLVector3( -a.mV[0], -a.mV[1], -a.mV[2] ); + return LLVector3( -a.mV[0], -a.mV[1], -a.mV[2] ); } -inline F32 dist_vec(const LLVector3 &a, const LLVector3 &b) +inline F32 dist_vec(const LLVector3 &a, const LLVector3 &b) { - F32 x = a.mV[0] - b.mV[0]; - F32 y = a.mV[1] - b.mV[1]; - F32 z = a.mV[2] - b.mV[2]; - return (F32) sqrt( x*x + y*y + z*z ); + F32 x = a.mV[0] - b.mV[0]; + F32 y = a.mV[1] - b.mV[1]; + F32 z = a.mV[2] - b.mV[2]; + return (F32) sqrt( x*x + y*y + z*z ); } -inline F32 dist_vec_squared(const LLVector3 &a, const LLVector3 &b) +inline F32 dist_vec_squared(const LLVector3 &a, const LLVector3 &b) { - F32 x = a.mV[0] - b.mV[0]; - F32 y = a.mV[1] - b.mV[1]; - F32 z = a.mV[2] - b.mV[2]; - return x*x + y*y + z*z; + F32 x = a.mV[0] - b.mV[0]; + F32 y = a.mV[1] - b.mV[1]; + F32 z = a.mV[2] - b.mV[2]; + return x*x + y*y + z*z; } -inline F32 dist_vec_squared2D(const LLVector3 &a, const LLVector3 &b) +inline F32 dist_vec_squared2D(const LLVector3 &a, const LLVector3 &b) { - F32 x = a.mV[0] - b.mV[0]; - F32 y = a.mV[1] - b.mV[1]; - return x*x + y*y; + F32 x = a.mV[0] - b.mV[0]; + F32 y = a.mV[1] - b.mV[1]; + return x*x + y*y; } inline LLVector3 projected_vec(const LLVector3 &a, const LLVector3 &b) { - F32 bb = b * b; - if (bb > FP_MAG_THRESHOLD * FP_MAG_THRESHOLD) - { - return ((a * b) / bb) * b; - } - else - { - return b.zero; - } + F32 bb = b * b; + if (bb > FP_MAG_THRESHOLD * FP_MAG_THRESHOLD) + { + return ((a * b) / bb) * b; + } + else + { + return b.zero; + } } inline LLVector3 inverse_projected_vec(const LLVector3& a, const LLVector3& b) { - LLVector3 normalized_a = a; - normalized_a.normalize(); - LLVector3 normalized_b = b; - F32 b_length = normalized_b.normalize(); + LLVector3 normalized_a = a; + normalized_a.normalize(); + LLVector3 normalized_b = b; + F32 b_length = normalized_b.normalize(); - F32 dot_product = normalized_a * normalized_b; - //NB: if a _|_ b, then returns an infinite vector - return normalized_a * (b_length / dot_product); + F32 dot_product = normalized_a * normalized_b; + //NB: if a _|_ b, then returns an infinite vector + return normalized_a * (b_length / dot_product); } inline LLVector3 parallel_component(const LLVector3 &a, const LLVector3 &b) { - return projected_vec(a, b); + return projected_vec(a, b); } inline LLVector3 orthogonal_component(const LLVector3 &a, const LLVector3 &b) { - return a - projected_vec(a, b); + return a - projected_vec(a, b); } inline LLVector3 lerp(const LLVector3 &a, const LLVector3 &b, F32 u) { - return LLVector3( - a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u, - a.mV[VY] + (b.mV[VY] - a.mV[VY]) * u, - a.mV[VZ] + (b.mV[VZ] - a.mV[VZ]) * u); + return LLVector3( + a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u, + a.mV[VY] + (b.mV[VY] - a.mV[VY]) * u, + a.mV[VZ] + (b.mV[VZ] - a.mV[VZ]) * u); } -inline bool LLVector3::isNull() const +inline bool LLVector3::isNull() const { - if ( F_APPROXIMATELY_ZERO > mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ] ) - { - return true; - } - return false; + if ( F_APPROXIMATELY_ZERO > mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ] ) + { + return true; + } + return false; } inline void update_min_max(LLVector3& min, LLVector3& max, const LLVector3& pos) { - for (U32 i = 0; i < 3; i++) - { - if (min.mV[i] > pos.mV[i]) - { - min.mV[i] = pos.mV[i]; - } - if (max.mV[i] < pos.mV[i]) - { - max.mV[i] = pos.mV[i]; - } - } + for (U32 i = 0; i < 3; i++) + { + if (min.mV[i] > pos.mV[i]) + { + min.mV[i] = pos.mV[i]; + } + if (max.mV[i] < pos.mV[i]) + { + max.mV[i] = pos.mV[i]; + } + } } inline void update_min_max(LLVector3& min, LLVector3& max, const F32* pos) { - for (U32 i = 0; i < 3; i++) - { - if (min.mV[i] > pos[i]) - { - min.mV[i] = pos[i]; - } - if (max.mV[i] < pos[i]) - { - max.mV[i] = pos[i]; - } - } + for (U32 i = 0; i < 3; i++) + { + if (min.mV[i] > pos[i]) + { + min.mV[i] = pos[i]; + } + if (max.mV[i] < pos[i]) + { + max.mV[i] = pos[i]; + } + } } inline F32 angle_between(const LLVector3& a, const LLVector3& b) { - F32 ab = a * b; // dotproduct - if (ab == -0.0f) - { - ab = 0.0f; // get rid of negative zero - } - LLVector3 c = a % b; // crossproduct - return atan2f(sqrtf(c * c), ab); // return the angle + F32 ab = a * b; // dotproduct + if (ab == -0.0f) + { + ab = 0.0f; // get rid of negative zero + } + LLVector3 c = a % b; // crossproduct + return atan2f(sqrtf(c * c), ab); // return the angle } inline bool are_parallel(const LLVector3 &a, const LLVector3 &b, F32 epsilon) { - LLVector3 an = a; - LLVector3 bn = b; - an.normalize(); - bn.normalize(); - F32 dot = an * bn; - if ( (1.0f - fabs(dot)) < epsilon) - { - return true; - } - return false; + LLVector3 an = a; + LLVector3 bn = b; + an.normalize(); + bn.normalize(); + F32 dot = an * bn; + if ( (1.0f - fabs(dot)) < epsilon) + { + return true; + } + return false; } -inline std::ostream& operator<<(std::ostream& s, const LLVector3 &a) +inline std::ostream& operator<<(std::ostream& s, const LLVector3 &a) { - s << "{ " << a.mV[VX] << ", " << a.mV[VY] << ", " << a.mV[VZ] << " }"; - return s; + s << "{ " << a.mV[VX] << ", " << a.mV[VY] << ", " << a.mV[VZ] << " }"; + return s; } #endif diff --git a/indra/llmath/v4color.cpp b/indra/llmath/v4color.cpp index 81d18285b9..fd3548bc48 100644 --- a/indra/llmath/v4color.cpp +++ b/indra/llmath/v4color.cpp @@ -1,25 +1,25 @@ -/** +/** * @file v4color.cpp * @brief LLColor4 class implementation. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,20 +38,20 @@ ////////////////////////////////////////////////////////////////////////////// -LLColor4 LLColor4::red( 1.f, 0.f, 0.f, 1.f); -LLColor4 LLColor4::green( 0.f, 1.f, 0.f, 1.f); -LLColor4 LLColor4::blue( 0.f, 0.f, 1.f, 1.f); -LLColor4 LLColor4::black( 0.f, 0.f, 0.f, 1.f); -LLColor4 LLColor4::yellow( 1.f, 1.f, 0.f, 1.f); +LLColor4 LLColor4::red( 1.f, 0.f, 0.f, 1.f); +LLColor4 LLColor4::green( 0.f, 1.f, 0.f, 1.f); +LLColor4 LLColor4::blue( 0.f, 0.f, 1.f, 1.f); +LLColor4 LLColor4::black( 0.f, 0.f, 0.f, 1.f); +LLColor4 LLColor4::yellow( 1.f, 1.f, 0.f, 1.f); LLColor4 LLColor4::magenta( 1.0f, 0.0f, 1.0f, 1.0f); -LLColor4 LLColor4::cyan( 0.0f, 1.0f, 1.0f, 1.0f); -LLColor4 LLColor4::white( 1.f, 1.f, 1.f, 1.f); -LLColor4 LLColor4::smoke( 0.5f, 0.5f, 0.5f, 0.5f); -LLColor4 LLColor4::grey( 0.5f, 0.5f, 0.5f, 1.0f); -LLColor4 LLColor4::orange( 1.f, 0.5, 0.f, 1.f ); -LLColor4 LLColor4::purple( 0.6f, 0.2f, 0.8f, 1.0f); -LLColor4 LLColor4::pink( 1.0f, 0.5f, 0.8f, 1.0f); -LLColor4 LLColor4::transparent( 0.f, 0.f, 0.f, 0.f ); +LLColor4 LLColor4::cyan( 0.0f, 1.0f, 1.0f, 1.0f); +LLColor4 LLColor4::white( 1.f, 1.f, 1.f, 1.f); +LLColor4 LLColor4::smoke( 0.5f, 0.5f, 0.5f, 0.5f); +LLColor4 LLColor4::grey( 0.5f, 0.5f, 0.5f, 1.0f); +LLColor4 LLColor4::orange( 1.f, 0.5, 0.f, 1.f ); +LLColor4 LLColor4::purple( 0.6f, 0.2f, 0.8f, 1.0f); +LLColor4 LLColor4::pink( 1.0f, 0.5f, 0.8f, 1.0f); +LLColor4 LLColor4::transparent( 0.f, 0.f, 0.f, 0.f ); ////////////////////////////////////////////////////////////////////////////// @@ -124,615 +124,615 @@ LLColor4 LLColor4::cyan6(0.2f, 0.6f, 0.6f, 1.0f); // conversion LLColor4::operator LLColor4U() const { - return LLColor4U( - (U8)llclampb(ll_round(mV[VRED]*255.f)), - (U8)llclampb(ll_round(mV[VGREEN]*255.f)), - (U8)llclampb(ll_round(mV[VBLUE]*255.f)), - (U8)llclampb(ll_round(mV[VALPHA]*255.f))); + return LLColor4U( + (U8)llclampb(ll_round(mV[VRED]*255.f)), + (U8)llclampb(ll_round(mV[VGREEN]*255.f)), + (U8)llclampb(ll_round(mV[VBLUE]*255.f)), + (U8)llclampb(ll_round(mV[VALPHA]*255.f))); } LLColor4::LLColor4(const LLColor3 &vec, F32 a) { - mV[VX] = vec.mV[VX]; - mV[VY] = vec.mV[VY]; - mV[VZ] = vec.mV[VZ]; - mV[VW] = a; + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; + mV[VZ] = vec.mV[VZ]; + mV[VW] = a; } LLColor4::LLColor4(const LLColor4U& color4u) { - const F32 SCALE = 1.f/255.f; - mV[VX] = color4u.mV[VX] * SCALE; - mV[VY] = color4u.mV[VY] * SCALE; - mV[VZ] = color4u.mV[VZ] * SCALE; - mV[VW] = color4u.mV[VW] * SCALE; + const F32 SCALE = 1.f/255.f; + mV[VX] = color4u.mV[VX] * SCALE; + mV[VY] = color4u.mV[VY] * SCALE; + mV[VZ] = color4u.mV[VZ] * SCALE; + mV[VW] = color4u.mV[VW] * SCALE; } LLColor4::LLColor4(const LLVector4& vector4) { - mV[VX] = vector4.mV[VX]; - mV[VY] = vector4.mV[VY]; - mV[VZ] = vector4.mV[VZ]; - mV[VW] = vector4.mV[VW]; + mV[VX] = vector4.mV[VX]; + mV[VY] = vector4.mV[VY]; + mV[VZ] = vector4.mV[VZ]; + mV[VW] = vector4.mV[VW]; } -const LLColor4& LLColor4::set(const LLColor4U& color4u) +const LLColor4& LLColor4::set(const LLColor4U& color4u) { - const F32 SCALE = 1.f/255.f; - mV[VX] = color4u.mV[VX] * SCALE; - mV[VY] = color4u.mV[VY] * SCALE; - mV[VZ] = color4u.mV[VZ] * SCALE; - mV[VW] = color4u.mV[VW] * SCALE; - return (*this); + const F32 SCALE = 1.f/255.f; + mV[VX] = color4u.mV[VX] * SCALE; + mV[VY] = color4u.mV[VY] * SCALE; + mV[VZ] = color4u.mV[VZ] * SCALE; + mV[VW] = color4u.mV[VW] * SCALE; + return (*this); } -const LLColor4& LLColor4::set(const LLColor3 &vec) +const LLColor4& LLColor4::set(const LLColor3 &vec) { - mV[VX] = vec.mV[VX]; - mV[VY] = vec.mV[VY]; - mV[VZ] = vec.mV[VZ]; + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; + mV[VZ] = vec.mV[VZ]; // no change to alpha! -// mV[VW] = 1.f; +// mV[VW] = 1.f; - return (*this); + return (*this); } -const LLColor4& LLColor4::set(const LLColor3 &vec, F32 a) +const LLColor4& LLColor4::set(const LLColor3 &vec, F32 a) { - mV[VX] = vec.mV[VX]; - mV[VY] = vec.mV[VY]; - mV[VZ] = vec.mV[VZ]; - mV[VW] = a; - return (*this); + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; + mV[VZ] = vec.mV[VZ]; + mV[VW] = a; + return (*this); } // deprecated -- use set() -const LLColor4& LLColor4::setVec(const LLColor4U& color4u) +const LLColor4& LLColor4::setVec(const LLColor4U& color4u) { - const F32 SCALE = 1.f/255.f; - mV[VX] = color4u.mV[VX] * SCALE; - mV[VY] = color4u.mV[VY] * SCALE; - mV[VZ] = color4u.mV[VZ] * SCALE; - mV[VW] = color4u.mV[VW] * SCALE; - return (*this); + const F32 SCALE = 1.f/255.f; + mV[VX] = color4u.mV[VX] * SCALE; + mV[VY] = color4u.mV[VY] * SCALE; + mV[VZ] = color4u.mV[VZ] * SCALE; + mV[VW] = color4u.mV[VW] * SCALE; + return (*this); } // deprecated -- use set() -const LLColor4& LLColor4::setVec(const LLColor3 &vec) +const LLColor4& LLColor4::setVec(const LLColor3 &vec) { - mV[VX] = vec.mV[VX]; - mV[VY] = vec.mV[VY]; - mV[VZ] = vec.mV[VZ]; + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; + mV[VZ] = vec.mV[VZ]; // no change to alpha! -// mV[VW] = 1.f; +// mV[VW] = 1.f; - return (*this); + return (*this); } // deprecated -- use set() -const LLColor4& LLColor4::setVec(const LLColor3 &vec, F32 a) +const LLColor4& LLColor4::setVec(const LLColor3 &vec, F32 a) { - mV[VX] = vec.mV[VX]; - mV[VY] = vec.mV[VY]; - mV[VZ] = vec.mV[VZ]; - mV[VW] = a; - return (*this); + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; + mV[VZ] = vec.mV[VZ]; + mV[VW] = a; + return (*this); } void LLColor4::setValue(const LLSD& sd) { #if 0 - // Clamping on setValue from LLSD is inconsistent with other set behavior - F32 val; - bool out_of_range = false; - val = sd[0].asReal(); - mV[0] = llclamp(val, 0.f, 1.f); - out_of_range = mV[0] != val; - - val = sd[1].asReal(); - mV[1] = llclamp(val, 0.f, 1.f); - out_of_range |= mV[1] != val; - - val = sd[2].asReal(); - mV[2] = llclamp(val, 0.f, 1.f); - out_of_range |= mV[2] != val; - - val = sd[3].asReal(); - mV[3] = llclamp(val, 0.f, 1.f); - out_of_range |= mV[3] != val; - - if (out_of_range) - { - LL_WARNS() << "LLSD color value out of range!" << LL_ENDL; - } + // Clamping on setValue from LLSD is inconsistent with other set behavior + F32 val; + bool out_of_range = false; + val = sd[0].asReal(); + mV[0] = llclamp(val, 0.f, 1.f); + out_of_range = mV[0] != val; + + val = sd[1].asReal(); + mV[1] = llclamp(val, 0.f, 1.f); + out_of_range |= mV[1] != val; + + val = sd[2].asReal(); + mV[2] = llclamp(val, 0.f, 1.f); + out_of_range |= mV[2] != val; + + val = sd[3].asReal(); + mV[3] = llclamp(val, 0.f, 1.f); + out_of_range |= mV[3] != val; + + if (out_of_range) + { + LL_WARNS() << "LLSD color value out of range!" << LL_ENDL; + } #else - mV[0] = (F32) sd[0].asReal(); - mV[1] = (F32) sd[1].asReal(); - mV[2] = (F32) sd[2].asReal(); - mV[3] = (F32) sd[3].asReal(); + mV[0] = (F32) sd[0].asReal(); + mV[1] = (F32) sd[1].asReal(); + mV[2] = (F32) sd[2].asReal(); + mV[3] = (F32) sd[3].asReal(); #endif } const LLColor4& LLColor4::operator=(const LLColor3 &a) { - mV[VX] = a.mV[VX]; - mV[VY] = a.mV[VY]; - mV[VZ] = a.mV[VZ]; + mV[VX] = a.mV[VX]; + mV[VY] = a.mV[VY]; + mV[VZ] = a.mV[VZ]; // converting from an rgb sets a=1 (opaque) - mV[VW] = 1.f; - return (*this); + mV[VW] = 1.f; + return (*this); } -std::ostream& operator<<(std::ostream& s, const LLColor4 &a) +std::ostream& operator<<(std::ostream& s, const LLColor4 &a) { - s << "{ " << a.mV[VX] << ", " << a.mV[VY] << ", " << a.mV[VZ] << ", " << a.mV[VW] << " }"; - return s; + s << "{ " << a.mV[VX] << ", " << a.mV[VY] << ", " << a.mV[VZ] << ", " << a.mV[VW] << " }"; + return s; } bool operator==(const LLColor4 &a, const LLColor3 &b) { - return ( (a.mV[VX] == b.mV[VX]) - &&(a.mV[VY] == b.mV[VY]) - &&(a.mV[VZ] == b.mV[VZ])); + return ( (a.mV[VX] == b.mV[VX]) + &&(a.mV[VY] == b.mV[VY]) + &&(a.mV[VZ] == b.mV[VZ])); } bool operator!=(const LLColor4 &a, const LLColor3 &b) { - return ( (a.mV[VX] != b.mV[VX]) - ||(a.mV[VY] != b.mV[VY]) - ||(a.mV[VZ] != b.mV[VZ])); + return ( (a.mV[VX] != b.mV[VX]) + ||(a.mV[VY] != b.mV[VY]) + ||(a.mV[VZ] != b.mV[VZ])); } -LLColor3 vec4to3(const LLColor4 &vec) +LLColor3 vec4to3(const LLColor4 &vec) { - LLColor3 temp(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); - return temp; + LLColor3 temp(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); + return temp; } -LLColor4 vec3to4(const LLColor3 &vec) +LLColor4 vec3to4(const LLColor3 &vec) { - LLColor3 temp(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); - return temp; + LLColor3 temp(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); + return temp; } static F32 hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn ) { - if ( valHUeIn < 0.0f ) valHUeIn += 1.0f; - if ( valHUeIn > 1.0f ) valHUeIn -= 1.0f; - if ( ( 6.0f * valHUeIn ) < 1.0f ) return ( val1In + ( val2In - val1In ) * 6.0f * valHUeIn ); - if ( ( 2.0f * valHUeIn ) < 1.0f ) return ( val2In ); - if ( ( 3.0f * valHUeIn ) < 2.0f ) return ( val1In + ( val2In - val1In ) * ( ( 2.0f / 3.0f ) - valHUeIn ) * 6.0f ); - return ( val1In ); + if ( valHUeIn < 0.0f ) valHUeIn += 1.0f; + if ( valHUeIn > 1.0f ) valHUeIn -= 1.0f; + if ( ( 6.0f * valHUeIn ) < 1.0f ) return ( val1In + ( val2In - val1In ) * 6.0f * valHUeIn ); + if ( ( 2.0f * valHUeIn ) < 1.0f ) return ( val2In ); + if ( ( 3.0f * valHUeIn ) < 2.0f ) return ( val1In + ( val2In - val1In ) * ( ( 2.0f / 3.0f ) - valHUeIn ) * 6.0f ); + return ( val1In ); } void LLColor4::setHSL ( F32 hValIn, F32 sValIn, F32 lValIn) { - if ( sValIn < 0.00001f ) - { - mV[VRED] = lValIn; - mV[VGREEN] = lValIn; - mV[VBLUE] = lValIn; - } - else - { - F32 interVal1; - F32 interVal2; - - if ( lValIn < 0.5f ) - interVal2 = lValIn * ( 1.0f + sValIn ); - else - interVal2 = ( lValIn + sValIn ) - ( sValIn * lValIn ); - - interVal1 = 2.0f * lValIn - interVal2; - - mV[VRED] = hueToRgb ( interVal1, interVal2, hValIn + ( 1.f / 3.f ) ); - mV[VGREEN] = hueToRgb ( interVal1, interVal2, hValIn ); - mV[VBLUE] = hueToRgb ( interVal1, interVal2, hValIn - ( 1.f / 3.f ) ); - } + if ( sValIn < 0.00001f ) + { + mV[VRED] = lValIn; + mV[VGREEN] = lValIn; + mV[VBLUE] = lValIn; + } + else + { + F32 interVal1; + F32 interVal2; + + if ( lValIn < 0.5f ) + interVal2 = lValIn * ( 1.0f + sValIn ); + else + interVal2 = ( lValIn + sValIn ) - ( sValIn * lValIn ); + + interVal1 = 2.0f * lValIn - interVal2; + + mV[VRED] = hueToRgb ( interVal1, interVal2, hValIn + ( 1.f / 3.f ) ); + mV[VGREEN] = hueToRgb ( interVal1, interVal2, hValIn ); + mV[VBLUE] = hueToRgb ( interVal1, interVal2, hValIn - ( 1.f / 3.f ) ); + } } void LLColor4::calcHSL(F32* hue, F32* saturation, F32* luminance) const { - F32 var_R = mV[VRED]; - F32 var_G = mV[VGREEN]; - F32 var_B = mV[VBLUE]; - - F32 var_Min = ( var_R < ( var_G < var_B ? var_G : var_B ) ? var_R : ( var_G < var_B ? var_G : var_B ) ); - F32 var_Max = ( var_R > ( var_G > var_B ? var_G : var_B ) ? var_R : ( var_G > var_B ? var_G : var_B ) ); - - F32 del_Max = var_Max - var_Min; - - F32 L = ( var_Max + var_Min ) / 2.0f; - F32 H = 0.0f; - F32 S = 0.0f; - - if ( del_Max == 0.0f ) - { - H = 0.0f; - S = 0.0f; - } - else - { - if ( L < 0.5 ) - S = del_Max / ( var_Max + var_Min ); - else - S = del_Max / ( 2.0f - var_Max - var_Min ); - - F32 del_R = ( ( ( var_Max - var_R ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max; - F32 del_G = ( ( ( var_Max - var_G ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max; - F32 del_B = ( ( ( var_Max - var_B ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max; - - if ( var_R >= var_Max ) - H = del_B - del_G; - else - if ( var_G >= var_Max ) - H = ( 1.0f / 3.0f ) + del_R - del_B; - else - if ( var_B >= var_Max ) - H = ( 2.0f / 3.0f ) + del_G - del_R; - - if ( H < 0.0f ) H += 1.0f; - if ( H > 1.0f ) H -= 1.0f; - } - - if (hue) *hue = H; - if (saturation) *saturation = S; - if (luminance) *luminance = L; + F32 var_R = mV[VRED]; + F32 var_G = mV[VGREEN]; + F32 var_B = mV[VBLUE]; + + F32 var_Min = ( var_R < ( var_G < var_B ? var_G : var_B ) ? var_R : ( var_G < var_B ? var_G : var_B ) ); + F32 var_Max = ( var_R > ( var_G > var_B ? var_G : var_B ) ? var_R : ( var_G > var_B ? var_G : var_B ) ); + + F32 del_Max = var_Max - var_Min; + + F32 L = ( var_Max + var_Min ) / 2.0f; + F32 H = 0.0f; + F32 S = 0.0f; + + if ( del_Max == 0.0f ) + { + H = 0.0f; + S = 0.0f; + } + else + { + if ( L < 0.5 ) + S = del_Max / ( var_Max + var_Min ); + else + S = del_Max / ( 2.0f - var_Max - var_Min ); + + F32 del_R = ( ( ( var_Max - var_R ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max; + F32 del_G = ( ( ( var_Max - var_G ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max; + F32 del_B = ( ( ( var_Max - var_B ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max; + + if ( var_R >= var_Max ) + H = del_B - del_G; + else + if ( var_G >= var_Max ) + H = ( 1.0f / 3.0f ) + del_R - del_B; + else + if ( var_B >= var_Max ) + H = ( 2.0f / 3.0f ) + del_G - del_R; + + if ( H < 0.0f ) H += 1.0f; + if ( H > 1.0f ) H -= 1.0f; + } + + if (hue) *hue = H; + if (saturation) *saturation = S; + if (luminance) *luminance = L; } // static bool LLColor4::parseColor(const std::string& buf, LLColor4* color) { - if( buf.empty() || color == nullptr) - { - return false; - } - - boost_tokenizer tokens(buf, boost::char_separator<char>(", ")); - boost_tokenizer::iterator token_iter = tokens.begin(); - if (token_iter == tokens.end()) - { - return false; - } - - // Grab the first token into a string, since we don't know - // if this is a float or a color name. - std::string color_name( (*token_iter) ); - ++token_iter; - - if (token_iter != tokens.end()) - { - // There are more tokens to read. This must be a vector. - LLColor4 v; - LLStringUtil::convertToF32( color_name, v.mV[VX] ); - LLStringUtil::convertToF32( *token_iter, v.mV[VY] ); - v.mV[VZ] = 0.0f; - v.mV[VW] = 1.0f; - - ++token_iter; - if (token_iter == tokens.end()) - { - // This is a malformed vector. - LL_WARNS() << "LLColor4::parseColor() malformed color " << buf << LL_ENDL; - } - else - { - // There is a z-component. - LLStringUtil::convertToF32( *token_iter, v.mV[VZ] ); - - ++token_iter; - if (token_iter != tokens.end()) - { - // There is an alpha component. - LLStringUtil::convertToF32( *token_iter, v.mV[VW] ); - } - } - - // Make sure all values are between 0 and 1. - if (v.mV[VX] > 1.f || v.mV[VY] > 1.f || v.mV[VZ] > 1.f || v.mV[VW] > 1.f) - { - v = v * (1.f / 255.f); - } - color->set( v ); - } - else // Single value. Read as a named color. - { - // We have a color name - if ( "red" == color_name ) - { - color->set(LLColor4::red); - } - else if ( "red1" == color_name ) - { - color->set(LLColor4::red1); - } - else if ( "red2" == color_name ) - { - color->set(LLColor4::red2); - } - else if ( "red3" == color_name ) - { - color->set(LLColor4::red3); - } - else if ( "red4" == color_name ) - { - color->set(LLColor4::red4); - } - else if ( "red5" == color_name ) - { - color->set(LLColor4::red5); - } - else if( "green" == color_name ) - { - color->set(LLColor4::green); - } - else if( "green1" == color_name ) - { - color->set(LLColor4::green1); - } - else if( "green2" == color_name ) - { - color->set(LLColor4::green2); - } - else if( "green3" == color_name ) - { - color->set(LLColor4::green3); - } - else if( "green4" == color_name ) - { - color->set(LLColor4::green4); - } - else if( "green5" == color_name ) - { - color->set(LLColor4::green5); - } - else if( "green6" == color_name ) - { - color->set(LLColor4::green6); - } - else if( "blue" == color_name ) - { - color->set(LLColor4::blue); - } - else if( "blue1" == color_name ) - { - color->set(LLColor4::blue1); - } - else if( "blue2" == color_name ) - { - color->set(LLColor4::blue2); - } - else if( "blue3" == color_name ) - { - color->set(LLColor4::blue3); - } - else if( "blue4" == color_name ) - { - color->set(LLColor4::blue4); - } - else if( "blue5" == color_name ) - { - color->set(LLColor4::blue5); - } - else if( "blue6" == color_name ) - { - color->set(LLColor4::blue6); - } - else if( "black" == color_name ) - { - color->set(LLColor4::black); - } - else if( "white" == color_name ) - { - color->set(LLColor4::white); - } - else if( "yellow" == color_name ) - { - color->set(LLColor4::yellow); - } - else if( "yellow1" == color_name ) - { - color->set(LLColor4::yellow1); - } - else if( "yellow2" == color_name ) - { - color->set(LLColor4::yellow2); - } - else if( "yellow3" == color_name ) - { - color->set(LLColor4::yellow3); - } - else if( "yellow4" == color_name ) - { - color->set(LLColor4::yellow4); - } - else if( "yellow5" == color_name ) - { - color->set(LLColor4::yellow5); - } - else if( "yellow6" == color_name ) - { - color->set(LLColor4::yellow6); - } - else if( "magenta" == color_name ) - { - color->set(LLColor4::magenta); - } - else if( "magenta1" == color_name ) - { - color->set(LLColor4::magenta1); - } - else if( "magenta2" == color_name ) - { - color->set(LLColor4::magenta2); - } - else if( "magenta3" == color_name ) - { - color->set(LLColor4::magenta3); - } - else if( "magenta4" == color_name ) - { - color->set(LLColor4::magenta4); - } - else if( "purple" == color_name ) - { - color->set(LLColor4::purple); - } - else if( "purple1" == color_name ) - { - color->set(LLColor4::purple1); - } - else if( "purple2" == color_name ) - { - color->set(LLColor4::purple2); - } - else if( "purple3" == color_name ) - { - color->set(LLColor4::purple3); - } - else if( "purple4" == color_name ) - { - color->set(LLColor4::purple4); - } - else if( "purple5" == color_name ) - { - color->set(LLColor4::purple5); - } - else if( "purple6" == color_name ) - { - color->set(LLColor4::purple6); - } - else if( "pink" == color_name ) - { - color->set(LLColor4::pink); - } - else if( "pink1" == color_name ) - { - color->set(LLColor4::pink1); - } - else if( "pink2" == color_name ) - { - color->set(LLColor4::pink2); - } - else if( "cyan" == color_name ) - { - color->set(LLColor4::cyan); - } - else if( "cyan1" == color_name ) - { - color->set(LLColor4::cyan1); - } - else if( "cyan2" == color_name ) - { - color->set(LLColor4::cyan2); - } - else if( "cyan3" == color_name ) - { - color->set(LLColor4::cyan3); - } - else if( "cyan4" == color_name ) - { - color->set(LLColor4::cyan4); - } - else if( "cyan5" == color_name ) - { - color->set(LLColor4::cyan5); - } - else if( "cyan6" == color_name ) - { - color->set(LLColor4::cyan6); - } - else if( "smoke" == color_name ) - { - color->set(LLColor4::smoke); - } - else if( "grey" == color_name ) - { - color->set(LLColor4::grey); - } - else if( "grey1" == color_name ) - { - color->set(LLColor4::grey1); - } - else if( "grey2" == color_name ) - { - color->set(LLColor4::grey2); - } - else if( "grey3" == color_name ) - { - color->set(LLColor4::grey3); - } - else if( "grey4" == color_name ) - { - color->set(LLColor4::grey4); - } - else if( "orange" == color_name ) - { - color->set(LLColor4::orange); - } - else if( "orange1" == color_name ) - { - color->set(LLColor4::orange1); - } - else if( "orange2" == color_name ) - { - color->set(LLColor4::orange2); - } - else if( "orange3" == color_name ) - { - color->set(LLColor4::orange3); - } - else if( "orange4" == color_name ) - { - color->set(LLColor4::orange4); - } - else if( "orange5" == color_name ) - { - color->set(LLColor4::orange5); - } - else if( "orange6" == color_name ) - { - color->set(LLColor4::orange6); - } - else if ( "clear" == color_name ) - { - color->set(0.f, 0.f, 0.f, 0.f); - } - else - { - LL_WARNS() << "invalid color " << color_name << LL_ENDL; - } - } - - return true; + if( buf.empty() || color == nullptr) + { + return false; + } + + boost_tokenizer tokens(buf, boost::char_separator<char>(", ")); + boost_tokenizer::iterator token_iter = tokens.begin(); + if (token_iter == tokens.end()) + { + return false; + } + + // Grab the first token into a string, since we don't know + // if this is a float or a color name. + std::string color_name( (*token_iter) ); + ++token_iter; + + if (token_iter != tokens.end()) + { + // There are more tokens to read. This must be a vector. + LLColor4 v; + LLStringUtil::convertToF32( color_name, v.mV[VX] ); + LLStringUtil::convertToF32( *token_iter, v.mV[VY] ); + v.mV[VZ] = 0.0f; + v.mV[VW] = 1.0f; + + ++token_iter; + if (token_iter == tokens.end()) + { + // This is a malformed vector. + LL_WARNS() << "LLColor4::parseColor() malformed color " << buf << LL_ENDL; + } + else + { + // There is a z-component. + LLStringUtil::convertToF32( *token_iter, v.mV[VZ] ); + + ++token_iter; + if (token_iter != tokens.end()) + { + // There is an alpha component. + LLStringUtil::convertToF32( *token_iter, v.mV[VW] ); + } + } + + // Make sure all values are between 0 and 1. + if (v.mV[VX] > 1.f || v.mV[VY] > 1.f || v.mV[VZ] > 1.f || v.mV[VW] > 1.f) + { + v = v * (1.f / 255.f); + } + color->set( v ); + } + else // Single value. Read as a named color. + { + // We have a color name + if ( "red" == color_name ) + { + color->set(LLColor4::red); + } + else if ( "red1" == color_name ) + { + color->set(LLColor4::red1); + } + else if ( "red2" == color_name ) + { + color->set(LLColor4::red2); + } + else if ( "red3" == color_name ) + { + color->set(LLColor4::red3); + } + else if ( "red4" == color_name ) + { + color->set(LLColor4::red4); + } + else if ( "red5" == color_name ) + { + color->set(LLColor4::red5); + } + else if( "green" == color_name ) + { + color->set(LLColor4::green); + } + else if( "green1" == color_name ) + { + color->set(LLColor4::green1); + } + else if( "green2" == color_name ) + { + color->set(LLColor4::green2); + } + else if( "green3" == color_name ) + { + color->set(LLColor4::green3); + } + else if( "green4" == color_name ) + { + color->set(LLColor4::green4); + } + else if( "green5" == color_name ) + { + color->set(LLColor4::green5); + } + else if( "green6" == color_name ) + { + color->set(LLColor4::green6); + } + else if( "blue" == color_name ) + { + color->set(LLColor4::blue); + } + else if( "blue1" == color_name ) + { + color->set(LLColor4::blue1); + } + else if( "blue2" == color_name ) + { + color->set(LLColor4::blue2); + } + else if( "blue3" == color_name ) + { + color->set(LLColor4::blue3); + } + else if( "blue4" == color_name ) + { + color->set(LLColor4::blue4); + } + else if( "blue5" == color_name ) + { + color->set(LLColor4::blue5); + } + else if( "blue6" == color_name ) + { + color->set(LLColor4::blue6); + } + else if( "black" == color_name ) + { + color->set(LLColor4::black); + } + else if( "white" == color_name ) + { + color->set(LLColor4::white); + } + else if( "yellow" == color_name ) + { + color->set(LLColor4::yellow); + } + else if( "yellow1" == color_name ) + { + color->set(LLColor4::yellow1); + } + else if( "yellow2" == color_name ) + { + color->set(LLColor4::yellow2); + } + else if( "yellow3" == color_name ) + { + color->set(LLColor4::yellow3); + } + else if( "yellow4" == color_name ) + { + color->set(LLColor4::yellow4); + } + else if( "yellow5" == color_name ) + { + color->set(LLColor4::yellow5); + } + else if( "yellow6" == color_name ) + { + color->set(LLColor4::yellow6); + } + else if( "magenta" == color_name ) + { + color->set(LLColor4::magenta); + } + else if( "magenta1" == color_name ) + { + color->set(LLColor4::magenta1); + } + else if( "magenta2" == color_name ) + { + color->set(LLColor4::magenta2); + } + else if( "magenta3" == color_name ) + { + color->set(LLColor4::magenta3); + } + else if( "magenta4" == color_name ) + { + color->set(LLColor4::magenta4); + } + else if( "purple" == color_name ) + { + color->set(LLColor4::purple); + } + else if( "purple1" == color_name ) + { + color->set(LLColor4::purple1); + } + else if( "purple2" == color_name ) + { + color->set(LLColor4::purple2); + } + else if( "purple3" == color_name ) + { + color->set(LLColor4::purple3); + } + else if( "purple4" == color_name ) + { + color->set(LLColor4::purple4); + } + else if( "purple5" == color_name ) + { + color->set(LLColor4::purple5); + } + else if( "purple6" == color_name ) + { + color->set(LLColor4::purple6); + } + else if( "pink" == color_name ) + { + color->set(LLColor4::pink); + } + else if( "pink1" == color_name ) + { + color->set(LLColor4::pink1); + } + else if( "pink2" == color_name ) + { + color->set(LLColor4::pink2); + } + else if( "cyan" == color_name ) + { + color->set(LLColor4::cyan); + } + else if( "cyan1" == color_name ) + { + color->set(LLColor4::cyan1); + } + else if( "cyan2" == color_name ) + { + color->set(LLColor4::cyan2); + } + else if( "cyan3" == color_name ) + { + color->set(LLColor4::cyan3); + } + else if( "cyan4" == color_name ) + { + color->set(LLColor4::cyan4); + } + else if( "cyan5" == color_name ) + { + color->set(LLColor4::cyan5); + } + else if( "cyan6" == color_name ) + { + color->set(LLColor4::cyan6); + } + else if( "smoke" == color_name ) + { + color->set(LLColor4::smoke); + } + else if( "grey" == color_name ) + { + color->set(LLColor4::grey); + } + else if( "grey1" == color_name ) + { + color->set(LLColor4::grey1); + } + else if( "grey2" == color_name ) + { + color->set(LLColor4::grey2); + } + else if( "grey3" == color_name ) + { + color->set(LLColor4::grey3); + } + else if( "grey4" == color_name ) + { + color->set(LLColor4::grey4); + } + else if( "orange" == color_name ) + { + color->set(LLColor4::orange); + } + else if( "orange1" == color_name ) + { + color->set(LLColor4::orange1); + } + else if( "orange2" == color_name ) + { + color->set(LLColor4::orange2); + } + else if( "orange3" == color_name ) + { + color->set(LLColor4::orange3); + } + else if( "orange4" == color_name ) + { + color->set(LLColor4::orange4); + } + else if( "orange5" == color_name ) + { + color->set(LLColor4::orange5); + } + else if( "orange6" == color_name ) + { + color->set(LLColor4::orange6); + } + else if ( "clear" == color_name ) + { + color->set(0.f, 0.f, 0.f, 0.f); + } + else + { + LL_WARNS() << "invalid color " << color_name << LL_ENDL; + } + } + + return true; } // static bool LLColor4::parseColor4(const std::string& buf, LLColor4* value) { - if( buf.empty() || value == nullptr) - { - return false; - } - - LLColor4 v; - S32 count = sscanf( buf.c_str(), "%f, %f, %f, %f", v.mV + 0, v.mV + 1, v.mV + 2, v.mV + 3 ); - if (1 == count ) - { - // try this format - count = sscanf( buf.c_str(), "%f %f %f %f", v.mV + 0, v.mV + 1, v.mV + 2, v.mV + 3 ); - } - if( 4 == count ) - { - value->setVec( v ); - return true; - } - - return false; + if( buf.empty() || value == nullptr) + { + return false; + } + + LLColor4 v; + S32 count = sscanf( buf.c_str(), "%f, %f, %f, %f", v.mV + 0, v.mV + 1, v.mV + 2, v.mV + 3 ); + if (1 == count ) + { + // try this format + count = sscanf( buf.c_str(), "%f %f %f %f", v.mV + 0, v.mV + 1, v.mV + 2, v.mV + 3 ); + } + if( 4 == count ) + { + value->setVec( v ); + return true; + } + + return false; } // EOF diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h index 498d4f7734..1e20ab977a 100644 --- a/indra/llmath/v4color.h +++ b/indra/llmath/v4color.h @@ -1,25 +1,25 @@ -/** +/** * @file v4color.h * @brief LLColor4 class header file. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -44,56 +44,56 @@ static const U32 MAX_LENGTH_OF_COLOR_NAME = 15; //Give plenty of room for additi class LLColor4 { - public: - F32 mV[LENGTHOFCOLOR4]; - LLColor4(); // Initializes LLColor4 to (0, 0, 0, 1) - LLColor4(F32 r, F32 g, F32 b); // Initializes LLColor4 to (r, g, b, 1) - LLColor4(F32 r, F32 g, F32 b, F32 a); // Initializes LLColor4 to (r. g, b, a) - LLColor4(const LLColor3 &vec, F32 a = 1.f); // Initializes LLColor4 to (vec, a) - explicit LLColor4(const LLSD& sd); - explicit LLColor4(const F32 *vec); // Initializes LLColor4 to (vec[0]. vec[1], vec[2], 1) - explicit LLColor4(U32 clr); // Initializes LLColor4 to (r=clr>>24, etc)) - explicit LLColor4(const LLColor4U& color4u); // "explicit" to avoid automatic conversion - explicit LLColor4(const LLVector4& vector4); // "explicit" to avoid automatic conversion - - LLSD getValue() const - { - LLSD ret; - ret[0] = mV[0]; - ret[1] = mV[1]; - ret[2] = mV[2]; - ret[3] = mV[3]; - return ret; - } - - void setValue(const LLSD& sd); - - void setHSL(F32 hue, F32 saturation, F32 luminance); - void calcHSL(F32* hue, F32* saturation, F32* luminance) const; - - const LLColor4& setToBlack(); // zero LLColor4 to (0, 0, 0, 1) - const LLColor4& setToWhite(); // zero LLColor4 to (0, 0, 0, 1) - - const LLColor4& setVec(F32 r, F32 g, F32 b, F32 a); // deprecated -- use set() - const LLColor4& setVec(F32 r, F32 g, F32 b); // deprecated -- use set() - const LLColor4& setVec(const LLColor4 &vec); // deprecated -- use set() - const LLColor4& setVec(const LLColor3 &vec); // deprecated -- use set() - const LLColor4& setVec(const LLColor3 &vec, F32 a); // deprecated -- use set() - const LLColor4& setVec(const F32 *vec); // deprecated -- use set() - const LLColor4& setVec(const LLColor4U& color4u); // deprecated -- use set() - - const LLColor4& set(F32 r, F32 g, F32 b, F32 a); // Sets LLColor4 to (r, g, b, a) - const LLColor4& set(F32 r, F32 g, F32 b); // Sets LLColor4 to (r, g, b) (no change in a) - const LLColor4& set(const LLColor4 &vec); // Sets LLColor4 to vec - const LLColor4& set(const LLColor3 &vec); // Sets LLColor4 to LLColor3 vec (no change in alpha) - const LLColor4& set(const LLColor3 &vec, F32 a); // Sets LLColor4 to LLColor3 vec, with alpha specified - const LLColor4& set(const F32 *vec); // Sets LLColor4 to vec - const LLColor4& set(const F64 *vec); // Sets LLColor4 to (double)vec - const LLColor4& set(const LLColor4U& color4u); // Sets LLColor4 to color4u, rescaled. + public: + F32 mV[LENGTHOFCOLOR4]; + LLColor4(); // Initializes LLColor4 to (0, 0, 0, 1) + LLColor4(F32 r, F32 g, F32 b); // Initializes LLColor4 to (r, g, b, 1) + LLColor4(F32 r, F32 g, F32 b, F32 a); // Initializes LLColor4 to (r. g, b, a) + LLColor4(const LLColor3 &vec, F32 a = 1.f); // Initializes LLColor4 to (vec, a) + explicit LLColor4(const LLSD& sd); + explicit LLColor4(const F32 *vec); // Initializes LLColor4 to (vec[0]. vec[1], vec[2], 1) + explicit LLColor4(U32 clr); // Initializes LLColor4 to (r=clr>>24, etc)) + explicit LLColor4(const LLColor4U& color4u); // "explicit" to avoid automatic conversion + explicit LLColor4(const LLVector4& vector4); // "explicit" to avoid automatic conversion + + LLSD getValue() const + { + LLSD ret; + ret[0] = mV[0]; + ret[1] = mV[1]; + ret[2] = mV[2]; + ret[3] = mV[3]; + return ret; + } + + void setValue(const LLSD& sd); + + void setHSL(F32 hue, F32 saturation, F32 luminance); + void calcHSL(F32* hue, F32* saturation, F32* luminance) const; + + const LLColor4& setToBlack(); // zero LLColor4 to (0, 0, 0, 1) + const LLColor4& setToWhite(); // zero LLColor4 to (0, 0, 0, 1) + + const LLColor4& setVec(F32 r, F32 g, F32 b, F32 a); // deprecated -- use set() + const LLColor4& setVec(F32 r, F32 g, F32 b); // deprecated -- use set() + const LLColor4& setVec(const LLColor4 &vec); // deprecated -- use set() + const LLColor4& setVec(const LLColor3 &vec); // deprecated -- use set() + const LLColor4& setVec(const LLColor3 &vec, F32 a); // deprecated -- use set() + const LLColor4& setVec(const F32 *vec); // deprecated -- use set() + const LLColor4& setVec(const LLColor4U& color4u); // deprecated -- use set() + + const LLColor4& set(F32 r, F32 g, F32 b, F32 a); // Sets LLColor4 to (r, g, b, a) + const LLColor4& set(F32 r, F32 g, F32 b); // Sets LLColor4 to (r, g, b) (no change in a) + const LLColor4& set(const LLColor4 &vec); // Sets LLColor4 to vec + const LLColor4& set(const LLColor3 &vec); // Sets LLColor4 to LLColor3 vec (no change in alpha) + const LLColor4& set(const LLColor3 &vec, F32 a); // Sets LLColor4 to LLColor3 vec, with alpha specified + const LLColor4& set(const F32 *vec); // Sets LLColor4 to vec + const LLColor4& set(const F64 *vec); // Sets LLColor4 to (double)vec + const LLColor4& set(const LLColor4U& color4u); // Sets LLColor4 to color4u, rescaled. // set from a vector of unknown type and size // may leave some data unmodified - template<typename T> + template<typename T> const LLColor4& set(const std::vector<T>& v); // write to a vector of unknown type and size @@ -101,250 +101,250 @@ class LLColor4 template<typename T> void write(std::vector<T>& v) const; - const LLColor4& setAlpha(F32 a); - - F32 magVec() const; // deprecated -- use length() - F32 magVecSquared() const; // deprecated -- use lengthSquared() - F32 normVec(); // deprecated -- use normalize() - - F32 length() const; // Returns magnitude of LLColor4 - F32 lengthSquared() const; // Returns magnitude squared of LLColor4 - F32 normalize(); // deprecated -- use normalize() - - bool isOpaque() { return mV[VALPHA] == 1.f; } - - F32 operator[](int idx) const { return mV[idx]; } - F32 &operator[](int idx) { return mV[idx]; } - - const LLColor4& operator=(const LLColor3 &a); // Assigns vec3 to vec4 and returns vec4 - - bool operator<(const LLColor4& rhs) const; - friend std::ostream& operator<<(std::ostream& s, const LLColor4 &a); // Print a - friend LLColor4 operator+(const LLColor4 &a, const LLColor4 &b); // Return vector a + b - friend LLColor4 operator-(const LLColor4 &a, const LLColor4 &b); // Return vector a minus b - friend LLColor4 operator*(const LLColor4 &a, const LLColor4 &b); // Return component wise a * b - friend LLColor4 operator*(const LLColor4 &a, F32 k); // Return rgb times scaler k (no alpha change) + const LLColor4& setAlpha(F32 a); + + F32 magVec() const; // deprecated -- use length() + F32 magVecSquared() const; // deprecated -- use lengthSquared() + F32 normVec(); // deprecated -- use normalize() + + F32 length() const; // Returns magnitude of LLColor4 + F32 lengthSquared() const; // Returns magnitude squared of LLColor4 + F32 normalize(); // deprecated -- use normalize() + + bool isOpaque() { return mV[VALPHA] == 1.f; } + + F32 operator[](int idx) const { return mV[idx]; } + F32 &operator[](int idx) { return mV[idx]; } + + const LLColor4& operator=(const LLColor3 &a); // Assigns vec3 to vec4 and returns vec4 + + bool operator<(const LLColor4& rhs) const; + friend std::ostream& operator<<(std::ostream& s, const LLColor4 &a); // Print a + friend LLColor4 operator+(const LLColor4 &a, const LLColor4 &b); // Return vector a + b + friend LLColor4 operator-(const LLColor4 &a, const LLColor4 &b); // Return vector a minus b + friend LLColor4 operator*(const LLColor4 &a, const LLColor4 &b); // Return component wise a * b + friend LLColor4 operator*(const LLColor4 &a, F32 k); // Return rgb times scaler k (no alpha change) friend LLColor4 operator/(const LLColor4 &a, F32 k); // Return rgb divided by scalar k (no alpha change) - friend LLColor4 operator*(F32 k, const LLColor4 &a); // Return rgb times scaler k (no alpha change) - friend LLColor4 operator%(const LLColor4 &a, F32 k); // Return alpha times scaler k (no rgb change) - friend LLColor4 operator%(F32 k, const LLColor4 &a); // Return alpha times scaler k (no rgb change) - - friend bool operator==(const LLColor4 &a, const LLColor4 &b); // Return a == b - friend bool operator!=(const LLColor4 &a, const LLColor4 &b); // Return a != b - - friend bool operator==(const LLColor4 &a, const LLColor3 &b); // Return a == b - friend bool operator!=(const LLColor4 &a, const LLColor3 &b); // Return a != b - - friend const LLColor4& operator+=(LLColor4 &a, const LLColor4 &b); // Return vector a + b - friend const LLColor4& operator-=(LLColor4 &a, const LLColor4 &b); // Return vector a minus b - friend const LLColor4& operator*=(LLColor4 &a, F32 k); // Return rgb times scaler k (no alpha change) - friend const LLColor4& operator%=(LLColor4 &a, F32 k); // Return alpha times scaler k (no rgb change) - - friend const LLColor4& operator*=(LLColor4 &a, const LLColor4 &b); // Doesn't multiply alpha! (for lighting) - - // conversion - operator LLColor4U() const; - - // Basic color values. - static LLColor4 red; - static LLColor4 green; - static LLColor4 blue; - static LLColor4 black; - static LLColor4 white; - static LLColor4 yellow; - static LLColor4 magenta; - static LLColor4 cyan; - static LLColor4 smoke; - static LLColor4 grey; - static LLColor4 orange; - static LLColor4 purple; - static LLColor4 pink; - static LLColor4 transparent; - - // Extra color values. - static LLColor4 grey1; - static LLColor4 grey2; - static LLColor4 grey3; - static LLColor4 grey4; - - static LLColor4 red1; - static LLColor4 red2; - static LLColor4 red3; - static LLColor4 red4; - static LLColor4 red5; - - static LLColor4 green1; - static LLColor4 green2; - static LLColor4 green3; - static LLColor4 green4; - static LLColor4 green5; - static LLColor4 green6; - - static LLColor4 blue1; - static LLColor4 blue2; - static LLColor4 blue3; - static LLColor4 blue4; - static LLColor4 blue5; - static LLColor4 blue6; - - static LLColor4 yellow1; - static LLColor4 yellow2; - static LLColor4 yellow3; - static LLColor4 yellow4; - static LLColor4 yellow5; - static LLColor4 yellow6; - static LLColor4 yellow7; - static LLColor4 yellow8; - static LLColor4 yellow9; - - static LLColor4 orange1; - static LLColor4 orange2; - static LLColor4 orange3; - static LLColor4 orange4; - static LLColor4 orange5; - static LLColor4 orange6; - - static LLColor4 magenta1; - static LLColor4 magenta2; - static LLColor4 magenta3; - static LLColor4 magenta4; - - static LLColor4 purple1; - static LLColor4 purple2; - static LLColor4 purple3; - static LLColor4 purple4; - static LLColor4 purple5; - static LLColor4 purple6; - - static LLColor4 pink1; - static LLColor4 pink2; - - static LLColor4 cyan1; - static LLColor4 cyan2; - static LLColor4 cyan3; - static LLColor4 cyan4; - static LLColor4 cyan5; - static LLColor4 cyan6; - - static bool parseColor(const std::string& buf, LLColor4* color); - static bool parseColor4(const std::string& buf, LLColor4* color); - - inline void clamp(); + friend LLColor4 operator*(F32 k, const LLColor4 &a); // Return rgb times scaler k (no alpha change) + friend LLColor4 operator%(const LLColor4 &a, F32 k); // Return alpha times scaler k (no rgb change) + friend LLColor4 operator%(F32 k, const LLColor4 &a); // Return alpha times scaler k (no rgb change) + + friend bool operator==(const LLColor4 &a, const LLColor4 &b); // Return a == b + friend bool operator!=(const LLColor4 &a, const LLColor4 &b); // Return a != b + + friend bool operator==(const LLColor4 &a, const LLColor3 &b); // Return a == b + friend bool operator!=(const LLColor4 &a, const LLColor3 &b); // Return a != b + + friend const LLColor4& operator+=(LLColor4 &a, const LLColor4 &b); // Return vector a + b + friend const LLColor4& operator-=(LLColor4 &a, const LLColor4 &b); // Return vector a minus b + friend const LLColor4& operator*=(LLColor4 &a, F32 k); // Return rgb times scaler k (no alpha change) + friend const LLColor4& operator%=(LLColor4 &a, F32 k); // Return alpha times scaler k (no rgb change) + + friend const LLColor4& operator*=(LLColor4 &a, const LLColor4 &b); // Doesn't multiply alpha! (for lighting) + + // conversion + operator LLColor4U() const; + + // Basic color values. + static LLColor4 red; + static LLColor4 green; + static LLColor4 blue; + static LLColor4 black; + static LLColor4 white; + static LLColor4 yellow; + static LLColor4 magenta; + static LLColor4 cyan; + static LLColor4 smoke; + static LLColor4 grey; + static LLColor4 orange; + static LLColor4 purple; + static LLColor4 pink; + static LLColor4 transparent; + + // Extra color values. + static LLColor4 grey1; + static LLColor4 grey2; + static LLColor4 grey3; + static LLColor4 grey4; + + static LLColor4 red1; + static LLColor4 red2; + static LLColor4 red3; + static LLColor4 red4; + static LLColor4 red5; + + static LLColor4 green1; + static LLColor4 green2; + static LLColor4 green3; + static LLColor4 green4; + static LLColor4 green5; + static LLColor4 green6; + + static LLColor4 blue1; + static LLColor4 blue2; + static LLColor4 blue3; + static LLColor4 blue4; + static LLColor4 blue5; + static LLColor4 blue6; + + static LLColor4 yellow1; + static LLColor4 yellow2; + static LLColor4 yellow3; + static LLColor4 yellow4; + static LLColor4 yellow5; + static LLColor4 yellow6; + static LLColor4 yellow7; + static LLColor4 yellow8; + static LLColor4 yellow9; + + static LLColor4 orange1; + static LLColor4 orange2; + static LLColor4 orange3; + static LLColor4 orange4; + static LLColor4 orange5; + static LLColor4 orange6; + + static LLColor4 magenta1; + static LLColor4 magenta2; + static LLColor4 magenta3; + static LLColor4 magenta4; + + static LLColor4 purple1; + static LLColor4 purple2; + static LLColor4 purple3; + static LLColor4 purple4; + static LLColor4 purple5; + static LLColor4 purple6; + + static LLColor4 pink1; + static LLColor4 pink2; + + static LLColor4 cyan1; + static LLColor4 cyan2; + static LLColor4 cyan3; + static LLColor4 cyan4; + static LLColor4 cyan5; + static LLColor4 cyan6; + + static bool parseColor(const std::string& buf, LLColor4* color); + static bool parseColor4(const std::string& buf, LLColor4* color); + + inline void clamp(); }; -// Non-member functions -F32 distVec(const LLColor4 &a, const LLColor4 &b); // Returns distance between a and b -F32 distVec_squared(const LLColor4 &a, const LLColor4 &b); // Returns distance squared between a and b -LLColor3 vec4to3(const LLColor4 &vec); -LLColor4 vec3to4(const LLColor3 &vec); +// Non-member functions +F32 distVec(const LLColor4 &a, const LLColor4 &b); // Returns distance between a and b +F32 distVec_squared(const LLColor4 &a, const LLColor4 &b); // Returns distance squared between a and b +LLColor3 vec4to3(const LLColor4 &vec); +LLColor4 vec3to4(const LLColor3 &vec); LLColor4 lerp(const LLColor4 &a, const LLColor4 &b, F32 u); inline LLColor4::LLColor4(void) { - mV[VX] = 0.f; - mV[VY] = 0.f; - mV[VZ] = 0.f; - mV[VW] = 1.f; + mV[VX] = 0.f; + mV[VY] = 0.f; + mV[VZ] = 0.f; + mV[VW] = 1.f; } inline LLColor4::LLColor4(const LLSD& sd) { - this->setValue(sd); + this->setValue(sd); } inline LLColor4::LLColor4(F32 r, F32 g, F32 b) { - mV[VX] = r; - mV[VY] = g; - mV[VZ] = b; - mV[VW] = 1.f; + mV[VX] = r; + mV[VY] = g; + mV[VZ] = b; + mV[VW] = 1.f; } inline LLColor4::LLColor4(F32 r, F32 g, F32 b, F32 a) { - mV[VX] = r; - mV[VY] = g; - mV[VZ] = b; - mV[VW] = a; + mV[VX] = r; + mV[VY] = g; + mV[VZ] = b; + mV[VW] = a; } inline LLColor4::LLColor4(U32 clr) { - mV[VX] = (clr&0xff) * (1.0f/255.0f); - mV[VY] = ((clr>>8)&0xff) * (1.0f/255.0f); - mV[VZ] = ((clr>>16)&0xff) * (1.0f/255.0f); - mV[VW] = (clr>>24) * (1.0f/255.0f); + mV[VX] = (clr&0xff) * (1.0f/255.0f); + mV[VY] = ((clr>>8)&0xff) * (1.0f/255.0f); + mV[VZ] = ((clr>>16)&0xff) * (1.0f/255.0f); + mV[VW] = (clr>>24) * (1.0f/255.0f); } inline LLColor4::LLColor4(const F32 *vec) { - mV[VX] = vec[VX]; - mV[VY] = vec[VY]; - mV[VZ] = vec[VZ]; - mV[VW] = vec[VW]; + mV[VX] = vec[VX]; + mV[VY] = vec[VY]; + mV[VZ] = vec[VZ]; + mV[VW] = vec[VW]; } -inline const LLColor4& LLColor4::setToBlack(void) +inline const LLColor4& LLColor4::setToBlack(void) { - mV[VX] = 0.f; - mV[VY] = 0.f; - mV[VZ] = 0.f; - mV[VW] = 1.f; - return (*this); + mV[VX] = 0.f; + mV[VY] = 0.f; + mV[VZ] = 0.f; + mV[VW] = 1.f; + return (*this); } -inline const LLColor4& LLColor4::setToWhite(void) +inline const LLColor4& LLColor4::setToWhite(void) { - mV[VX] = 1.f; - mV[VY] = 1.f; - mV[VZ] = 1.f; - mV[VW] = 1.f; - return (*this); + mV[VX] = 1.f; + mV[VY] = 1.f; + mV[VZ] = 1.f; + mV[VW] = 1.f; + return (*this); } -inline const LLColor4& LLColor4::set(F32 x, F32 y, F32 z) +inline const LLColor4& LLColor4::set(F32 x, F32 y, F32 z) { - mV[VX] = x; - mV[VY] = y; - mV[VZ] = z; + mV[VX] = x; + mV[VY] = y; + mV[VZ] = z; // no change to alpha! -// mV[VW] = 1.f; +// mV[VW] = 1.f; - return (*this); + return (*this); } -inline const LLColor4& LLColor4::set(F32 x, F32 y, F32 z, F32 a) +inline const LLColor4& LLColor4::set(F32 x, F32 y, F32 z, F32 a) { - mV[VX] = x; - mV[VY] = y; - mV[VZ] = z; - mV[VW] = a; - return (*this); + mV[VX] = x; + mV[VY] = y; + mV[VZ] = z; + mV[VW] = a; + return (*this); } -inline const LLColor4& LLColor4::set(const LLColor4 &vec) +inline const LLColor4& LLColor4::set(const LLColor4 &vec) { - mV[VX] = vec.mV[VX]; - mV[VY] = vec.mV[VY]; - mV[VZ] = vec.mV[VZ]; - mV[VW] = vec.mV[VW]; - return (*this); + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; + mV[VZ] = vec.mV[VZ]; + mV[VW] = vec.mV[VW]; + return (*this); } -inline const LLColor4& LLColor4::set(const F32 *vec) +inline const LLColor4& LLColor4::set(const F32 *vec) { - mV[VX] = vec[VX]; - mV[VY] = vec[VY]; - mV[VZ] = vec[VZ]; - mV[VW] = vec[VW]; - return (*this); + mV[VX] = vec[VX]; + mV[VY] = vec[VY]; + mV[VZ] = vec[VZ]; + mV[VW] = vec[VW]; + return (*this); } -inline const LLColor4& LLColor4::set(const F64 *vec) +inline const LLColor4& LLColor4::set(const F64 *vec) { mV[VX] = static_cast<F32>(vec[VX]); mV[VY] = static_cast<F32>(vec[VY]); @@ -354,108 +354,108 @@ inline const LLColor4& LLColor4::set(const F64 *vec) } // deprecated -inline const LLColor4& LLColor4::setVec(F32 x, F32 y, F32 z) +inline const LLColor4& LLColor4::setVec(F32 x, F32 y, F32 z) { - mV[VX] = x; - mV[VY] = y; - mV[VZ] = z; + mV[VX] = x; + mV[VY] = y; + mV[VZ] = z; // no change to alpha! -// mV[VW] = 1.f; +// mV[VW] = 1.f; - return (*this); + return (*this); } // deprecated -inline const LLColor4& LLColor4::setVec(F32 x, F32 y, F32 z, F32 a) +inline const LLColor4& LLColor4::setVec(F32 x, F32 y, F32 z, F32 a) { - mV[VX] = x; - mV[VY] = y; - mV[VZ] = z; - mV[VW] = a; - return (*this); + mV[VX] = x; + mV[VY] = y; + mV[VZ] = z; + mV[VW] = a; + return (*this); } // deprecated -inline const LLColor4& LLColor4::setVec(const LLColor4 &vec) +inline const LLColor4& LLColor4::setVec(const LLColor4 &vec) { - mV[VX] = vec.mV[VX]; - mV[VY] = vec.mV[VY]; - mV[VZ] = vec.mV[VZ]; - mV[VW] = vec.mV[VW]; - return (*this); + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; + mV[VZ] = vec.mV[VZ]; + mV[VW] = vec.mV[VW]; + return (*this); } // deprecated -inline const LLColor4& LLColor4::setVec(const F32 *vec) +inline const LLColor4& LLColor4::setVec(const F32 *vec) { - mV[VX] = vec[VX]; - mV[VY] = vec[VY]; - mV[VZ] = vec[VZ]; - mV[VW] = vec[VW]; - return (*this); + mV[VX] = vec[VX]; + mV[VY] = vec[VY]; + mV[VZ] = vec[VZ]; + mV[VW] = vec[VW]; + return (*this); } -inline const LLColor4& LLColor4::setAlpha(F32 a) +inline const LLColor4& LLColor4::setAlpha(F32 a) { - mV[VW] = a; - return (*this); + mV[VW] = a; + return (*this); } // LLColor4 Magnitude and Normalization Functions -inline F32 LLColor4::length(void) const +inline F32 LLColor4::length(void) const { - return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); } -inline F32 LLColor4::lengthSquared(void) const +inline F32 LLColor4::lengthSquared(void) const { - return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]; + return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]; } -inline F32 LLColor4::normalize(void) +inline F32 LLColor4::normalize(void) { - F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); - F32 oomag; + F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + F32 oomag; - if (mag) - { - oomag = 1.f/mag; - mV[VX] *= oomag; - mV[VY] *= oomag; - mV[VZ] *= oomag; - } - return (mag); + if (mag) + { + oomag = 1.f/mag; + mV[VX] *= oomag; + mV[VY] *= oomag; + mV[VZ] *= oomag; + } + return (mag); } // deprecated -inline F32 LLColor4::magVec(void) const +inline F32 LLColor4::magVec(void) const { - return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); } // deprecated -inline F32 LLColor4::magVecSquared(void) const +inline F32 LLColor4::magVecSquared(void) const { - return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]; + return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]; } // deprecated -inline F32 LLColor4::normVec(void) +inline F32 LLColor4::normVec(void) { - F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); - F32 oomag; + F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + F32 oomag; - if (mag) - { - oomag = 1.f/mag; - mV[VX] *= oomag; - mV[VY] *= oomag; - mV[VZ] *= oomag; - } - return (mag); + if (mag) + { + oomag = 1.f/mag; + mV[VX] *= oomag; + mV[VY] *= oomag; + mV[VZ] *= oomag; + } + return (mag); } // LLColor4 Operators @@ -463,39 +463,39 @@ inline F32 LLColor4::normVec(void) inline LLColor4 operator+(const LLColor4 &a, const LLColor4 &b) { - return LLColor4( - a.mV[VX] + b.mV[VX], - a.mV[VY] + b.mV[VY], - a.mV[VZ] + b.mV[VZ], - a.mV[VW] + b.mV[VW]); + return LLColor4( + a.mV[VX] + b.mV[VX], + a.mV[VY] + b.mV[VY], + a.mV[VZ] + b.mV[VZ], + a.mV[VW] + b.mV[VW]); } inline LLColor4 operator-(const LLColor4 &a, const LLColor4 &b) { - return LLColor4( - a.mV[VX] - b.mV[VX], - a.mV[VY] - b.mV[VY], - a.mV[VZ] - b.mV[VZ], - a.mV[VW] - b.mV[VW]); + return LLColor4( + a.mV[VX] - b.mV[VX], + a.mV[VY] - b.mV[VY], + a.mV[VZ] - b.mV[VZ], + a.mV[VW] - b.mV[VW]); } inline LLColor4 operator*(const LLColor4 &a, const LLColor4 &b) { - return LLColor4( - a.mV[VX] * b.mV[VX], - a.mV[VY] * b.mV[VY], - a.mV[VZ] * b.mV[VZ], - a.mV[VW] * b.mV[VW]); + return LLColor4( + a.mV[VX] * b.mV[VX], + a.mV[VY] * b.mV[VY], + a.mV[VZ] * b.mV[VZ], + a.mV[VW] * b.mV[VW]); } inline LLColor4 operator*(const LLColor4 &a, F32 k) -{ - // only affects rgb (not a!) - return LLColor4( - a.mV[VX] * k, - a.mV[VY] * k, - a.mV[VZ] * k, - a.mV[VW]); +{ + // only affects rgb (not a!) + return LLColor4( + a.mV[VX] * k, + a.mV[VY] * k, + a.mV[VZ] * k, + a.mV[VW]); } inline LLColor4 operator/(const LLColor4 &a, F32 k) @@ -509,170 +509,170 @@ inline LLColor4 operator/(const LLColor4 &a, F32 k) inline LLColor4 operator*(F32 k, const LLColor4 &a) { - // only affects rgb (not a!) - return LLColor4( - a.mV[VX] * k, - a.mV[VY] * k, - a.mV[VZ] * k, - a.mV[VW]); + // only affects rgb (not a!) + return LLColor4( + a.mV[VX] * k, + a.mV[VY] * k, + a.mV[VZ] * k, + a.mV[VW]); } inline LLColor4 operator%(F32 k, const LLColor4 &a) { - // only affects alpha (not rgb!) - return LLColor4( - a.mV[VX], - a.mV[VY], - a.mV[VZ], - a.mV[VW] * k); + // only affects alpha (not rgb!) + return LLColor4( + a.mV[VX], + a.mV[VY], + a.mV[VZ], + a.mV[VW] * k); } inline LLColor4 operator%(const LLColor4 &a, F32 k) { - // only affects alpha (not rgb!) - return LLColor4( - a.mV[VX], - a.mV[VY], - a.mV[VZ], - a.mV[VW] * k); + // only affects alpha (not rgb!) + return LLColor4( + a.mV[VX], + a.mV[VY], + a.mV[VZ], + a.mV[VW] * k); } inline bool operator==(const LLColor4 &a, const LLColor4 &b) { - return ( (a.mV[VX] == b.mV[VX]) - &&(a.mV[VY] == b.mV[VY]) - &&(a.mV[VZ] == b.mV[VZ]) - &&(a.mV[VW] == b.mV[VW])); + return ( (a.mV[VX] == b.mV[VX]) + &&(a.mV[VY] == b.mV[VY]) + &&(a.mV[VZ] == b.mV[VZ]) + &&(a.mV[VW] == b.mV[VW])); } inline bool operator!=(const LLColor4 &a, const LLColor4 &b) { - return ( (a.mV[VX] != b.mV[VX]) - ||(a.mV[VY] != b.mV[VY]) - ||(a.mV[VZ] != b.mV[VZ]) - ||(a.mV[VW] != b.mV[VW])); + return ( (a.mV[VX] != b.mV[VX]) + ||(a.mV[VY] != b.mV[VY]) + ||(a.mV[VZ] != b.mV[VZ]) + ||(a.mV[VW] != b.mV[VW])); } inline const LLColor4& operator+=(LLColor4 &a, const LLColor4 &b) { - a.mV[VX] += b.mV[VX]; - a.mV[VY] += b.mV[VY]; - a.mV[VZ] += b.mV[VZ]; - a.mV[VW] += b.mV[VW]; - return a; + a.mV[VX] += b.mV[VX]; + a.mV[VY] += b.mV[VY]; + a.mV[VZ] += b.mV[VZ]; + a.mV[VW] += b.mV[VW]; + return a; } inline const LLColor4& operator-=(LLColor4 &a, const LLColor4 &b) { - a.mV[VX] -= b.mV[VX]; - a.mV[VY] -= b.mV[VY]; - a.mV[VZ] -= b.mV[VZ]; - a.mV[VW] -= b.mV[VW]; - return a; + a.mV[VX] -= b.mV[VX]; + a.mV[VY] -= b.mV[VY]; + a.mV[VZ] -= b.mV[VZ]; + a.mV[VW] -= b.mV[VW]; + return a; } inline const LLColor4& operator*=(LLColor4 &a, F32 k) { - // only affects rgb (not a!) - a.mV[VX] *= k; - a.mV[VY] *= k; - a.mV[VZ] *= k; - return a; + // only affects rgb (not a!) + a.mV[VX] *= k; + a.mV[VY] *= k; + a.mV[VZ] *= k; + return a; } inline const LLColor4& operator *=(LLColor4 &a, const LLColor4 &b) { - a.mV[VX] *= b.mV[VX]; - a.mV[VY] *= b.mV[VY]; - a.mV[VZ] *= b.mV[VZ]; -// a.mV[VW] *= b.mV[VW]; - return a; + a.mV[VX] *= b.mV[VX]; + a.mV[VY] *= b.mV[VY]; + a.mV[VZ] *= b.mV[VZ]; +// a.mV[VW] *= b.mV[VW]; + return a; } inline const LLColor4& operator%=(LLColor4 &a, F32 k) { - // only affects alpha (not rgb!) - a.mV[VW] *= k; - return a; + // only affects alpha (not rgb!) + a.mV[VW] *= k; + return a; } // Non-member functions -inline F32 distVec(const LLColor4 &a, const LLColor4 &b) +inline F32 distVec(const LLColor4 &a, const LLColor4 &b) { - LLColor4 vec = a - b; - return (vec.length()); + LLColor4 vec = a - b; + return (vec.length()); } -inline F32 distVec_squared(const LLColor4 &a, const LLColor4 &b) +inline F32 distVec_squared(const LLColor4 &a, const LLColor4 &b) { - LLColor4 vec = a - b; - return (vec.lengthSquared()); + LLColor4 vec = a - b; + return (vec.lengthSquared()); } inline LLColor4 lerp(const LLColor4 &a, const LLColor4 &b, F32 u) { - return LLColor4( - a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u, - a.mV[VY] + (b.mV[VY] - a.mV[VY]) * u, - a.mV[VZ] + (b.mV[VZ] - a.mV[VZ]) * u, - a.mV[VW] + (b.mV[VW] - a.mV[VW]) * u); + return LLColor4( + a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u, + a.mV[VY] + (b.mV[VY] - a.mV[VY]) * u, + a.mV[VZ] + (b.mV[VZ] - a.mV[VZ]) * u, + a.mV[VW] + (b.mV[VW] - a.mV[VW]) * u); } inline bool LLColor4::operator<(const LLColor4& rhs) const { - if (mV[0] != rhs.mV[0]) - { - return mV[0] < rhs.mV[0]; - } - if (mV[1] != rhs.mV[1]) - { - return mV[1] < rhs.mV[1]; - } - if (mV[2] != rhs.mV[2]) - { - return mV[2] < rhs.mV[2]; - } + if (mV[0] != rhs.mV[0]) + { + return mV[0] < rhs.mV[0]; + } + if (mV[1] != rhs.mV[1]) + { + return mV[1] < rhs.mV[1]; + } + if (mV[2] != rhs.mV[2]) + { + return mV[2] < rhs.mV[2]; + } - return mV[3] < rhs.mV[3]; + return mV[3] < rhs.mV[3]; } void LLColor4::clamp() { - // Clamp the color... - if (mV[0] < 0.f) - { - mV[0] = 0.f; - } - else if (mV[0] > 1.f) - { - mV[0] = 1.f; - } - if (mV[1] < 0.f) - { - mV[1] = 0.f; - } - else if (mV[1] > 1.f) - { - mV[1] = 1.f; - } - if (mV[2] < 0.f) - { - mV[2] = 0.f; - } - else if (mV[2] > 1.f) - { - mV[2] = 1.f; - } - if (mV[3] < 0.f) - { - mV[3] = 0.f; - } - else if (mV[3] > 1.f) - { - mV[3] = 1.f; - } + // Clamp the color... + if (mV[0] < 0.f) + { + mV[0] = 0.f; + } + else if (mV[0] > 1.f) + { + mV[0] = 1.f; + } + if (mV[1] < 0.f) + { + mV[1] = 0.f; + } + else if (mV[1] > 1.f) + { + mV[1] = 1.f; + } + if (mV[2] < 0.f) + { + mV[2] = 0.f; + } + else if (mV[2] > 1.f) + { + mV[2] = 1.f; + } + if (mV[3] < 0.f) + { + mV[3] = 0.f; + } + else if (mV[3] > 1.f) + { + mV[3] = 1.f; + } } // Return the given linear space color value in gamma corrected (sRGB) space diff --git a/indra/llmath/v4coloru.cpp b/indra/llmath/v4coloru.cpp index d238d609b4..45d310856a 100644 --- a/indra/llmath/v4coloru.cpp +++ b/indra/llmath/v4coloru.cpp @@ -1,25 +1,25 @@ -/** +/** * @file v4coloru.cpp * @brief LLColor4U class implementation. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -43,7 +43,7 @@ LLColor4U LLColor4U::blue ( 0, 0, 255, 255); /* inlined to fix gcc compile link error LLColor4U::operator LLColor4() { - return(LLColor4((F32)mV[VRED]/255.f,(F32)mV[VGREEN]/255.f,(F32)mV[VBLUE]/255.f,(F32)mV[VALPHA]/255.f)); + return(LLColor4((F32)mV[VRED]/255.f,(F32)mV[VGREEN]/255.f,(F32)mV[VBLUE]/255.f,(F32)mV[VALPHA]/255.f)); } */ @@ -53,10 +53,10 @@ LLColor4U::operator LLColor4() /* LLColor4U::LLColor4U(const LLColor3 &vec) { - mV[VX] = vec.mV[VX]; - mV[VY] = vec.mV[VY]; - mV[VZ] = vec.mV[VZ]; - mV[VW] = 255; + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; + mV[VZ] = vec.mV[VZ]; + mV[VW] = 255; } */ @@ -70,51 +70,51 @@ LLColor4U::LLColor4U(const LLColor3 &vec) /* LLColor4U LLColor4U::operator=(const LLColor3 &a) { - mV[VX] = a.mV[VX]; - mV[VY] = a.mV[VY]; - mV[VZ] = a.mV[VZ]; + mV[VX] = a.mV[VX]; + mV[VY] = a.mV[VY]; + mV[VZ] = a.mV[VZ]; // converting from an rgb sets a=1 (opaque) - mV[VW] = 255; - return (*this); + mV[VW] = 255; + return (*this); } */ -std::ostream& operator<<(std::ostream& s, const LLColor4U &a) +std::ostream& operator<<(std::ostream& s, const LLColor4U &a) { - s << "{ " << (S32)a.mV[VX] << ", " << (S32)a.mV[VY] << ", " << (S32)a.mV[VZ] << ", " << (S32)a.mV[VW] << " }"; - return s; + s << "{ " << (S32)a.mV[VX] << ", " << (S32)a.mV[VY] << ", " << (S32)a.mV[VZ] << ", " << (S32)a.mV[VW] << " }"; + return s; } // static bool LLColor4U::parseColor4U(const std::string& buf, LLColor4U* value) { - if( buf.empty() || value == nullptr) - { - return false; - } - - U32 v[4]; - S32 count = sscanf( buf.c_str(), "%u, %u, %u, %u", v + 0, v + 1, v + 2, v + 3 ); - if (1 == count ) - { - // try this format - count = sscanf( buf.c_str(), "%u %u %u %u", v + 0, v + 1, v + 2, v + 3 ); - } - if( 4 != count ) - { - return false; - } - - for( S32 i = 0; i < 4; i++ ) - { - if( v[i] > U8_MAX ) - { - return false; - } - } - - value->set( U8(v[0]), U8(v[1]), U8(v[2]), U8(v[3]) ); - return true; + if( buf.empty() || value == nullptr) + { + return false; + } + + U32 v[4]; + S32 count = sscanf( buf.c_str(), "%u, %u, %u, %u", v + 0, v + 1, v + 2, v + 3 ); + if (1 == count ) + { + // try this format + count = sscanf( buf.c_str(), "%u %u %u %u", v + 0, v + 1, v + 2, v + 3 ); + } + if( 4 != count ) + { + return false; + } + + for( S32 i = 0; i < 4; i++ ) + { + if( v[i] > U8_MAX ) + { + return false; + } + } + + value->set( U8(v[0]), U8(v[1]), U8(v[2]), U8(v[3]) ); + return true; } diff --git a/indra/llmath/v4coloru.h b/indra/llmath/v4coloru.h index ca6a5425f9..6d921d12fa 100644 --- a/indra/llmath/v4coloru.h +++ b/indra/llmath/v4coloru.h @@ -1,25 +1,25 @@ -/** +/** * @file v4coloru.h * @brief The LLColor4U class. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -47,537 +47,537 @@ class LLColor4U { public: - U8 mV[LENGTHOFCOLOR4U]; - - LLColor4U(); // Initializes LLColor4U to (0, 0, 0, 1) - LLColor4U(U8 r, U8 g, U8 b); // Initializes LLColor4U to (r, g, b, 1) - LLColor4U(U8 r, U8 g, U8 b, U8 a); // Initializes LLColor4U to (r. g, b, a) - LLColor4U(const U8 *vec); // Initializes LLColor4U to (vec[0]. vec[1], vec[2], 1) - explicit LLColor4U(const LLSD& sd) - { - setValue(sd); - } - - void setValue(const LLSD& sd) - { - mV[0] = sd[0].asInteger(); - mV[1] = sd[1].asInteger(); - mV[2] = sd[2].asInteger(); - mV[3] = sd[3].asInteger(); - } - - LLSD getValue() const - { - LLSD ret; - ret[0] = mV[0]; - ret[1] = mV[1]; - ret[2] = mV[2]; - ret[3] = mV[3]; - return ret; - } - - const LLColor4U& setToBlack(); // zero LLColor4U to (0, 0, 0, 1) - const LLColor4U& setToWhite(); // zero LLColor4U to (0, 0, 0, 1) - - const LLColor4U& set(U8 r, U8 g, U8 b, U8 a);// Sets LLColor4U to (r, g, b, a) - const LLColor4U& set(U8 r, U8 g, U8 b); // Sets LLColor4U to (r, g, b) (no change in a) - const LLColor4U& set(const LLColor4U &vec); // Sets LLColor4U to vec - const LLColor4U& set(const U8 *vec); // Sets LLColor4U to vec - - const LLColor4U& setVec(U8 r, U8 g, U8 b, U8 a); // deprecated -- use set() - const LLColor4U& setVec(U8 r, U8 g, U8 b); // deprecated -- use set() - const LLColor4U& setVec(const LLColor4U &vec); // deprecated -- use set() - const LLColor4U& setVec(const U8 *vec); // deprecated -- use set() - - const LLColor4U& setAlpha(U8 a); - - F32 magVec() const; // deprecated -- use length() - F32 magVecSquared() const; // deprecated -- use lengthSquared() - - F32 length() const; // Returns magnitude squared of LLColor4U - F32 lengthSquared() const; // Returns magnitude squared of LLColor4U - - friend std::ostream& operator<<(std::ostream& s, const LLColor4U &a); // Print a - friend LLColor4U operator+(const LLColor4U &a, const LLColor4U &b); // Return vector a + b - friend LLColor4U operator-(const LLColor4U &a, const LLColor4U &b); // Return vector a minus b - friend LLColor4U operator*(const LLColor4U &a, const LLColor4U &b); // Return a * b - friend bool operator==(const LLColor4U &a, const LLColor4U &b); // Return a == b - friend bool operator!=(const LLColor4U &a, const LLColor4U &b); // Return a != b - - friend const LLColor4U& operator+=(LLColor4U &a, const LLColor4U &b); // Return vector a + b - friend const LLColor4U& operator-=(LLColor4U &a, const LLColor4U &b); // Return vector a minus b - friend const LLColor4U& operator*=(LLColor4U &a, U8 k); // Return rgb times scaler k (no alpha change) - friend const LLColor4U& operator%=(LLColor4U &a, U8 k); // Return alpha times scaler k (no rgb change) - - LLColor4U addClampMax(const LLColor4U &color); // Add and clamp the max - - LLColor4U multAll(const F32 k); // Multiply ALL channels by scalar k - - inline void setVecScaleClamp(const LLColor3 &color); - inline void setVecScaleClamp(const LLColor4 &color); - - static bool parseColor4U(const std::string& buf, LLColor4U* value); - - // conversion - operator LLColor4() const - { - return LLColor4(*this); - } - - U32 asRGBA() const; - void fromRGBA( U32 aVal ); - - static LLColor4U white; - static LLColor4U black; - static LLColor4U red; - static LLColor4U green; - static LLColor4U blue; + U8 mV[LENGTHOFCOLOR4U]; + + LLColor4U(); // Initializes LLColor4U to (0, 0, 0, 1) + LLColor4U(U8 r, U8 g, U8 b); // Initializes LLColor4U to (r, g, b, 1) + LLColor4U(U8 r, U8 g, U8 b, U8 a); // Initializes LLColor4U to (r. g, b, a) + LLColor4U(const U8 *vec); // Initializes LLColor4U to (vec[0]. vec[1], vec[2], 1) + explicit LLColor4U(const LLSD& sd) + { + setValue(sd); + } + + void setValue(const LLSD& sd) + { + mV[0] = sd[0].asInteger(); + mV[1] = sd[1].asInteger(); + mV[2] = sd[2].asInteger(); + mV[3] = sd[3].asInteger(); + } + + LLSD getValue() const + { + LLSD ret; + ret[0] = mV[0]; + ret[1] = mV[1]; + ret[2] = mV[2]; + ret[3] = mV[3]; + return ret; + } + + const LLColor4U& setToBlack(); // zero LLColor4U to (0, 0, 0, 1) + const LLColor4U& setToWhite(); // zero LLColor4U to (0, 0, 0, 1) + + const LLColor4U& set(U8 r, U8 g, U8 b, U8 a);// Sets LLColor4U to (r, g, b, a) + const LLColor4U& set(U8 r, U8 g, U8 b); // Sets LLColor4U to (r, g, b) (no change in a) + const LLColor4U& set(const LLColor4U &vec); // Sets LLColor4U to vec + const LLColor4U& set(const U8 *vec); // Sets LLColor4U to vec + + const LLColor4U& setVec(U8 r, U8 g, U8 b, U8 a); // deprecated -- use set() + const LLColor4U& setVec(U8 r, U8 g, U8 b); // deprecated -- use set() + const LLColor4U& setVec(const LLColor4U &vec); // deprecated -- use set() + const LLColor4U& setVec(const U8 *vec); // deprecated -- use set() + + const LLColor4U& setAlpha(U8 a); + + F32 magVec() const; // deprecated -- use length() + F32 magVecSquared() const; // deprecated -- use lengthSquared() + + F32 length() const; // Returns magnitude squared of LLColor4U + F32 lengthSquared() const; // Returns magnitude squared of LLColor4U + + friend std::ostream& operator<<(std::ostream& s, const LLColor4U &a); // Print a + friend LLColor4U operator+(const LLColor4U &a, const LLColor4U &b); // Return vector a + b + friend LLColor4U operator-(const LLColor4U &a, const LLColor4U &b); // Return vector a minus b + friend LLColor4U operator*(const LLColor4U &a, const LLColor4U &b); // Return a * b + friend bool operator==(const LLColor4U &a, const LLColor4U &b); // Return a == b + friend bool operator!=(const LLColor4U &a, const LLColor4U &b); // Return a != b + + friend const LLColor4U& operator+=(LLColor4U &a, const LLColor4U &b); // Return vector a + b + friend const LLColor4U& operator-=(LLColor4U &a, const LLColor4U &b); // Return vector a minus b + friend const LLColor4U& operator*=(LLColor4U &a, U8 k); // Return rgb times scaler k (no alpha change) + friend const LLColor4U& operator%=(LLColor4U &a, U8 k); // Return alpha times scaler k (no rgb change) + + LLColor4U addClampMax(const LLColor4U &color); // Add and clamp the max + + LLColor4U multAll(const F32 k); // Multiply ALL channels by scalar k + + inline void setVecScaleClamp(const LLColor3 &color); + inline void setVecScaleClamp(const LLColor4 &color); + + static bool parseColor4U(const std::string& buf, LLColor4U* value); + + // conversion + operator LLColor4() const + { + return LLColor4(*this); + } + + U32 asRGBA() const; + void fromRGBA( U32 aVal ); + + static LLColor4U white; + static LLColor4U black; + static LLColor4U red; + static LLColor4U green; + static LLColor4U blue; }; -// Non-member functions -F32 distVec(const LLColor4U &a, const LLColor4U &b); // Returns distance between a and b -F32 distVec_squared(const LLColor4U &a, const LLColor4U &b); // Returns distance squared between a and b +// Non-member functions +F32 distVec(const LLColor4U &a, const LLColor4U &b); // Returns distance between a and b +F32 distVec_squared(const LLColor4U &a, const LLColor4U &b); // Returns distance squared between a and b inline LLColor4U::LLColor4U() { - mV[VX] = 0; - mV[VY] = 0; - mV[VZ] = 0; - mV[VW] = 255; + mV[VX] = 0; + mV[VY] = 0; + mV[VZ] = 0; + mV[VW] = 255; } inline LLColor4U::LLColor4U(U8 r, U8 g, U8 b) { - mV[VX] = r; - mV[VY] = g; - mV[VZ] = b; - mV[VW] = 255; + mV[VX] = r; + mV[VY] = g; + mV[VZ] = b; + mV[VW] = 255; } inline LLColor4U::LLColor4U(U8 r, U8 g, U8 b, U8 a) { - mV[VX] = r; - mV[VY] = g; - mV[VZ] = b; - mV[VW] = a; + mV[VX] = r; + mV[VY] = g; + mV[VZ] = b; + mV[VW] = a; } inline LLColor4U::LLColor4U(const U8 *vec) { - mV[VX] = vec[VX]; - mV[VY] = vec[VY]; - mV[VZ] = vec[VZ]; - mV[VW] = vec[VW]; + mV[VX] = vec[VX]; + mV[VY] = vec[VY]; + mV[VZ] = vec[VZ]; + mV[VW] = vec[VW]; } /* inline LLColor4U::operator LLColor4() { - return(LLColor4((F32)mV[VRED]/255.f,(F32)mV[VGREEN]/255.f,(F32)mV[VBLUE]/255.f,(F32)mV[VALPHA]/255.f)); + return(LLColor4((F32)mV[VRED]/255.f,(F32)mV[VGREEN]/255.f,(F32)mV[VBLUE]/255.f,(F32)mV[VALPHA]/255.f)); } */ -inline const LLColor4U& LLColor4U::setToBlack(void) +inline const LLColor4U& LLColor4U::setToBlack(void) { - mV[VX] = 0; - mV[VY] = 0; - mV[VZ] = 0; - mV[VW] = 255; - return (*this); + mV[VX] = 0; + mV[VY] = 0; + mV[VZ] = 0; + mV[VW] = 255; + return (*this); } -inline const LLColor4U& LLColor4U::setToWhite(void) +inline const LLColor4U& LLColor4U::setToWhite(void) { - mV[VX] = 255; - mV[VY] = 255; - mV[VZ] = 255; - mV[VW] = 255; - return (*this); + mV[VX] = 255; + mV[VY] = 255; + mV[VZ] = 255; + mV[VW] = 255; + return (*this); } -inline const LLColor4U& LLColor4U::set(const U8 x, const U8 y, const U8 z) +inline const LLColor4U& LLColor4U::set(const U8 x, const U8 y, const U8 z) { - mV[VX] = x; - mV[VY] = y; - mV[VZ] = z; + mV[VX] = x; + mV[VY] = y; + mV[VZ] = z; // no change to alpha! -// mV[VW] = 255; +// mV[VW] = 255; - return (*this); + return (*this); } -inline const LLColor4U& LLColor4U::set(const U8 r, const U8 g, const U8 b, U8 a) +inline const LLColor4U& LLColor4U::set(const U8 r, const U8 g, const U8 b, U8 a) { - mV[0] = r; - mV[1] = g; - mV[2] = b; - mV[3] = a; - return (*this); + mV[0] = r; + mV[1] = g; + mV[2] = b; + mV[3] = a; + return (*this); } -inline const LLColor4U& LLColor4U::set(const LLColor4U &vec) +inline const LLColor4U& LLColor4U::set(const LLColor4U &vec) { - mV[VX] = vec.mV[VX]; - mV[VY] = vec.mV[VY]; - mV[VZ] = vec.mV[VZ]; - mV[VW] = vec.mV[VW]; - return (*this); + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; + mV[VZ] = vec.mV[VZ]; + mV[VW] = vec.mV[VW]; + return (*this); } -inline const LLColor4U& LLColor4U::set(const U8 *vec) +inline const LLColor4U& LLColor4U::set(const U8 *vec) { - mV[VX] = vec[VX]; - mV[VY] = vec[VY]; - mV[VZ] = vec[VZ]; - mV[VW] = vec[VW]; - return (*this); + mV[VX] = vec[VX]; + mV[VY] = vec[VY]; + mV[VZ] = vec[VZ]; + mV[VW] = vec[VW]; + return (*this); } // deprecated -inline const LLColor4U& LLColor4U::setVec(const U8 x, const U8 y, const U8 z) +inline const LLColor4U& LLColor4U::setVec(const U8 x, const U8 y, const U8 z) { - mV[VX] = x; - mV[VY] = y; - mV[VZ] = z; + mV[VX] = x; + mV[VY] = y; + mV[VZ] = z; // no change to alpha! -// mV[VW] = 255; +// mV[VW] = 255; - return (*this); + return (*this); } // deprecated -inline const LLColor4U& LLColor4U::setVec(const U8 r, const U8 g, const U8 b, U8 a) +inline const LLColor4U& LLColor4U::setVec(const U8 r, const U8 g, const U8 b, U8 a) { - mV[0] = r; - mV[1] = g; - mV[2] = b; - mV[3] = a; - return (*this); + mV[0] = r; + mV[1] = g; + mV[2] = b; + mV[3] = a; + return (*this); } // deprecated -inline const LLColor4U& LLColor4U::setVec(const LLColor4U &vec) +inline const LLColor4U& LLColor4U::setVec(const LLColor4U &vec) { - mV[VX] = vec.mV[VX]; - mV[VY] = vec.mV[VY]; - mV[VZ] = vec.mV[VZ]; - mV[VW] = vec.mV[VW]; - return (*this); + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; + mV[VZ] = vec.mV[VZ]; + mV[VW] = vec.mV[VW]; + return (*this); } // deprecated -inline const LLColor4U& LLColor4U::setVec(const U8 *vec) +inline const LLColor4U& LLColor4U::setVec(const U8 *vec) { - mV[VX] = vec[VX]; - mV[VY] = vec[VY]; - mV[VZ] = vec[VZ]; - mV[VW] = vec[VW]; - return (*this); + mV[VX] = vec[VX]; + mV[VY] = vec[VY]; + mV[VZ] = vec[VZ]; + mV[VW] = vec[VW]; + return (*this); } -inline const LLColor4U& LLColor4U::setAlpha(U8 a) +inline const LLColor4U& LLColor4U::setAlpha(U8 a) { - mV[VW] = a; - return (*this); + mV[VW] = a; + return (*this); } // LLColor4U Magnitude and Normalization Functions -inline F32 LLColor4U::length(void) const +inline F32 LLColor4U::length(void) const { - return (F32) sqrt( ((F32)mV[VX]) * mV[VX] + ((F32)mV[VY]) * mV[VY] + ((F32)mV[VZ]) * mV[VZ] ); + return (F32) sqrt( ((F32)mV[VX]) * mV[VX] + ((F32)mV[VY]) * mV[VY] + ((F32)mV[VZ]) * mV[VZ] ); } -inline F32 LLColor4U::lengthSquared(void) const +inline F32 LLColor4U::lengthSquared(void) const { - return ((F32)mV[VX]) * mV[VX] + ((F32)mV[VY]) * mV[VY] + ((F32)mV[VZ]) * mV[VZ]; + return ((F32)mV[VX]) * mV[VX] + ((F32)mV[VY]) * mV[VY] + ((F32)mV[VZ]) * mV[VZ]; } // deprecated -inline F32 LLColor4U::magVec(void) const +inline F32 LLColor4U::magVec(void) const { - return (F32) sqrt( ((F32)mV[VX]) * mV[VX] + ((F32)mV[VY]) * mV[VY] + ((F32)mV[VZ]) * mV[VZ] ); + return (F32) sqrt( ((F32)mV[VX]) * mV[VX] + ((F32)mV[VY]) * mV[VY] + ((F32)mV[VZ]) * mV[VZ] ); } // deprecated -inline F32 LLColor4U::magVecSquared(void) const +inline F32 LLColor4U::magVecSquared(void) const { - return ((F32)mV[VX]) * mV[VX] + ((F32)mV[VY]) * mV[VY] + ((F32)mV[VZ]) * mV[VZ]; + return ((F32)mV[VX]) * mV[VX] + ((F32)mV[VY]) * mV[VY] + ((F32)mV[VZ]) * mV[VZ]; } inline LLColor4U operator+(const LLColor4U &a, const LLColor4U &b) { - return LLColor4U( - a.mV[VX] + b.mV[VX], - a.mV[VY] + b.mV[VY], - a.mV[VZ] + b.mV[VZ], - a.mV[VW] + b.mV[VW]); + return LLColor4U( + a.mV[VX] + b.mV[VX], + a.mV[VY] + b.mV[VY], + a.mV[VZ] + b.mV[VZ], + a.mV[VW] + b.mV[VW]); } inline LLColor4U operator-(const LLColor4U &a, const LLColor4U &b) { - return LLColor4U( - a.mV[VX] - b.mV[VX], - a.mV[VY] - b.mV[VY], - a.mV[VZ] - b.mV[VZ], - a.mV[VW] - b.mV[VW]); + return LLColor4U( + a.mV[VX] - b.mV[VX], + a.mV[VY] - b.mV[VY], + a.mV[VZ] - b.mV[VZ], + a.mV[VW] - b.mV[VW]); } inline LLColor4U operator*(const LLColor4U &a, const LLColor4U &b) { - return LLColor4U( - a.mV[VX] * b.mV[VX], - a.mV[VY] * b.mV[VY], - a.mV[VZ] * b.mV[VZ], - a.mV[VW] * b.mV[VW]); + return LLColor4U( + a.mV[VX] * b.mV[VX], + a.mV[VY] * b.mV[VY], + a.mV[VZ] * b.mV[VZ], + a.mV[VW] * b.mV[VW]); } inline LLColor4U LLColor4U::addClampMax(const LLColor4U &color) { - return LLColor4U(llmin((S32)mV[VX] + color.mV[VX], 255), - llmin((S32)mV[VY] + color.mV[VY], 255), - llmin((S32)mV[VZ] + color.mV[VZ], 255), - llmin((S32)mV[VW] + color.mV[VW], 255)); + return LLColor4U(llmin((S32)mV[VX] + color.mV[VX], 255), + llmin((S32)mV[VY] + color.mV[VY], 255), + llmin((S32)mV[VZ] + color.mV[VZ], 255), + llmin((S32)mV[VW] + color.mV[VW], 255)); } inline LLColor4U LLColor4U::multAll(const F32 k) { - // Round to nearest - return LLColor4U( - (U8)ll_round(mV[VX] * k), - (U8)ll_round(mV[VY] * k), - (U8)ll_round(mV[VZ] * k), - (U8)ll_round(mV[VW] * k)); + // Round to nearest + return LLColor4U( + (U8)ll_round(mV[VX] * k), + (U8)ll_round(mV[VY] * k), + (U8)ll_round(mV[VZ] * k), + (U8)ll_round(mV[VW] * k)); } /* inline LLColor4U operator*(const LLColor4U &a, U8 k) -{ - // only affects rgb (not a!) - return LLColor4U( - a.mV[VX] * k, - a.mV[VY] * k, - a.mV[VZ] * k, - a.mV[VW]); +{ + // only affects rgb (not a!) + return LLColor4U( + a.mV[VX] * k, + a.mV[VY] * k, + a.mV[VZ] * k, + a.mV[VW]); } inline LLColor4U operator*(U8 k, const LLColor4U &a) { - // only affects rgb (not a!) - return LLColor4U( - a.mV[VX] * k, - a.mV[VY] * k, - a.mV[VZ] * k, - a.mV[VW]); + // only affects rgb (not a!) + return LLColor4U( + a.mV[VX] * k, + a.mV[VY] * k, + a.mV[VZ] * k, + a.mV[VW]); } inline LLColor4U operator%(U8 k, const LLColor4U &a) { - // only affects alpha (not rgb!) - return LLColor4U( - a.mV[VX], - a.mV[VY], - a.mV[VZ], - a.mV[VW] * k ); + // only affects alpha (not rgb!) + return LLColor4U( + a.mV[VX], + a.mV[VY], + a.mV[VZ], + a.mV[VW] * k ); } inline LLColor4U operator%(const LLColor4U &a, U8 k) { - // only affects alpha (not rgb!) - return LLColor4U( - a.mV[VX], - a.mV[VY], - a.mV[VZ], - a.mV[VW] * k ); + // only affects alpha (not rgb!) + return LLColor4U( + a.mV[VX], + a.mV[VY], + a.mV[VZ], + a.mV[VW] * k ); } */ inline bool operator==(const LLColor4U &a, const LLColor4U &b) { - return ( (a.mV[VX] == b.mV[VX]) - &&(a.mV[VY] == b.mV[VY]) - &&(a.mV[VZ] == b.mV[VZ]) - &&(a.mV[VW] == b.mV[VW])); + return ( (a.mV[VX] == b.mV[VX]) + &&(a.mV[VY] == b.mV[VY]) + &&(a.mV[VZ] == b.mV[VZ]) + &&(a.mV[VW] == b.mV[VW])); } inline bool operator!=(const LLColor4U &a, const LLColor4U &b) { - return ( (a.mV[VX] != b.mV[VX]) - ||(a.mV[VY] != b.mV[VY]) - ||(a.mV[VZ] != b.mV[VZ]) - ||(a.mV[VW] != b.mV[VW])); + return ( (a.mV[VX] != b.mV[VX]) + ||(a.mV[VY] != b.mV[VY]) + ||(a.mV[VZ] != b.mV[VZ]) + ||(a.mV[VW] != b.mV[VW])); } inline const LLColor4U& operator+=(LLColor4U &a, const LLColor4U &b) { - a.mV[VX] += b.mV[VX]; - a.mV[VY] += b.mV[VY]; - a.mV[VZ] += b.mV[VZ]; - a.mV[VW] += b.mV[VW]; - return a; + a.mV[VX] += b.mV[VX]; + a.mV[VY] += b.mV[VY]; + a.mV[VZ] += b.mV[VZ]; + a.mV[VW] += b.mV[VW]; + return a; } inline const LLColor4U& operator-=(LLColor4U &a, const LLColor4U &b) { - a.mV[VX] -= b.mV[VX]; - a.mV[VY] -= b.mV[VY]; - a.mV[VZ] -= b.mV[VZ]; - a.mV[VW] -= b.mV[VW]; - return a; + a.mV[VX] -= b.mV[VX]; + a.mV[VY] -= b.mV[VY]; + a.mV[VZ] -= b.mV[VZ]; + a.mV[VW] -= b.mV[VW]; + return a; } inline const LLColor4U& operator*=(LLColor4U &a, U8 k) { - // only affects rgb (not a!) - a.mV[VX] *= k; - a.mV[VY] *= k; - a.mV[VZ] *= k; - return a; + // only affects rgb (not a!) + a.mV[VX] *= k; + a.mV[VY] *= k; + a.mV[VZ] *= k; + return a; } inline const LLColor4U& operator%=(LLColor4U &a, U8 k) { - // only affects alpha (not rgb!) - a.mV[VW] *= k; - return a; + // only affects alpha (not rgb!) + a.mV[VW] *= k; + return a; } -inline F32 distVec(const LLColor4U &a, const LLColor4U &b) +inline F32 distVec(const LLColor4U &a, const LLColor4U &b) { - LLColor4U vec = a - b; - return (vec.length()); + LLColor4U vec = a - b; + return (vec.length()); } -inline F32 distVec_squared(const LLColor4U &a, const LLColor4U &b) +inline F32 distVec_squared(const LLColor4U &a, const LLColor4U &b) { - LLColor4U vec = a - b; - return (vec.lengthSquared()); + LLColor4U vec = a - b; + return (vec.lengthSquared()); } void LLColor4U::setVecScaleClamp(const LLColor4& color) { - F32 color_scale_factor = 255.f; - F32 max_color = llmax(color.mV[0], color.mV[1], color.mV[2]); - if (max_color > 1.f) - { - color_scale_factor /= max_color; - } - const S32 MAX_COLOR = 255; - S32 r = ll_round(color.mV[0] * color_scale_factor); - if (r > MAX_COLOR) - { - r = MAX_COLOR; - } - else if (r < 0) - { - r = 0; - } - mV[0] = r; - - S32 g = ll_round(color.mV[1] * color_scale_factor); - if (g > MAX_COLOR) - { - g = MAX_COLOR; - } - else if (g < 0) - { - g = 0; - } - mV[1] = g; - - S32 b = ll_round(color.mV[2] * color_scale_factor); - if (b > MAX_COLOR) - { - b = MAX_COLOR; - } - else if (b < 0) - { - b = 0; - } - mV[2] = b; - - // Alpha shouldn't be scaled, just clamped... - S32 a = ll_round(color.mV[3] * MAX_COLOR); - if (a > MAX_COLOR) - { - a = MAX_COLOR; - } - else if (a < 0) - { - a = 0; - } - mV[3] = a; + F32 color_scale_factor = 255.f; + F32 max_color = llmax(color.mV[0], color.mV[1], color.mV[2]); + if (max_color > 1.f) + { + color_scale_factor /= max_color; + } + const S32 MAX_COLOR = 255; + S32 r = ll_round(color.mV[0] * color_scale_factor); + if (r > MAX_COLOR) + { + r = MAX_COLOR; + } + else if (r < 0) + { + r = 0; + } + mV[0] = r; + + S32 g = ll_round(color.mV[1] * color_scale_factor); + if (g > MAX_COLOR) + { + g = MAX_COLOR; + } + else if (g < 0) + { + g = 0; + } + mV[1] = g; + + S32 b = ll_round(color.mV[2] * color_scale_factor); + if (b > MAX_COLOR) + { + b = MAX_COLOR; + } + else if (b < 0) + { + b = 0; + } + mV[2] = b; + + // Alpha shouldn't be scaled, just clamped... + S32 a = ll_round(color.mV[3] * MAX_COLOR); + if (a > MAX_COLOR) + { + a = MAX_COLOR; + } + else if (a < 0) + { + a = 0; + } + mV[3] = a; } void LLColor4U::setVecScaleClamp(const LLColor3& color) { - F32 color_scale_factor = 255.f; - F32 max_color = llmax(color.mV[0], color.mV[1], color.mV[2]); - if (max_color > 1.f) - { - color_scale_factor /= max_color; - } - - const S32 MAX_COLOR = 255; - S32 r = ll_round(color.mV[0] * color_scale_factor); - if (r > MAX_COLOR) - { - r = MAX_COLOR; - } - else - if (r < 0) - { - r = 0; - } - mV[0] = r; - - S32 g = ll_round(color.mV[1] * color_scale_factor); - if (g > MAX_COLOR) - { - g = MAX_COLOR; - } - else - if (g < 0) - { - g = 0; - } - mV[1] = g; - - S32 b = ll_round(color.mV[2] * color_scale_factor); - if (b > MAX_COLOR) - { - b = MAX_COLOR; - } - if (b < 0) - { - b = 0; - } - mV[2] = b; - - mV[3] = 255; + F32 color_scale_factor = 255.f; + F32 max_color = llmax(color.mV[0], color.mV[1], color.mV[2]); + if (max_color > 1.f) + { + color_scale_factor /= max_color; + } + + const S32 MAX_COLOR = 255; + S32 r = ll_round(color.mV[0] * color_scale_factor); + if (r > MAX_COLOR) + { + r = MAX_COLOR; + } + else + if (r < 0) + { + r = 0; + } + mV[0] = r; + + S32 g = ll_round(color.mV[1] * color_scale_factor); + if (g > MAX_COLOR) + { + g = MAX_COLOR; + } + else + if (g < 0) + { + g = 0; + } + mV[1] = g; + + S32 b = ll_round(color.mV[2] * color_scale_factor); + if (b > MAX_COLOR) + { + b = MAX_COLOR; + } + if (b < 0) + { + b = 0; + } + mV[2] = b; + + mV[3] = 255; } inline U32 LLColor4U::asRGBA() const { - // Little endian: values are swapped in memory. The original code access the array like a U32, so we need to swap here + // Little endian: values are swapped in memory. The original code access the array like a U32, so we need to swap here - return (mV[3] << 24) | (mV[2] << 16) | (mV[1] << 8) | mV[0]; + return (mV[3] << 24) | (mV[2] << 16) | (mV[1] << 8) | mV[0]; } inline void LLColor4U::fromRGBA( U32 aVal ) { - // Little endian: values are swapped in memory. The original code access the array like a U32, so we need to swap here + // Little endian: values are swapped in memory. The original code access the array like a U32, so we need to swap here - mV[ 0 ] = aVal & 0xFF; - aVal >>= 8; - mV[ 1 ] = aVal & 0xFF; - aVal >>= 8; - mV[ 2 ] = aVal & 0xFF; - aVal >>= 8; - mV[ 3 ] = aVal & 0xFF; + mV[ 0 ] = aVal & 0xFF; + aVal >>= 8; + mV[ 1 ] = aVal & 0xFF; + aVal >>= 8; + mV[ 2 ] = aVal & 0xFF; + aVal >>= 8; + mV[ 3 ] = aVal & 0xFF; } diff --git a/indra/llmath/v4math.cpp b/indra/llmath/v4math.cpp index a68028d74a..0aa6eb09c3 100644 --- a/indra/llmath/v4math.cpp +++ b/indra/llmath/v4math.cpp @@ -1,25 +1,25 @@ -/** +/** * @file v4math.cpp * @brief LLVector4 class implementation. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -36,47 +36,47 @@ // LLVector4 // Axis-Angle rotations -const LLVector4& LLVector4::rotVec(const LLMatrix4 &mat) +const LLVector4& LLVector4::rotVec(const LLMatrix4 &mat) { - *this = *this * mat; - return *this; + *this = *this * mat; + return *this; } -const LLVector4& LLVector4::rotVec(const LLQuaternion &q) +const LLVector4& LLVector4::rotVec(const LLQuaternion &q) { - *this = *this * q; - return *this; + *this = *this * q; + return *this; } -const LLVector4& LLVector4::scaleVec(const LLVector4& vec) +const LLVector4& LLVector4::scaleVec(const LLVector4& vec) { - mV[VX] *= vec.mV[VX]; - mV[VY] *= vec.mV[VY]; - mV[VZ] *= vec.mV[VZ]; - mV[VW] *= vec.mV[VW]; + mV[VX] *= vec.mV[VX]; + mV[VY] *= vec.mV[VY]; + mV[VZ] *= vec.mV[VZ]; + mV[VW] *= vec.mV[VW]; - return *this; + return *this; } // Sets all values to absolute value of their original values // Returns true if data changed bool LLVector4::abs() { - bool ret{ false }; + bool ret{ false }; - if (mV[0] < 0.f) { mV[0] = -mV[0]; ret = true; } - if (mV[1] < 0.f) { mV[1] = -mV[1]; ret = true; } - if (mV[2] < 0.f) { mV[2] = -mV[2]; ret = true; } - if (mV[3] < 0.f) { mV[3] = -mV[3]; ret = true; } + if (mV[0] < 0.f) { mV[0] = -mV[0]; ret = true; } + if (mV[1] < 0.f) { mV[1] = -mV[1]; ret = true; } + if (mV[2] < 0.f) { mV[2] = -mV[2]; ret = true; } + if (mV[3] < 0.f) { mV[3] = -mV[3]; ret = true; } - return ret; + return ret; } -std::ostream& operator<<(std::ostream& s, const LLVector4 &a) +std::ostream& operator<<(std::ostream& s, const LLVector4 &a) { - s << "{ " << a.mV[VX] << ", " << a.mV[VY] << ", " << a.mV[VZ] << ", " << a.mV[VW] << " }"; - return s; + s << "{ " << a.mV[VX] << ", " << a.mV[VY] << ", " << a.mV[VZ] << ", " << a.mV[VW] << " }"; + return s; } @@ -84,37 +84,37 @@ std::ostream& operator<<(std::ostream& s, const LLVector4 &a) F32 angle_between( const LLVector4& a, const LLVector4& b ) { - LLVector4 an = a; - LLVector4 bn = b; - an.normalize(); - bn.normalize(); - F32 cosine = an * bn; - F32 angle = (cosine >= 1.0f) ? 0.0f : - (cosine <= -1.0f) ? F_PI : - acos(cosine); - return angle; + LLVector4 an = a; + LLVector4 bn = b; + an.normalize(); + bn.normalize(); + F32 cosine = an * bn; + F32 angle = (cosine >= 1.0f) ? 0.0f : + (cosine <= -1.0f) ? F_PI : + acos(cosine); + return angle; } bool are_parallel(const LLVector4 &a, const LLVector4 &b, F32 epsilon) { - LLVector4 an = a; - LLVector4 bn = b; - an.normalize(); - bn.normalize(); - F32 dot = an * bn; - if ( (1.0f - fabs(dot)) < epsilon) - return true; - return false; + LLVector4 an = a; + LLVector4 bn = b; + an.normalize(); + bn.normalize(); + F32 dot = an * bn; + if ( (1.0f - fabs(dot)) < epsilon) + return true; + return false; } LLVector3 vec4to3(const LLVector4 &vec) { - return LLVector3( vec.mV[VX], vec.mV[VY], vec.mV[VZ] ); + return LLVector3( vec.mV[VX], vec.mV[VY], vec.mV[VZ] ); } LLVector4 vec3to4(const LLVector3 &vec) { - return LLVector4(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); + return LLVector4(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); } diff --git a/indra/llmath/v4math.h b/indra/llmath/v4math.h index f46033db11..7ed22212d3 100644 --- a/indra/llmath/v4math.h +++ b/indra/llmath/v4math.h @@ -1,25 +1,25 @@ -/** +/** * @file v4math.h * @brief LLVector4 class header file. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -42,28 +42,28 @@ static const U32 LENGTHOFVECTOR4 = 4; class LLVector4 { - public: - F32 mV[LENGTHOFVECTOR4]; - LLVector4(); // Initializes LLVector4 to (0, 0, 0, 1) - explicit LLVector4(const F32 *vec); // Initializes LLVector4 to (vec[0]. vec[1], vec[2], vec[3]) - explicit LLVector4(const F64 *vec); // Initialized LLVector4 to ((F32) vec[0], (F32) vec[1], (F32) vec[3], (F32) vec[4]); + public: + F32 mV[LENGTHOFVECTOR4]; + LLVector4(); // Initializes LLVector4 to (0, 0, 0, 1) + explicit LLVector4(const F32 *vec); // Initializes LLVector4 to (vec[0]. vec[1], vec[2], vec[3]) + explicit LLVector4(const F64 *vec); // Initialized LLVector4 to ((F32) vec[0], (F32) vec[1], (F32) vec[3], (F32) vec[4]); explicit LLVector4(const LLVector2 &vec); explicit LLVector4(const LLVector2 &vec, F32 z, F32 w); - explicit LLVector4(const LLVector3 &vec); // Initializes LLVector4 to (vec, 1) - explicit LLVector4(const LLVector3 &vec, F32 w); // Initializes LLVector4 to (vec, w) + explicit LLVector4(const LLVector3 &vec); // Initializes LLVector4 to (vec, 1) + explicit LLVector4(const LLVector3 &vec, F32 w); // Initializes LLVector4 to (vec, w) explicit LLVector4(const LLSD &sd); - LLVector4(F32 x, F32 y, F32 z); // Initializes LLVector4 to (x. y, z, 1) - LLVector4(F32 x, F32 y, F32 z, F32 w); - - LLSD getValue() const - { - LLSD ret; - ret[0] = mV[0]; - ret[1] = mV[1]; - ret[2] = mV[2]; - ret[3] = mV[3]; - return ret; - } + LLVector4(F32 x, F32 y, F32 z); // Initializes LLVector4 to (x. y, z, 1) + LLVector4(F32 x, F32 y, F32 z, F32 w); + + LLSD getValue() const + { + LLSD ret; + ret[0] = mV[0]; + ret[1] = mV[1]; + ret[2] = mV[2]; + ret[3] = mV[3]; + return ret; + } void setValue(const LLSD& sd) { @@ -74,116 +74,116 @@ class LLVector4 } - inline bool isFinite() const; // checks to see if all values of LLVector3 are finite - - inline void clear(); // Clears LLVector4 to (0, 0, 0, 1) - inline void clearVec(); // deprecated - inline void zeroVec(); // deprecated - - inline void set(F32 x, F32 y, F32 z); // Sets LLVector4 to (x, y, z, 1) - inline void set(F32 x, F32 y, F32 z, F32 w); // Sets LLVector4 to (x, y, z, w) - inline void set(const LLVector4 &vec); // Sets LLVector4 to vec - inline void set(const LLVector3 &vec, F32 w = 1.f); // Sets LLVector4 to LLVector3 vec - inline void set(const F32 *vec); // Sets LLVector4 to vec - - inline void setVec(F32 x, F32 y, F32 z); // deprecated - inline void setVec(F32 x, F32 y, F32 z, F32 w); // deprecated - inline void setVec(const LLVector4 &vec); // deprecated - inline void setVec(const LLVector3 &vec, F32 w = 1.f); // deprecated - inline void setVec(const F32 *vec); // deprecated - - F32 length() const; // Returns magnitude of LLVector4 - F32 lengthSquared() const; // Returns magnitude squared of LLVector4 - F32 normalize(); // Normalizes and returns the magnitude of LLVector4 - - F32 magVec() const; // deprecated - F32 magVecSquared() const; // deprecated - F32 normVec(); // deprecated - - // Sets all values to absolute value of their original values - // Returns true if data changed - bool abs(); - - bool isExactlyClear() const { return (mV[VW] == 1.0f) && !mV[VX] && !mV[VY] && !mV[VZ]; } - bool isExactlyZero() const { return !mV[VW] && !mV[VX] && !mV[VY] && !mV[VZ]; } - - const LLVector4& rotVec(const LLMatrix4 &mat); // Rotates by MAT4 mat - const LLVector4& rotVec(const LLQuaternion &q); // Rotates by QUAT q - - const LLVector4& scaleVec(const LLVector4& vec); // Scales component-wise by vec - - F32 operator[](int idx) const { return mV[idx]; } - F32 &operator[](int idx) { return mV[idx]; } - - friend std::ostream& operator<<(std::ostream& s, const LLVector4 &a); // Print a - friend LLVector4 operator+(const LLVector4 &a, const LLVector4 &b); // Return vector a + b - friend LLVector4 operator-(const LLVector4 &a, const LLVector4 &b); // Return vector a minus b - friend F32 operator*(const LLVector4 &a, const LLVector4 &b); // Return a dot b - friend LLVector4 operator%(const LLVector4 &a, const LLVector4 &b); // Return a cross b - friend LLVector4 operator/(const LLVector4 &a, F32 k); // Return a divided by scaler k - friend LLVector4 operator*(const LLVector4 &a, F32 k); // Return a times scaler k - friend LLVector4 operator*(F32 k, const LLVector4 &a); // Return a times scaler k - friend bool operator==(const LLVector4 &a, const LLVector4 &b); // Return a == b - friend bool operator!=(const LLVector4 &a, const LLVector4 &b); // Return a != b - - friend const LLVector4& operator+=(LLVector4 &a, const LLVector4 &b); // Return vector a + b - friend const LLVector4& operator-=(LLVector4 &a, const LLVector4 &b); // Return vector a minus b - friend const LLVector4& operator%=(LLVector4 &a, const LLVector4 &b); // Return a cross b - friend const LLVector4& operator*=(LLVector4 &a, F32 k); // Return a times scaler k - friend const LLVector4& operator/=(LLVector4 &a, F32 k); // Return a divided by scaler k - - friend LLVector4 operator-(const LLVector4 &a); // Return vector -a + inline bool isFinite() const; // checks to see if all values of LLVector3 are finite + + inline void clear(); // Clears LLVector4 to (0, 0, 0, 1) + inline void clearVec(); // deprecated + inline void zeroVec(); // deprecated + + inline void set(F32 x, F32 y, F32 z); // Sets LLVector4 to (x, y, z, 1) + inline void set(F32 x, F32 y, F32 z, F32 w); // Sets LLVector4 to (x, y, z, w) + inline void set(const LLVector4 &vec); // Sets LLVector4 to vec + inline void set(const LLVector3 &vec, F32 w = 1.f); // Sets LLVector4 to LLVector3 vec + inline void set(const F32 *vec); // Sets LLVector4 to vec + + inline void setVec(F32 x, F32 y, F32 z); // deprecated + inline void setVec(F32 x, F32 y, F32 z, F32 w); // deprecated + inline void setVec(const LLVector4 &vec); // deprecated + inline void setVec(const LLVector3 &vec, F32 w = 1.f); // deprecated + inline void setVec(const F32 *vec); // deprecated + + F32 length() const; // Returns magnitude of LLVector4 + F32 lengthSquared() const; // Returns magnitude squared of LLVector4 + F32 normalize(); // Normalizes and returns the magnitude of LLVector4 + + F32 magVec() const; // deprecated + F32 magVecSquared() const; // deprecated + F32 normVec(); // deprecated + + // Sets all values to absolute value of their original values + // Returns true if data changed + bool abs(); + + bool isExactlyClear() const { return (mV[VW] == 1.0f) && !mV[VX] && !mV[VY] && !mV[VZ]; } + bool isExactlyZero() const { return !mV[VW] && !mV[VX] && !mV[VY] && !mV[VZ]; } + + const LLVector4& rotVec(const LLMatrix4 &mat); // Rotates by MAT4 mat + const LLVector4& rotVec(const LLQuaternion &q); // Rotates by QUAT q + + const LLVector4& scaleVec(const LLVector4& vec); // Scales component-wise by vec + + F32 operator[](int idx) const { return mV[idx]; } + F32 &operator[](int idx) { return mV[idx]; } + + friend std::ostream& operator<<(std::ostream& s, const LLVector4 &a); // Print a + friend LLVector4 operator+(const LLVector4 &a, const LLVector4 &b); // Return vector a + b + friend LLVector4 operator-(const LLVector4 &a, const LLVector4 &b); // Return vector a minus b + friend F32 operator*(const LLVector4 &a, const LLVector4 &b); // Return a dot b + friend LLVector4 operator%(const LLVector4 &a, const LLVector4 &b); // Return a cross b + friend LLVector4 operator/(const LLVector4 &a, F32 k); // Return a divided by scaler k + friend LLVector4 operator*(const LLVector4 &a, F32 k); // Return a times scaler k + friend LLVector4 operator*(F32 k, const LLVector4 &a); // Return a times scaler k + friend bool operator==(const LLVector4 &a, const LLVector4 &b); // Return a == b + friend bool operator!=(const LLVector4 &a, const LLVector4 &b); // Return a != b + + friend const LLVector4& operator+=(LLVector4 &a, const LLVector4 &b); // Return vector a + b + friend const LLVector4& operator-=(LLVector4 &a, const LLVector4 &b); // Return vector a minus b + friend const LLVector4& operator%=(LLVector4 &a, const LLVector4 &b); // Return a cross b + friend const LLVector4& operator*=(LLVector4 &a, F32 k); // Return a times scaler k + friend const LLVector4& operator/=(LLVector4 &a, F32 k); // Return a divided by scaler k + + friend LLVector4 operator-(const LLVector4 &a); // Return vector -a }; -// Non-member functions -F32 angle_between(const LLVector4 &a, const LLVector4 &b); // Returns angle (radians) between a and b -bool are_parallel(const LLVector4 &a, const LLVector4 &b, F32 epsilon = F_APPROXIMATELY_ZERO); // Returns true if a and b are very close to parallel -F32 dist_vec(const LLVector4 &a, const LLVector4 &b); // Returns distance between a and b -F32 dist_vec_squared(const LLVector4 &a, const LLVector4 &b); // Returns distance squared between a and b -LLVector3 vec4to3(const LLVector4 &vec); -LLVector4 vec3to4(const LLVector3 &vec); +// Non-member functions +F32 angle_between(const LLVector4 &a, const LLVector4 &b); // Returns angle (radians) between a and b +bool are_parallel(const LLVector4 &a, const LLVector4 &b, F32 epsilon = F_APPROXIMATELY_ZERO); // Returns true if a and b are very close to parallel +F32 dist_vec(const LLVector4 &a, const LLVector4 &b); // Returns distance between a and b +F32 dist_vec_squared(const LLVector4 &a, const LLVector4 &b); // Returns distance squared between a and b +LLVector3 vec4to3(const LLVector4 &vec); +LLVector4 vec3to4(const LLVector3 &vec); LLVector4 lerp(const LLVector4 &a, const LLVector4 &b, F32 u); // Returns a vector that is a linear interpolation between a and b // Constructors inline LLVector4::LLVector4(void) { - mV[VX] = 0.f; - mV[VY] = 0.f; - mV[VZ] = 0.f; - mV[VW] = 1.f; + mV[VX] = 0.f; + mV[VY] = 0.f; + mV[VZ] = 0.f; + mV[VW] = 1.f; } inline LLVector4::LLVector4(F32 x, F32 y, F32 z) { - mV[VX] = x; - mV[VY] = y; - mV[VZ] = z; - mV[VW] = 1.f; + mV[VX] = x; + mV[VY] = y; + mV[VZ] = z; + mV[VW] = 1.f; } inline LLVector4::LLVector4(F32 x, F32 y, F32 z, F32 w) { - mV[VX] = x; - mV[VY] = y; - mV[VZ] = z; - mV[VW] = w; + mV[VX] = x; + mV[VY] = y; + mV[VZ] = z; + mV[VW] = w; } inline LLVector4::LLVector4(const F32 *vec) { - mV[VX] = vec[VX]; - mV[VY] = vec[VY]; - mV[VZ] = vec[VZ]; - mV[VW] = vec[VW]; + mV[VX] = vec[VX]; + mV[VY] = vec[VY]; + mV[VZ] = vec[VZ]; + mV[VW] = vec[VW]; } inline LLVector4::LLVector4(const F64 *vec) { - mV[VX] = (F32) vec[VX]; - mV[VY] = (F32) vec[VY]; - mV[VZ] = (F32) vec[VZ]; - mV[VW] = (F32) vec[VW]; + mV[VX] = (F32) vec[VX]; + mV[VY] = (F32) vec[VY]; + mV[VZ] = (F32) vec[VZ]; + mV[VW] = (F32) vec[VW]; } inline LLVector4::LLVector4(const LLVector2 &vec) @@ -204,18 +204,18 @@ inline LLVector4::LLVector4(const LLVector2 &vec, F32 z, F32 w) inline LLVector4::LLVector4(const LLVector3 &vec) { - mV[VX] = vec.mV[VX]; - mV[VY] = vec.mV[VY]; - mV[VZ] = vec.mV[VZ]; - mV[VW] = 1.f; + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; + mV[VZ] = vec.mV[VZ]; + mV[VW] = 1.f; } inline LLVector4::LLVector4(const LLVector3 &vec, F32 w) { - mV[VX] = vec.mV[VX]; - mV[VY] = vec.mV[VY]; - mV[VZ] = vec.mV[VZ]; - mV[VW] = w; + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; + mV[VZ] = vec.mV[VZ]; + mV[VW] = w; } inline LLVector4::LLVector4(const LLSD &sd) @@ -226,310 +226,310 @@ inline LLVector4::LLVector4(const LLSD &sd) inline bool LLVector4::isFinite() const { - return (llfinite(mV[VX]) && llfinite(mV[VY]) && llfinite(mV[VZ]) && llfinite(mV[VW])); + return (llfinite(mV[VX]) && llfinite(mV[VY]) && llfinite(mV[VZ]) && llfinite(mV[VW])); } // Clear and Assignment Functions -inline void LLVector4::clear(void) +inline void LLVector4::clear(void) { - mV[VX] = 0.f; - mV[VY] = 0.f; - mV[VZ] = 0.f; - mV[VW] = 1.f; + mV[VX] = 0.f; + mV[VY] = 0.f; + mV[VZ] = 0.f; + mV[VW] = 1.f; } // deprecated -inline void LLVector4::clearVec(void) +inline void LLVector4::clearVec(void) { - mV[VX] = 0.f; - mV[VY] = 0.f; - mV[VZ] = 0.f; - mV[VW] = 1.f; + mV[VX] = 0.f; + mV[VY] = 0.f; + mV[VZ] = 0.f; + mV[VW] = 1.f; } // deprecated -inline void LLVector4::zeroVec(void) +inline void LLVector4::zeroVec(void) { - mV[VX] = 0.f; - mV[VY] = 0.f; - mV[VZ] = 0.f; - mV[VW] = 0.f; + mV[VX] = 0.f; + mV[VY] = 0.f; + mV[VZ] = 0.f; + mV[VW] = 0.f; } -inline void LLVector4::set(F32 x, F32 y, F32 z) +inline void LLVector4::set(F32 x, F32 y, F32 z) { - mV[VX] = x; - mV[VY] = y; - mV[VZ] = z; - mV[VW] = 1.f; + mV[VX] = x; + mV[VY] = y; + mV[VZ] = z; + mV[VW] = 1.f; } -inline void LLVector4::set(F32 x, F32 y, F32 z, F32 w) +inline void LLVector4::set(F32 x, F32 y, F32 z, F32 w) { - mV[VX] = x; - mV[VY] = y; - mV[VZ] = z; - mV[VW] = w; + mV[VX] = x; + mV[VY] = y; + mV[VZ] = z; + mV[VW] = w; } -inline void LLVector4::set(const LLVector4 &vec) +inline void LLVector4::set(const LLVector4 &vec) { - mV[VX] = vec.mV[VX]; - mV[VY] = vec.mV[VY]; - mV[VZ] = vec.mV[VZ]; - mV[VW] = vec.mV[VW]; + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; + mV[VZ] = vec.mV[VZ]; + mV[VW] = vec.mV[VW]; } -inline void LLVector4::set(const LLVector3 &vec, F32 w) +inline void LLVector4::set(const LLVector3 &vec, F32 w) { - mV[VX] = vec.mV[VX]; - mV[VY] = vec.mV[VY]; - mV[VZ] = vec.mV[VZ]; - mV[VW] = w; + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; + mV[VZ] = vec.mV[VZ]; + mV[VW] = w; } -inline void LLVector4::set(const F32 *vec) +inline void LLVector4::set(const F32 *vec) { - mV[VX] = vec[VX]; - mV[VY] = vec[VY]; - mV[VZ] = vec[VZ]; - mV[VW] = vec[VW]; + mV[VX] = vec[VX]; + mV[VY] = vec[VY]; + mV[VZ] = vec[VZ]; + mV[VW] = vec[VW]; } // deprecated -inline void LLVector4::setVec(F32 x, F32 y, F32 z) +inline void LLVector4::setVec(F32 x, F32 y, F32 z) { - mV[VX] = x; - mV[VY] = y; - mV[VZ] = z; - mV[VW] = 1.f; + mV[VX] = x; + mV[VY] = y; + mV[VZ] = z; + mV[VW] = 1.f; } // deprecated -inline void LLVector4::setVec(F32 x, F32 y, F32 z, F32 w) +inline void LLVector4::setVec(F32 x, F32 y, F32 z, F32 w) { - mV[VX] = x; - mV[VY] = y; - mV[VZ] = z; - mV[VW] = w; + mV[VX] = x; + mV[VY] = y; + mV[VZ] = z; + mV[VW] = w; } // deprecated -inline void LLVector4::setVec(const LLVector4 &vec) +inline void LLVector4::setVec(const LLVector4 &vec) { - mV[VX] = vec.mV[VX]; - mV[VY] = vec.mV[VY]; - mV[VZ] = vec.mV[VZ]; - mV[VW] = vec.mV[VW]; + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; + mV[VZ] = vec.mV[VZ]; + mV[VW] = vec.mV[VW]; } // deprecated -inline void LLVector4::setVec(const LLVector3 &vec, F32 w) +inline void LLVector4::setVec(const LLVector3 &vec, F32 w) { - mV[VX] = vec.mV[VX]; - mV[VY] = vec.mV[VY]; - mV[VZ] = vec.mV[VZ]; - mV[VW] = w; + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; + mV[VZ] = vec.mV[VZ]; + mV[VW] = w; } // deprecated -inline void LLVector4::setVec(const F32 *vec) +inline void LLVector4::setVec(const F32 *vec) { - mV[VX] = vec[VX]; - mV[VY] = vec[VY]; - mV[VZ] = vec[VZ]; - mV[VW] = vec[VW]; + mV[VX] = vec[VX]; + mV[VY] = vec[VY]; + mV[VZ] = vec[VZ]; + mV[VW] = vec[VW]; } // LLVector4 Magnitude and Normalization Functions -inline F32 LLVector4::length(void) const +inline F32 LLVector4::length(void) const { - return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); } -inline F32 LLVector4::lengthSquared(void) const +inline F32 LLVector4::lengthSquared(void) const { - return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]; + return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]; } -inline F32 LLVector4::magVec(void) const +inline F32 LLVector4::magVec(void) const { - return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); } -inline F32 LLVector4::magVecSquared(void) const +inline F32 LLVector4::magVecSquared(void) const { - return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]; + return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]; } // LLVector4 Operators inline LLVector4 operator+(const LLVector4 &a, const LLVector4 &b) { - LLVector4 c(a); - return c += b; + LLVector4 c(a); + return c += b; } inline LLVector4 operator-(const LLVector4 &a, const LLVector4 &b) { - LLVector4 c(a); - return c -= b; + LLVector4 c(a); + return c -= b; } inline F32 operator*(const LLVector4 &a, const LLVector4 &b) { - return (a.mV[VX]*b.mV[VX] + a.mV[VY]*b.mV[VY] + a.mV[VZ]*b.mV[VZ]); + return (a.mV[VX]*b.mV[VX] + a.mV[VY]*b.mV[VY] + a.mV[VZ]*b.mV[VZ]); } inline LLVector4 operator%(const LLVector4 &a, const LLVector4 &b) { - return LLVector4(a.mV[VY]*b.mV[VZ] - b.mV[VY]*a.mV[VZ], a.mV[VZ]*b.mV[VX] - b.mV[VZ]*a.mV[VX], a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY]); + return LLVector4(a.mV[VY]*b.mV[VZ] - b.mV[VY]*a.mV[VZ], a.mV[VZ]*b.mV[VX] - b.mV[VZ]*a.mV[VX], a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY]); } inline LLVector4 operator/(const LLVector4 &a, F32 k) { - F32 t = 1.f / k; - return LLVector4( a.mV[VX] * t, a.mV[VY] * t, a.mV[VZ] * t ); + F32 t = 1.f / k; + return LLVector4( a.mV[VX] * t, a.mV[VY] * t, a.mV[VZ] * t ); } inline LLVector4 operator*(const LLVector4 &a, F32 k) { - return LLVector4( a.mV[VX] * k, a.mV[VY] * k, a.mV[VZ] * k ); + return LLVector4( a.mV[VX] * k, a.mV[VY] * k, a.mV[VZ] * k ); } inline LLVector4 operator*(F32 k, const LLVector4 &a) { - return LLVector4( a.mV[VX] * k, a.mV[VY] * k, a.mV[VZ] * k ); + return LLVector4( a.mV[VX] * k, a.mV[VY] * k, a.mV[VZ] * k ); } inline bool operator==(const LLVector4 &a, const LLVector4 &b) { - return ( (a.mV[VX] == b.mV[VX]) - &&(a.mV[VY] == b.mV[VY]) - &&(a.mV[VZ] == b.mV[VZ])); + return ( (a.mV[VX] == b.mV[VX]) + &&(a.mV[VY] == b.mV[VY]) + &&(a.mV[VZ] == b.mV[VZ])); } inline bool operator!=(const LLVector4 &a, const LLVector4 &b) { - return ( (a.mV[VX] != b.mV[VX]) - ||(a.mV[VY] != b.mV[VY]) - ||(a.mV[VZ] != b.mV[VZ]) - ||(a.mV[VW] != b.mV[VW]) ); + return ( (a.mV[VX] != b.mV[VX]) + ||(a.mV[VY] != b.mV[VY]) + ||(a.mV[VZ] != b.mV[VZ]) + ||(a.mV[VW] != b.mV[VW]) ); } inline const LLVector4& operator+=(LLVector4 &a, const LLVector4 &b) { - a.mV[VX] += b.mV[VX]; - a.mV[VY] += b.mV[VY]; - a.mV[VZ] += b.mV[VZ]; - return a; + a.mV[VX] += b.mV[VX]; + a.mV[VY] += b.mV[VY]; + a.mV[VZ] += b.mV[VZ]; + return a; } inline const LLVector4& operator-=(LLVector4 &a, const LLVector4 &b) { - a.mV[VX] -= b.mV[VX]; - a.mV[VY] -= b.mV[VY]; - a.mV[VZ] -= b.mV[VZ]; - return a; + a.mV[VX] -= b.mV[VX]; + a.mV[VY] -= b.mV[VY]; + a.mV[VZ] -= b.mV[VZ]; + return a; } inline const LLVector4& operator%=(LLVector4 &a, const LLVector4 &b) { - LLVector4 ret(a.mV[VY]*b.mV[VZ] - b.mV[VY]*a.mV[VZ], a.mV[VZ]*b.mV[VX] - b.mV[VZ]*a.mV[VX], a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY]); - a = ret; - return a; + LLVector4 ret(a.mV[VY]*b.mV[VZ] - b.mV[VY]*a.mV[VZ], a.mV[VZ]*b.mV[VX] - b.mV[VZ]*a.mV[VX], a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY]); + a = ret; + return a; } inline const LLVector4& operator*=(LLVector4 &a, F32 k) { - a.mV[VX] *= k; - a.mV[VY] *= k; - a.mV[VZ] *= k; - return a; + a.mV[VX] *= k; + a.mV[VY] *= k; + a.mV[VZ] *= k; + return a; } inline const LLVector4& operator/=(LLVector4 &a, F32 k) { - F32 t = 1.f / k; - a.mV[VX] *= t; - a.mV[VY] *= t; - a.mV[VZ] *= t; - return a; + F32 t = 1.f / k; + a.mV[VX] *= t; + a.mV[VY] *= t; + a.mV[VZ] *= t; + return a; } inline LLVector4 operator-(const LLVector4 &a) { - return LLVector4( -a.mV[VX], -a.mV[VY], -a.mV[VZ] ); + return LLVector4( -a.mV[VX], -a.mV[VY], -a.mV[VZ] ); } -inline F32 dist_vec(const LLVector4 &a, const LLVector4 &b) +inline F32 dist_vec(const LLVector4 &a, const LLVector4 &b) { - LLVector4 vec = a - b; - return (vec.length()); + LLVector4 vec = a - b; + return (vec.length()); } -inline F32 dist_vec_squared(const LLVector4 &a, const LLVector4 &b) +inline F32 dist_vec_squared(const LLVector4 &a, const LLVector4 &b) { - LLVector4 vec = a - b; - return (vec.lengthSquared()); + LLVector4 vec = a - b; + return (vec.lengthSquared()); } inline LLVector4 lerp(const LLVector4 &a, const LLVector4 &b, F32 u) { - return LLVector4( - a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u, - a.mV[VY] + (b.mV[VY] - a.mV[VY]) * u, - a.mV[VZ] + (b.mV[VZ] - a.mV[VZ]) * u, - a.mV[VW] + (b.mV[VW] - a.mV[VW]) * u); + return LLVector4( + a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u, + a.mV[VY] + (b.mV[VY] - a.mV[VY]) * u, + a.mV[VZ] + (b.mV[VZ] - a.mV[VZ]) * u, + a.mV[VW] + (b.mV[VW] - a.mV[VW]) * u); } -inline F32 LLVector4::normalize(void) +inline F32 LLVector4::normalize(void) { - F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); - F32 oomag; + F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + F32 oomag; - if (mag > FP_MAG_THRESHOLD) - { - oomag = 1.f/mag; - mV[VX] *= oomag; - mV[VY] *= oomag; - mV[VZ] *= oomag; - } - else - { - mV[0] = 0.f; - mV[1] = 0.f; - mV[2] = 0.f; - mag = 0; - } - return (mag); + if (mag > FP_MAG_THRESHOLD) + { + oomag = 1.f/mag; + mV[VX] *= oomag; + mV[VY] *= oomag; + mV[VZ] *= oomag; + } + else + { + mV[0] = 0.f; + mV[1] = 0.f; + mV[2] = 0.f; + mag = 0; + } + return (mag); } // deprecated -inline F32 LLVector4::normVec(void) -{ - F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); - F32 oomag; - - if (mag > FP_MAG_THRESHOLD) - { - oomag = 1.f/mag; - mV[VX] *= oomag; - mV[VY] *= oomag; - mV[VZ] *= oomag; - } - else - { - mV[0] = 0.f; - mV[1] = 0.f; - mV[2] = 0.f; - mag = 0; - } - return (mag); +inline F32 LLVector4::normVec(void) +{ + F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + F32 oomag; + + if (mag > FP_MAG_THRESHOLD) + { + oomag = 1.f/mag; + mV[VX] *= oomag; + mV[VY] *= oomag; + mV[VZ] *= oomag; + } + else + { + mV[0] = 0.f; + mV[1] = 0.f; + mV[2] = 0.f; + mag = 0; + } + return (mag); } // Because apparently some parts of the viewer use this for color info. diff --git a/indra/llmath/xform.cpp b/indra/llmath/xform.cpp index 838dee0a54..39bbb94c9f 100644 --- a/indra/llmath/xform.cpp +++ b/indra/llmath/xform.cpp @@ -1,24 +1,24 @@ -/** +/** * @file xform.cpp * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -29,7 +29,7 @@ LLXform::LLXform() { - init(); + init(); } LLXform::~LLXform() @@ -39,27 +39,27 @@ LLXform::~LLXform() // Link optimization - don't inline these LL_WARNS() void LLXform::warn(const char* const msg) { - LL_WARNS() << msg << LL_ENDL; + LL_WARNS() << msg << LL_ENDL; } LLXform* LLXform::getRoot() const { - const LLXform* root = this; - while(root->mParent) - { - root = root->mParent; - } - return (LLXform*)root; + const LLXform* root = this; + while(root->mParent) + { + root = root->mParent; + } + return (LLXform*)root; } bool LLXform::isRoot() const { - return (!mParent); + return (!mParent); } bool LLXform::isRootEdit() const { - return (!mParent); + return (!mParent); } LLXformMatrix::~LLXformMatrix() @@ -68,52 +68,52 @@ LLXformMatrix::~LLXformMatrix() void LLXformMatrix::update() { - if (mParent) - { - mWorldPosition = mPosition; - if (mParent->getScaleChildOffset()) - { - mWorldPosition.scaleVec(mParent->getScale()); - } - mWorldPosition *= mParent->getWorldRotation(); - mWorldPosition += mParent->getWorldPosition(); - mWorldRotation = mRotation * mParent->getWorldRotation(); - } - else - { - mWorldPosition = mPosition; - mWorldRotation = mRotation; - } + if (mParent) + { + mWorldPosition = mPosition; + if (mParent->getScaleChildOffset()) + { + mWorldPosition.scaleVec(mParent->getScale()); + } + mWorldPosition *= mParent->getWorldRotation(); + mWorldPosition += mParent->getWorldPosition(); + mWorldRotation = mRotation * mParent->getWorldRotation(); + } + else + { + mWorldPosition = mPosition; + mWorldRotation = mRotation; + } } void LLXformMatrix::updateMatrix(bool update_bounds) { - update(); + update(); - mWorldMatrix.initAll(mScale, mWorldRotation, mWorldPosition); + mWorldMatrix.initAll(mScale, mWorldRotation, mWorldPosition); - if (update_bounds && (mChanged & MOVED)) - { - mMin.mV[0] = mMax.mV[0] = mWorldMatrix.mMatrix[3][0]; - mMin.mV[1] = mMax.mV[1] = mWorldMatrix.mMatrix[3][1]; - mMin.mV[2] = mMax.mV[2] = mWorldMatrix.mMatrix[3][2]; + if (update_bounds && (mChanged & MOVED)) + { + mMin.mV[0] = mMax.mV[0] = mWorldMatrix.mMatrix[3][0]; + mMin.mV[1] = mMax.mV[1] = mWorldMatrix.mMatrix[3][1]; + mMin.mV[2] = mMax.mV[2] = mWorldMatrix.mMatrix[3][2]; - F32 f0 = (fabs(mWorldMatrix.mMatrix[0][0])+fabs(mWorldMatrix.mMatrix[1][0])+fabs(mWorldMatrix.mMatrix[2][0])) * 0.5f; - F32 f1 = (fabs(mWorldMatrix.mMatrix[0][1])+fabs(mWorldMatrix.mMatrix[1][1])+fabs(mWorldMatrix.mMatrix[2][1])) * 0.5f; - F32 f2 = (fabs(mWorldMatrix.mMatrix[0][2])+fabs(mWorldMatrix.mMatrix[1][2])+fabs(mWorldMatrix.mMatrix[2][2])) * 0.5f; + F32 f0 = (fabs(mWorldMatrix.mMatrix[0][0])+fabs(mWorldMatrix.mMatrix[1][0])+fabs(mWorldMatrix.mMatrix[2][0])) * 0.5f; + F32 f1 = (fabs(mWorldMatrix.mMatrix[0][1])+fabs(mWorldMatrix.mMatrix[1][1])+fabs(mWorldMatrix.mMatrix[2][1])) * 0.5f; + F32 f2 = (fabs(mWorldMatrix.mMatrix[0][2])+fabs(mWorldMatrix.mMatrix[1][2])+fabs(mWorldMatrix.mMatrix[2][2])) * 0.5f; - mMin.mV[0] -= f0; - mMin.mV[1] -= f1; - mMin.mV[2] -= f2; + mMin.mV[0] -= f0; + mMin.mV[1] -= f1; + mMin.mV[2] -= f2; - mMax.mV[0] += f0; - mMax.mV[1] += f1; - mMax.mV[2] += f2; - } + mMax.mV[0] += f0; + mMax.mV[1] += f1; + mMax.mV[2] += f2; + } } void LLXformMatrix::getMinMax(LLVector3& min, LLVector3& max) const { - min = mMin; - max = mMax; + min = mMin; + max = mMax; } diff --git a/indra/llmath/xform.h b/indra/llmath/xform.h index a301e4ca47..7434301670 100644 --- a/indra/llmath/xform.h +++ b/indra/llmath/xform.h @@ -1,24 +1,24 @@ -/** +/** * @file xform.h * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -30,286 +30,286 @@ #include "m4math.h" #include "llquaternion.h" -constexpr F32 MAX_OBJECT_Z = 4096.f; // should match REGION_HEIGHT_METERS, Pre-havok4: 768.f -constexpr F32 MIN_OBJECT_Z = -256.f; +constexpr F32 MAX_OBJECT_Z = 4096.f; // should match REGION_HEIGHT_METERS, Pre-havok4: 768.f +constexpr F32 MIN_OBJECT_Z = -256.f; constexpr F32 DEFAULT_MAX_PRIM_SCALE = 64.f; constexpr F32 DEFAULT_MAX_PRIM_SCALE_NO_MESH = 10.f; constexpr F32 MIN_PRIM_SCALE = 0.01f; -constexpr F32 MAX_PRIM_SCALE = 65536.f; // something very high but not near FLT_MAX +constexpr F32 MAX_PRIM_SCALE = 65536.f; // something very high but not near FLT_MAX class LLXform { protected: - LLVector3 mPosition; - LLQuaternion mRotation; - LLVector3 mScale; - - //RN: TODO: move these world transform members to LLXformMatrix - // as they are *never* updated or accessed in the base class - LLVector3 mWorldPosition; - LLQuaternion mWorldRotation; + LLVector3 mPosition; + LLQuaternion mRotation; + LLVector3 mScale; - LLXform* mParent; - U32 mChanged; + //RN: TODO: move these world transform members to LLXformMatrix + // as they are *never* updated or accessed in the base class + LLVector3 mWorldPosition; + LLQuaternion mWorldRotation; - bool mScaleChildOffset; + LLXform* mParent; + U32 mChanged; + + bool mScaleChildOffset; public: - typedef enum e_changed_flags - { - UNCHANGED = 0x00, - TRANSLATED = 0x01, - ROTATED = 0x02, - SCALED = 0x04, - SHIFTED = 0x08, - GEOMETRY = 0x10, - TEXTURE = 0x20, - MOVED = TRANSLATED|ROTATED|SCALED, - SILHOUETTE = 0x40, - ALL_CHANGED = 0x7f - }EChangedFlags; - - void init() - { - mParent = NULL; - mChanged = UNCHANGED; - mPosition.setVec(0,0,0); - mRotation.loadIdentity(); - mScale. setVec(1,1,1); - mWorldPosition.clearVec(); - mWorldRotation.loadIdentity(); - mScaleChildOffset = false; - } - - LLXform(); - virtual ~LLXform(); - - void getLocalMat4(LLMatrix4 &mat) const { mat.initAll(mScale, mRotation, mPosition); } - - inline bool setParent(LLXform *parent); - - inline void setPosition(const LLVector3& pos); - inline void setPosition(const F32 x, const F32 y, const F32 z); - inline void setPositionX(const F32 x); - inline void setPositionY(const F32 y); - inline void setPositionZ(const F32 z); - inline void addPosition(const LLVector3& pos); - - - inline void setScale(const LLVector3& scale); - inline void setScale(const F32 x, const F32 y, const F32 z); - inline void setRotation(const LLQuaternion& rot); - inline void setRotation(const F32 x, const F32 y, const F32 z); - inline void setRotation(const F32 x, const F32 y, const F32 z, const F32 s); - - // Above functions must be inline for speed, but also - // need to emit warnings. LL_WARNS() causes inline LLError::CallSite - // static objects that make more work for the linker. - // Avoid inline LL_WARNS() by calling this function. - void warn(const char* const msg); - - void setChanged(const U32 bits) { mChanged |= bits; } - bool isChanged() const { return mChanged; } - bool isChanged(const U32 bits) const { return mChanged & bits; } - void clearChanged() { mChanged = 0; } - void clearChanged(U32 bits) { mChanged &= ~bits; } - - void setScaleChildOffset(bool scale) { mScaleChildOffset = scale; } - bool getScaleChildOffset() { return mScaleChildOffset; } - - LLXform* getParent() const { return mParent; } - LLXform* getRoot() const; - virtual bool isRoot() const; - virtual bool isRootEdit() const; - - const LLVector3& getPosition() const { return mPosition; } - const LLVector3& getScale() const { return mScale; } - const LLQuaternion& getRotation() const { return mRotation; } - const LLVector3& getPositionW() const { return mWorldPosition; } - const LLQuaternion& getWorldRotation() const { return mWorldRotation; } - const LLVector3& getWorldPosition() const { return mWorldPosition; } + typedef enum e_changed_flags + { + UNCHANGED = 0x00, + TRANSLATED = 0x01, + ROTATED = 0x02, + SCALED = 0x04, + SHIFTED = 0x08, + GEOMETRY = 0x10, + TEXTURE = 0x20, + MOVED = TRANSLATED|ROTATED|SCALED, + SILHOUETTE = 0x40, + ALL_CHANGED = 0x7f + }EChangedFlags; + + void init() + { + mParent = NULL; + mChanged = UNCHANGED; + mPosition.setVec(0,0,0); + mRotation.loadIdentity(); + mScale. setVec(1,1,1); + mWorldPosition.clearVec(); + mWorldRotation.loadIdentity(); + mScaleChildOffset = false; + } + + LLXform(); + virtual ~LLXform(); + + void getLocalMat4(LLMatrix4 &mat) const { mat.initAll(mScale, mRotation, mPosition); } + + inline bool setParent(LLXform *parent); + + inline void setPosition(const LLVector3& pos); + inline void setPosition(const F32 x, const F32 y, const F32 z); + inline void setPositionX(const F32 x); + inline void setPositionY(const F32 y); + inline void setPositionZ(const F32 z); + inline void addPosition(const LLVector3& pos); + + + inline void setScale(const LLVector3& scale); + inline void setScale(const F32 x, const F32 y, const F32 z); + inline void setRotation(const LLQuaternion& rot); + inline void setRotation(const F32 x, const F32 y, const F32 z); + inline void setRotation(const F32 x, const F32 y, const F32 z, const F32 s); + + // Above functions must be inline for speed, but also + // need to emit warnings. LL_WARNS() causes inline LLError::CallSite + // static objects that make more work for the linker. + // Avoid inline LL_WARNS() by calling this function. + void warn(const char* const msg); + + void setChanged(const U32 bits) { mChanged |= bits; } + bool isChanged() const { return mChanged; } + bool isChanged(const U32 bits) const { return mChanged & bits; } + void clearChanged() { mChanged = 0; } + void clearChanged(U32 bits) { mChanged &= ~bits; } + + void setScaleChildOffset(bool scale) { mScaleChildOffset = scale; } + bool getScaleChildOffset() { return mScaleChildOffset; } + + LLXform* getParent() const { return mParent; } + LLXform* getRoot() const; + virtual bool isRoot() const; + virtual bool isRootEdit() const; + + const LLVector3& getPosition() const { return mPosition; } + const LLVector3& getScale() const { return mScale; } + const LLQuaternion& getRotation() const { return mRotation; } + const LLVector3& getPositionW() const { return mWorldPosition; } + const LLQuaternion& getWorldRotation() const { return mWorldRotation; } + const LLVector3& getWorldPosition() const { return mWorldPosition; } }; class LLXformMatrix : public LLXform { public: - LLXformMatrix() : LLXform() {}; - virtual ~LLXformMatrix(); + LLXformMatrix() : LLXform() {}; + virtual ~LLXformMatrix(); - const LLMatrix4& getWorldMatrix() const { return mWorldMatrix; } - void setWorldMatrix (const LLMatrix4& mat) { mWorldMatrix = mat; } + const LLMatrix4& getWorldMatrix() const { return mWorldMatrix; } + void setWorldMatrix (const LLMatrix4& mat) { mWorldMatrix = mat; } - void init() - { - mWorldMatrix.setIdentity(); - mMin.clearVec(); - mMax.clearVec(); + void init() + { + mWorldMatrix.setIdentity(); + mMin.clearVec(); + mMax.clearVec(); - LLXform::init(); - } + LLXform::init(); + } - void update(); - void updateMatrix(bool update_bounds = true); - void getMinMax(LLVector3& min,LLVector3& max) const; + void update(); + void updateMatrix(bool update_bounds = true); + void getMinMax(LLVector3& min,LLVector3& max) const; protected: - LLMatrix4 mWorldMatrix; - LLVector3 mMin; - LLVector3 mMax; + LLMatrix4 mWorldMatrix; + LLVector3 mMin; + LLVector3 mMax; }; bool LLXform::setParent(LLXform* parent) { - // Validate and make sure we're not creating a loop - if (parent == mParent) - { - return true; - } - if (parent) - { - LLXform *cur_par = parent->mParent; - while (cur_par) - { - if (cur_par == this) - { - //warn("LLXform::setParent Creating loop when setting parent!"); - return false; - } - cur_par = cur_par->mParent; - } - } - mParent = parent; - return true; + // Validate and make sure we're not creating a loop + if (parent == mParent) + { + return true; + } + if (parent) + { + LLXform *cur_par = parent->mParent; + while (cur_par) + { + if (cur_par == this) + { + //warn("LLXform::setParent Creating loop when setting parent!"); + return false; + } + cur_par = cur_par->mParent; + } + } + mParent = parent; + return true; } -void LLXform::setPosition(const LLVector3& pos) +void LLXform::setPosition(const LLVector3& pos) { - setChanged(TRANSLATED); - if (pos.isFinite()) - mPosition = pos; - else - { - mPosition.clearVec(); - warn("Non Finite in LLXform::setPosition(LLVector3)"); - } + setChanged(TRANSLATED); + if (pos.isFinite()) + mPosition = pos; + else + { + mPosition.clearVec(); + warn("Non Finite in LLXform::setPosition(LLVector3)"); + } } void LLXform::setPosition(const F32 x, const F32 y, const F32 z) { - setChanged(TRANSLATED); - if (llfinite(x) && llfinite(y) && llfinite(z)) - mPosition.setVec(x,y,z); - else - { - mPosition.clearVec(); - warn("Non Finite in LLXform::setPosition(F32,F32,F32)"); - } + setChanged(TRANSLATED); + if (llfinite(x) && llfinite(y) && llfinite(z)) + mPosition.setVec(x,y,z); + else + { + mPosition.clearVec(); + warn("Non Finite in LLXform::setPosition(F32,F32,F32)"); + } } void LLXform::setPositionX(const F32 x) -{ - setChanged(TRANSLATED); - if (llfinite(x)) - mPosition.mV[VX] = x; - else - { - mPosition.mV[VX] = 0.f; - warn("Non Finite in LLXform::setPositionX"); - } +{ + setChanged(TRANSLATED); + if (llfinite(x)) + mPosition.mV[VX] = x; + else + { + mPosition.mV[VX] = 0.f; + warn("Non Finite in LLXform::setPositionX"); + } } void LLXform::setPositionY(const F32 y) -{ - setChanged(TRANSLATED); - if (llfinite(y)) - mPosition.mV[VY] = y; - else - { - mPosition.mV[VY] = 0.f; - warn("Non Finite in LLXform::setPositionY"); - } +{ + setChanged(TRANSLATED); + if (llfinite(y)) + mPosition.mV[VY] = y; + else + { + mPosition.mV[VY] = 0.f; + warn("Non Finite in LLXform::setPositionY"); + } } void LLXform::setPositionZ(const F32 z) -{ - setChanged(TRANSLATED); - if (llfinite(z)) - mPosition.mV[VZ] = z; - else - { - mPosition.mV[VZ] = 0.f; - warn("Non Finite in LLXform::setPositionZ"); - } +{ + setChanged(TRANSLATED); + if (llfinite(z)) + mPosition.mV[VZ] = z; + else + { + mPosition.mV[VZ] = 0.f; + warn("Non Finite in LLXform::setPositionZ"); + } } void LLXform::addPosition(const LLVector3& pos) -{ - setChanged(TRANSLATED); - if (pos.isFinite()) - mPosition += pos; - else - warn("Non Finite in LLXform::addPosition"); +{ + setChanged(TRANSLATED); + if (pos.isFinite()) + mPosition += pos; + else + warn("Non Finite in LLXform::addPosition"); } void LLXform::setScale(const LLVector3& scale) -{ - setChanged(SCALED); - if (scale.isFinite()) - mScale = scale; - else - { - mScale.setVec(1.f, 1.f, 1.f); - warn("Non Finite in LLXform::setScale"); - } +{ + setChanged(SCALED); + if (scale.isFinite()) + mScale = scale; + else + { + mScale.setVec(1.f, 1.f, 1.f); + warn("Non Finite in LLXform::setScale"); + } } void LLXform::setScale(const F32 x, const F32 y, const F32 z) -{ - setChanged(SCALED); - if (llfinite(x) && llfinite(y) && llfinite(z)) - mScale.setVec(x,y,z); - else - { - mScale.setVec(1.f, 1.f, 1.f); - warn("Non Finite in LLXform::setScale"); - } +{ + setChanged(SCALED); + if (llfinite(x) && llfinite(y) && llfinite(z)) + mScale.setVec(x,y,z); + else + { + mScale.setVec(1.f, 1.f, 1.f); + warn("Non Finite in LLXform::setScale"); + } } void LLXform::setRotation(const LLQuaternion& rot) -{ - setChanged(ROTATED); - if (rot.isFinite()) - mRotation = rot; - else - { - mRotation.loadIdentity(); - warn("Non Finite in LLXform::setRotation"); - } +{ + setChanged(ROTATED); + if (rot.isFinite()) + mRotation = rot; + else + { + mRotation.loadIdentity(); + warn("Non Finite in LLXform::setRotation"); + } } -void LLXform::setRotation(const F32 x, const F32 y, const F32 z) -{ - setChanged(ROTATED); - if (llfinite(x) && llfinite(y) && llfinite(z)) - { - mRotation.setQuat(x,y,z); - } - else - { - mRotation.loadIdentity(); - warn("Non Finite in LLXform::setRotation"); - } +void LLXform::setRotation(const F32 x, const F32 y, const F32 z) +{ + setChanged(ROTATED); + if (llfinite(x) && llfinite(y) && llfinite(z)) + { + mRotation.setQuat(x,y,z); + } + else + { + mRotation.loadIdentity(); + warn("Non Finite in LLXform::setRotation"); + } } -void LLXform::setRotation(const F32 x, const F32 y, const F32 z, const F32 s) -{ - setChanged(ROTATED); - if (llfinite(x) && llfinite(y) && llfinite(z) && llfinite(s)) - { - mRotation.mQ[VX] = x; mRotation.mQ[VY] = y; mRotation.mQ[VZ] = z; mRotation.mQ[VS] = s; - } - else - { - mRotation.loadIdentity(); - warn("Non Finite in LLXform::setRotation"); - } +void LLXform::setRotation(const F32 x, const F32 y, const F32 z, const F32 s) +{ + setChanged(ROTATED); + if (llfinite(x) && llfinite(y) && llfinite(z) && llfinite(s)) + { + mRotation.mQ[VX] = x; mRotation.mQ[VY] = y; mRotation.mQ[VZ] = z; mRotation.mQ[VS] = s; + } + else + { + mRotation.loadIdentity(); + warn("Non Finite in LLXform::setRotation"); + } } #endif |