Files
SingularityViewer/indra/llmath/xform.h
Lirusaito 6e3f404a1c Rip out old workarounds, hacks and macros for newer C++ features not being supported back in the day.
Adds LL_COMPILE_TIME_MESSAGE support to Linux.

llfinite -> std::isfinite
llisnan -> std::isnan
vector_shrink_to_fit -> vector.shrink_to_fit
2016-02-14 17:37:10 -05:00

318 lines
7.8 KiB
C++

/**
* @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$
*/
#ifndef LL_XFORM_H
#define LL_XFORM_H
#include "v3math.h"
#include "m4math.h"
#include "llmatrix4a.h"
#include "llquaternion.h"
const F32 MAX_OBJECT_Z = 4096.f; // should match REGION_HEIGHT_METERS, Pre-havok4: 768.f
const F32 MIN_OBJECT_Z = -256.f;
const F32 DEFAULT_MAX_PRIM_SCALE = 256.f;
const F32 DEFAULT_MAX_PRIM_SCALE_NO_MESH = DEFAULT_MAX_PRIM_SCALE;
//const F32 MIN_PRIM_SCALE = 0.01f;
const 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;
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; }
};
LL_ALIGN_PREFIX(16)
class LLXformMatrix : public LLXform
{
public:
LLXformMatrix() : LLXform() {};
virtual ~LLXformMatrix();
const LLMatrix4a& getWorldMatrix() const { return mWorldMatrix; }
void setWorldMatrix (const LLMatrix4a& mat) { mWorldMatrix = mat; }
void init()
{
mWorldMatrix.setIdentity();
mMin.clear();
mMax.clear();
LLXform::init();
}
void update();
void updateMatrix(BOOL update_bounds = TRUE);
void getMinMax(LLVector3& min,LLVector3& max) const;
protected:
LL_ALIGN_16(LLMatrix4a mWorldMatrix);
LL_ALIGN_16(LLVector4a mMin);
LL_ALIGN_16(LLVector4a mMax);
} LL_ALIGN_POSTFIX(16);
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;
}
void LLXform::setPosition(const LLVector3& pos)
{
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 (std::isfinite(x) && std::isfinite(y) && std::isfinite(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 (std::isfinite(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 (std::isfinite(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 (std::isfinite(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");
}
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");
}
}
void LLXform::setScale(const F32 x, const F32 y, const F32 z)
{
setChanged(SCALED);
if (std::isfinite(x) && std::isfinite(y) && std::isfinite(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");
}
}
void LLXform::setRotation(const F32 x, const F32 y, const F32 z)
{
setChanged(ROTATED);
if (std::isfinite(x) && std::isfinite(y) && std::isfinite(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 (std::isfinite(x) && std::isfinite(y) && std::isfinite(z) && std::isfinite(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