llmath and llcommon updates. Marginal.

This commit is contained in:
Shyotl
2011-05-18 14:36:05 -05:00
parent 62e3aa10c1
commit 5f6fc78706
18 changed files with 494 additions and 118 deletions

View File

@@ -242,5 +242,13 @@ inline LLDATATYPE llclampb(const LLDATATYPE& a)
return llmin(llmax(a, (LLDATATYPE)0), (LLDATATYPE)255);
}
template <class LLDATATYPE>
inline void llswap(LLDATATYPE& lhs, LLDATATYPE& rhs)
{
LLDATATYPE tmp = lhs;
lhs = rhs;
rhs = tmp;
}
#endif // LL_LLDEFS_H

View File

@@ -108,9 +108,8 @@ public:
// methods to acquire finalized result
void raw_digest(unsigned char *array) const; // provide 16-byte array for binary data
void hex_digest(char *string) const; // provide 33-byte array for ascii-hex string
friend std::ostream& operator<< (std::ostream&, LLMD5 context);
friend LL_COMMON_API std::ostream& operator<< (std::ostream&, LLMD5 context);
private:

View File

@@ -67,6 +67,10 @@ LLCamera::LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_p
setView(vertical_fov_rads);
}
LLCamera::~LLCamera()
{
}
// ---------------- LLCamera::getFoo() member functions ----------------
@@ -88,11 +92,11 @@ F32 LLCamera::getMaxView() const
// ---------------- LLCamera::setFoo() member functions ----------------
void LLCamera::setUserClipPlane(LLPlane plane)
void LLCamera::setUserClipPlane(LLPlane& plane)
{
mPlaneCount = 7;
mAgentPlanes[6].p = plane;
mAgentPlanes[6].mask = calcPlaneMask(plane);
mAgentPlanes[6] = plane;
mPlaneMask[6] = plane.calcPlaneMask();
}
void LLCamera::disableUserClipPlane()
@@ -247,12 +251,12 @@ S32 LLCamera::AABBInFrustum(const LLVector3 &center, const LLVector3& radius)
{
for (U32 i = 0; i < mPlaneCount; i++)
{
mask = mAgentPlanes[i].mask;
mask = mPlaneMask[i];
if (mask == 0xff)
{
continue;
}
LLPlane p = mAgentPlanes[i].p;
LLPlane p = mAgentPlanes[i];
LLVector3 n = LLVector3(p);
float d = p.mV[3];
LLVector3 rscale = radius.scaledVec(scaler[mask]);
@@ -299,12 +303,12 @@ S32 LLCamera::AABBInFrustumNoFarClip(const LLVector3 &center, const LLVector3& r
continue;
}
mask = mAgentPlanes[i].mask;
mask = mPlaneMask[i];
if (mask == 0xff)
{
continue;
}
LLPlane p = mAgentPlanes[i].p;
LLPlane p = mAgentPlanes[i];
LLVector3 n = LLVector3(p);
float d = p.mV[3];
LLVector3 rscale = radius.scaledVec(scaler[mask]);
@@ -444,28 +448,22 @@ int LLCamera::sphereInFrustumOld(const LLVector3 &sphere_center, const F32 radiu
int LLCamera::sphereInFrustum(const LLVector3 &sphere_center, const F32 radius) const
{
// Returns 1 if sphere is in frustum, 0 if not.
int res = 2;
bool res = false;
for (int i = 0; i < 6; i++)
{
if (mAgentPlanes[i].mask == 0xff)
if (mPlaneMask[i] != 0xff)
{
continue;
}
float d = mAgentPlanes[i].dist(sphere_center);
float d = mAgentPlanes[i].p.dist(sphere_center);
if (d > radius)
{
return 0;
}
if (d > -radius)
{
res = 1;
if (d > radius)
{
return 0;
}
res = res || (d > -radius);
}
}
return res;
return res?1:2;
}
@@ -617,25 +615,6 @@ LLPlane planeFromPoints(LLVector3 p1, LLVector3 p2, LLVector3 p3)
return LLPlane(p1, n);
}
U8 LLCamera::calcPlaneMask(const LLPlane& plane)
{
U8 mask = 0;
if (plane.mV[0] >= 0)
{
mask |= 1;
}
if (plane.mV[1] >= 0)
{
mask |= 2;
}
if (plane.mV[2] >= 0)
{
mask |= 4;
}
return mask;
}
void LLCamera::ignoreAgentFrustumPlane(S32 idx)
{
@@ -644,8 +623,8 @@ void LLCamera::ignoreAgentFrustumPlane(S32 idx)
return;
}
mAgentPlanes[idx].mask = 0xff;
mAgentPlanes[idx].p.clearVec();
mPlaneMask[idx] = 0xff;
mAgentPlanes[idx].clear();
}
void LLCamera::calcAgentFrustumPlanes(LLVector3* frust)
@@ -662,27 +641,27 @@ void LLCamera::calcAgentFrustumPlanes(LLVector3* frust)
//order of planes is important, keep most likely to fail in the front of the list
//near - frust[0], frust[1], frust[2]
mAgentPlanes[2].p = planeFromPoints(frust[0], frust[1], frust[2]);
mAgentPlanes[2] = planeFromPoints(frust[0], frust[1], frust[2]);
//far
mAgentPlanes[5].p = planeFromPoints(frust[5], frust[4], frust[6]);
mAgentPlanes[5] = planeFromPoints(frust[5], frust[4], frust[6]);
//left
mAgentPlanes[0].p = planeFromPoints(frust[4], frust[0], frust[7]);
mAgentPlanes[0] = planeFromPoints(frust[4], frust[0], frust[7]);
//right
mAgentPlanes[1].p = planeFromPoints(frust[1], frust[5], frust[6]);
mAgentPlanes[1] = planeFromPoints(frust[1], frust[5], frust[6]);
//top
mAgentPlanes[4].p = planeFromPoints(frust[3], frust[2], frust[6]);
mAgentPlanes[4] = planeFromPoints(frust[3], frust[2], frust[6]);
//bottom
mAgentPlanes[3].p = planeFromPoints(frust[1], frust[0], frust[4]);
mAgentPlanes[3] = planeFromPoints(frust[1], frust[0], frust[4]);
//cache plane octant facing mask for use in AABBInFrustum
for (U32 i = 0; i < mPlaneCount; i++)
{
mAgentPlanes[i].mask = calcPlaneMask(mAgentPlanes[i].p);
mPlaneMask[i] = mAgentPlanes[i].calcPlaneMask();
}
}

View File

@@ -70,6 +70,12 @@ class LLCamera
: public LLCoordFrame
{
public:
LLCamera(const LLCamera& rhs)
{
*this = rhs;
}
enum {
PLANE_LEFT = 0,
PLANE_RIGHT = 1,
@@ -107,6 +113,9 @@ public:
};
private:
LLPlane mAgentPlanes[7]; //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP
U8 mPlaneMask[8]; // 8 for alignment
F32 mView; // angle between top and bottom frustum planes in radians.
F32 mAspect; // width/height
S32 mViewHeightInPixels; // for ViewHeightInPixels() only
@@ -120,30 +129,22 @@ private:
LLPlane mWorldPlanes[PLANE_NUM];
LLPlane mHorizPlanes[HORIZ_PLANE_NUM];
struct frustum_plane
{
frustum_plane() : mask(0) {}
LLPlane p;
U8 mask;
};
frustum_plane mAgentPlanes[7]; //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP
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[8]; //8 corners of 6-plane frustum
F32 mFrustumCornerDist; //distance to corner of frustum against far clip plane
LLPlane getAgentPlane(U32 idx) { return mAgentPlanes[idx].p; }
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(){} // no-op virtual destructor
virtual ~LLCamera();
void setUserClipPlane(LLPlane plane);
void setUserClipPlane(LLPlane& plane);
void disableUserClipPlane();
U8 calcPlaneMask(const LLPlane& plane);
virtual void setView(F32 vertical_fov_rads);
void setViewHeightInPixels(S32 height);
void setAspect(F32 new_aspect);

View File

@@ -384,11 +384,14 @@ inline F32 snap_to_sig_figs(F32 foo, S32 sig_figs)
bar *= 10.f;
}
foo = (F32)llround(foo * bar);
//F32 new_foo = (F32)llround(foo * bar);
// the llround() implementation sucks. Don't us it.
// shift back
foo /= bar;
return foo;
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;
}
inline F32 lerp(F32 a, F32 b, F32 u)
@@ -522,4 +525,41 @@ inline F32 llgaussian(F32 x, F32 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;
}
VEC_TYPE Q1 = data[data.size()/4];
VEC_TYPE Q3 = data[data.size()-data.size()/4-1];
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++;
}
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 (i > 0)
{
data.erase(data.begin(), data.begin()+i);
}
}
#endif

View File

@@ -73,6 +73,13 @@ public:
virtual void visit(const LLOctreeNode<T>* branch) = 0;
};
template <class T>
class LLOctreeTravelerDepthFirst : public LLOctreeTraveler<T>
{
public:
virtual void traverse(const LLOctreeNode<T>* node);
};
template <class T>
class LLOctreeNode : public LLTreeNode<T>
{
@@ -124,11 +131,10 @@ public:
inline void setParent(BaseType* parent) { mParent = (oct_node*) parent; }
inline const LLVector3d& getCenter() const { return mCenter; }
inline const LLVector3d& getSize() const { return mSize; }
inline void setCenter(LLVector3d center) { mCenter = center; }
inline void setSize(LLVector3d size) { mSize = size; }
inline oct_node* getNodeAt(T* data) { return getNodeAt(data->getPositionGroup(), data->getBinRadius()); }
inline U8 getOctant() const { return mOctant; }
inline void setOctant(U8 octant) { mOctant = octant; }
inline void setCenter(const LLVector3d center) { mCenter = center; }
inline void setSize(const LLVector3d 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(); }
@@ -197,17 +203,17 @@ public:
return contains(xform->getBinRadius());
}
bool contains(F64 radius)
bool contains(F32 radius)
{
if (mParent == NULL)
{ //root node contains nothing
return false;
}
F64 size = mSize.mdV[0];
F64 p_size = size * 2.0;
F32 size = mSize[0];
F32 p_size = size * 2.f;
return (radius <= 0.001 && size <= 0.001) ||
return (radius <= 0.001f && size <= 0.001f) ||
(radius <= p_size && radius > size);
}
@@ -243,7 +249,30 @@ public:
void accept(tree_traveler* visitor) const { visitor->visit(this); }
void accept(oct_traveler* visitor) const { visitor->visit(this); }
oct_node* getNodeAt(const LLVector3d& pos, const F64& rad)
void validateChildMap()
{
for (U32 i = 0; i < 8; i++)
{
U8 idx = mChildMap[i];
if (idx != 255)
{
LLOctreeNode<T>* child = mChild[idx];
if (child->getOctant() != i)
{
llerrs << "Invalid child map, bad octant data." << llendl;
}
if (getOctant(child->getCenter()) != child->getOctant())
{
llerrs << "Invalid child octant compared to position data." << llendl;
}
}
}
}
oct_node* getNodeAt(const LLVector3d& pos, const F32& rad)
{
LLOctreeNode<T>* node = this;
@@ -251,24 +280,18 @@ public:
{
//do a quick search by octant
U8 octant = node->getOctant(pos.mdV);
BOOL keep_going = TRUE;
//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
while (keep_going && node->getSize().mdV[0] >= rad)
U8 next_node = node->mChildMap[octant];
while (next_node != 255 && node->getSize()[0] >= rad)
{
keep_going = FALSE;
for (U32 i = 0; i < node->getChildCount() && !keep_going; i++)
{
if (node->getChild(i)->getOctant() == octant)
{
node = node->getChild(i);
octant = node->getOctant(pos.mdV);
keep_going = TRUE;
}
}
node = node->getChild(next_node);
octant = node->getOctant(pos.mdV);
next_node = node->mChildMap[octant];
}
}
else if (!node->contains(rad) && node->getParent())
@@ -444,6 +467,9 @@ public:
void clearChildren()
{
mChild.clear();
U32* foo = (U32*) mChildMap;
foo[0] = foo[1] = 0xFFFFFFFF;
}
void validate()
@@ -477,6 +503,12 @@ public:
void addChild(oct_node* child, BOOL silent = FALSE)
{
#if LL_OCTREE_PARANOIA_CHECK
if (child->getSize() == getSize())
{
OCT_ERRS << "Child size is same as parent size!" << llendl;
}
for (U32 i = 0; i < getChildCount(); i++)
{
if(mChild[i]->getSize() != child->getSize())
@@ -495,6 +527,8 @@ public:
}
#endif
mChildMap[child->getOctant()] = (U8) mChild.size();
mChild.push_back(child);
child->setParent(this);
@@ -508,7 +542,7 @@ public:
}
}
void removeChild(U8 index, BOOL destroy = FALSE)
void removeChild(S32 index, BOOL destroy = FALSE)
{
for (U32 i = 0; i < this->getListenerCount(); i++)
{
@@ -516,6 +550,8 @@ public:
listener->handleChildRemoval(this, getChild(index));
}
if (destroy)
{
mChild[index]->destroy();
@@ -523,6 +559,15 @@ public:
}
mChild.erase(mChild.begin() + index);
//rebuild child map
U32* foo = (U32*) mChildMap;
foo[0] = foo[1] = 0xFFFFFFFF;
for (U32 i = 0; i < mChild.size(); ++i)
{
mChildMap[mChild[i]->getOctant()] = i;
}
checkAlive();
}
@@ -553,14 +598,27 @@ public:
}
protected:
child_list mChild;
element_list mData;
oct_node* mParent;
typedef enum
{
CENTER = 0,
SIZE = 1,
MAX = 2,
MIN = 3
} eDName;
LLVector3d mCenter;
LLVector3d mSize;
LLVector3d mMax;
LLVector3d mMin;
oct_node* mParent;
U8 mOctant;
child_list mChild;
U8 mChildMap[8];
element_list mData;
};
//just like a regular node, except it might expand on insert and compress on balance
@@ -571,8 +629,8 @@ public:
typedef LLOctreeNode<T> BaseType;
typedef LLOctreeNode<T> oct_node;
LLOctreeRoot( LLVector3d center,
LLVector3d size,
LLOctreeRoot( const LLVector3d &center,
const LLVector3d &size,
BaseType* parent)
: BaseType(center, size, parent)
{
@@ -604,6 +662,8 @@ public:
//destroy child
child->clearChildren();
delete child;
return false;
}
return true;
@@ -700,7 +760,6 @@ public:
}
};
//========================
// LLOctreeTraveler
//========================
@@ -714,4 +773,14 @@ void LLOctreeTraveler<T>::traverse(const LLOctreeNode<T>* node)
}
}
template <class T>
void LLOctreeTravelerDepthFirst<T>::traverse(const LLOctreeNode<T>* node)
{
for (U32 i = 0; i < node->getChildCount(); i++)
{
traverse(node->getChild(i));
}
node->accept(this);
}
#endif

View File

@@ -48,13 +48,13 @@ public:
LLPlane() {}; // no default constructor
LLPlane(const LLVector3 &p0, F32 d) { setVec(p0, d); }
LLPlane(const LLVector3 &p0, const LLVector3 &n) { setVec(p0, n); }
void setVec(const LLVector3 &p0, F32 d) { LLVector4::setVec(p0[0], p0[1], p0[2], d); }
void setVec(const LLVector3 &p0, const LLVector3 &n)
inline void setVec(const LLVector3 &p0, F32 d) { LLVector4::setVec(p0[0], p0[1], p0[2], d); }
inline void setVec(const LLVector3 &p0, const LLVector3 &n)
{
F32 d = -(p0 * n);
setVec(n, d);
}
void setVec(const LLVector3 &p0, const LLVector3 &p1, const LLVector3 &p2)
inline void setVec(const LLVector3 &p0, const LLVector3 &p1, const LLVector3 &p2)
{
LLVector3 u, v, w;
u = p1 - p0;
@@ -64,8 +64,39 @@ public:
F32 d = -(w * p0);
setVec(w, d);
}
LLPlane& operator=(const LLVector4& v2) { LLVector4::setVec(v2[0],v2[1],v2[2],v2[3]); return *this;}
inline LLPlane& operator=(const LLVector4& v2) { LLVector4::setVec(v2[0],v2[1],v2[2],v2[3]); return *this;}
inline void set(const LLPlane& p2) { LLVector4::setVec(p2); }
//
F32 dist(const LLVector3 &v2) const { return mV[0]*v2[0] + mV[1]*v2[1] + mV[2]*v2[2] + mV[3]; }
// reset the vector to 0, 0, 0, 1
inline void clear() { LLVector4::setVec(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()
{
U8 mask = 0;
if (mV[0] >= 0)
{
mask |= 1;
}
if (mV[1] >= 0)
{
mask |= 2;
}
if (mV[2] >= 0)
{
mask |= 4;
}
return mask;
}
};

View File

@@ -32,9 +32,10 @@
#include "linden_common.h"
#include "llmath.h" // for F_PI
#include "llquaternion.h"
#include "llmath.h" // for F_PI
//#include "vmath.h"
#include "v3math.h"
#include "v3dmath.h"

View File

@@ -33,7 +33,11 @@
#ifndef LLQUATERNION_H
#define LLQUATERNION_H
#include "llmath.h"
#include <iostream>
#ifndef LLMATH_H //enforce specific include order to avoid tangling inline dependencies
#error "Please include llmath.h first."
#endif
class LLVector4;
class LLVector3;

View File

@@ -103,27 +103,33 @@ BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLV
BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size)
{
float fAWdU[3];
LLVector3 dir;
LLVector3 diff;
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];
for (U32 i = 0; i < 3; i++)
{
dir.mV[i] = 0.5f * (end.mV[i] - start.mV[i]);
diff.mV[i] = (0.5f * (end.mV[i] + start.mV[i])) - center.mV[i];
fAWdU[i] = fabsf(dir.mV[i]);
if(fabsf(diff.mV[i])>size.mV[i] + fAWdU[i]) return false;
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.mV[1] * diff.mV[2] - dir.mV[2] * diff.mV[1]; if(fabsf(f)>size.mV[1]*fAWdU[2] + size.mV[2]*fAWdU[1]) return false;
f = dir.mV[2] * diff.mV[0] - dir.mV[0] * diff.mV[2]; if(fabsf(f)>size.mV[0]*fAWdU[2] + size.mV[2]*fAWdU[0]) return false;
f = dir.mV[0] * diff.mV[1] - dir.mV[1] * diff.mV[0]; if(fabsf(f)>size.mV[0]*fAWdU[1] + size.mV[1]*fAWdU[0]) return false;
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;
}
// 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.
@@ -1688,7 +1694,8 @@ LLVolume::LLVolume(const LLVolumeParams &params, const F32 detail, const BOOL ge
mGenerateSingleFace = generate_single_face;
generate();
if (mParams.getSculptID().isNull() && params.getSculptType() == LL_SCULPT_TYPE_NONE)
if (mParams.getSculptID().isNull() && mParams.getSculptType() == LL_SCULPT_TYPE_NONE)
{
createVolumeFaces();
}

View File

@@ -984,6 +984,7 @@ LLVector3 calc_binormal_from_triangle(
const LLVector3& pos2,
const LLVector2& tex2);
BOOL LLLineSegmentBoxIntersect(const F32* start, const F32* end, const F32* center, const F32* size);
BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size);
BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir,
F32* intersection_a, F32* intersection_b, F32* intersection_t, BOOL two_sided);

View File

@@ -221,8 +221,33 @@ const LLMatrix4& LLMatrix4::transpose()
F32 LLMatrix4::determinant() const
{
llerrs << "Not implemented!" << llendl;
return 0.f;
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.
@@ -428,6 +453,17 @@ const LLMatrix4& LLMatrix4::initRotTrans(const LLQuaternion &q, const LLVector
return (*this);
}
const LLMatrix4& LLMatrix4::initScale(const LLVector3 &scale)
{
setIdentity();
mMatrix[VX][VX] = scale.mV[VX];
mMatrix[VY][VY] = scale.mV[VY];
mMatrix[VZ][VZ] = scale.mV[VZ];
return (*this);
}
const LLMatrix4& LLMatrix4::initAll(const LLVector3 &scale, const LLQuaternion &q, const LLVector3 &pos)
{
F32 sx, sy, sz;
@@ -774,6 +810,23 @@ bool operator!=(const LLMatrix4 &a, const LLMatrix4 &b)
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];
}
}
}
return false;
}
const LLMatrix4& operator*=(LLMatrix4 &a, F32 k)
{
U32 i, j;
@@ -813,4 +866,54 @@ std::ostream& operator<<(std::ostream& s, const LLMatrix4 &a)
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];
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[12] = mMatrix[3][0];
ret[13] = mMatrix[3][1];
ret[14] = mMatrix[3][2];
ret[15] = mMatrix[3][3];
return ret;
}
void LLMatrix4::setValue(const LLSD& data)
{
mMatrix[0][0] = data[0].asReal();
mMatrix[0][1] = data[1].asReal();
mMatrix[0][2] = data[2].asReal();
mMatrix[0][3] = data[3].asReal();
mMatrix[1][0] = data[4].asReal();
mMatrix[1][1] = data[5].asReal();
mMatrix[1][2] = data[6].asReal();
mMatrix[1][3] = data[7].asReal();
mMatrix[2][0] = data[8].asReal();
mMatrix[2][1] = data[9].asReal();
mMatrix[2][2] = data[10].asReal();
mMatrix[2][3] = data[11].asReal();
mMatrix[3][0] = data[12].asReal();
mMatrix[3][1] = data[13].asReal();
mMatrix[3][2] = data[14].asReal();
mMatrix[3][3] = data[15].asReal();
}

View File

@@ -125,6 +125,8 @@ public:
~LLMatrix4(void); // Destructor
LLSD getValue() const;
void setValue(const LLSD&);
//////////////////////////////
//
@@ -138,6 +140,7 @@ public:
// various useful matrix functions
const LLMatrix4& setIdentity(); // Load identity matrix
bool isIdentity() const;
const LLMatrix4& setZero(); // Clears matrix to all zeros.
const LLMatrix4& initRotation(const F32 angle, const F32 x, const F32 y, const F32 z); // Calculate rotation matrix by rotating angle radians about (x, y, z)
@@ -159,6 +162,7 @@ public:
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& initScale(const LLVector3 &scale);
// Set all
const LLMatrix4& initAll(const LLVector3 &scale, const LLQuaternion &q, const LLVector3 &pos);
@@ -236,6 +240,7 @@ public:
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
@@ -269,6 +274,30 @@ inline const LLMatrix4& LLMatrix4::setIdentity()
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;
}
/*
inline LLMatrix4 operator*(const LLMatrix4 &a, const LLMatrix4 &b)

View File

@@ -115,3 +115,18 @@ LLVector2 lerp(const LLVector2 &a, const LLVector2 &b, F32 u)
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;
}
void LLVector2::setValue(LLSD& sd)
{
mV[0] = (F32) sd[0].asReal();
mV[1] = (F32) sd[1].asReal();
}

View File

@@ -66,6 +66,9 @@ class LLVector2
void set(const LLVector2 &vec); // Sets LLVector2 to vec
void set(const F32 *vec); // Sets LLVector2 to vec
LLSD getValue() const;
void setValue(LLSD& sd);
void setVec(F32 x, F32 y); // deprecated
void setVec(const LLVector2 &vec); // deprecated
void setVec(const F32 *vec); // deprecated

View File

@@ -140,6 +140,21 @@ BOOL LLVector3::clampLength( F32 length_limit )
return changed;
}
BOOL LLVector3::clamp(const LLVector3 &min_vec, const LLVector3 &max_vec)
{
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] > 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;
}
// Sets all values to absolute value of their original values
// Returns TRUE if data changed
@@ -197,6 +212,28 @@ const LLVector3& LLVector3::rotVec(const LLQuaternion &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;
}
const LLVector3& LLVector3::rotVec(F32 angle, const LLVector3 &vec)
{
if ( !vec.isExactlyZero() && angle )

View File

@@ -40,6 +40,7 @@
class LLVector2;
class LLVector4;
class LLMatrix3;
class LLMatrix4;
class LLVector3d;
class LLQuaternion;
@@ -75,6 +76,7 @@ class LLVector3
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
@@ -115,6 +117,7 @@ class LLVector3
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
@@ -162,6 +165,8 @@ F32 dist_vec(const LLVector3 &a, const LLVector3 &b); // Returns distance betwe
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 parallel_component(const LLVector3 &a, const LLVector3 &b); // Returns vector a projected on vector b (same as projected_vec)
LLVector3 orthogonal_component(const LLVector3 &a, const LLVector3 &b); // Returns component of vector a not parallel to vector b (same as projected_vec)
LLVector3 lerp(const LLVector3 &a, const LLVector3 &b, F32 u); // Returns a vector that is a linear interpolation between a and b
inline LLVector3::LLVector3(void)
@@ -496,6 +501,17 @@ inline LLVector3 projected_vec(const LLVector3 &a, const LLVector3 &b)
return project_axis * (a * project_axis);
}
inline LLVector3 parallel_component(const LLVector3 &a, const LLVector3 &b)
{
return projected_vec(a, b);
}
inline LLVector3 orthogonal_component(const LLVector3 &a, const LLVector3 &b)
{
return a - projected_vec(a, b);
}
inline LLVector3 lerp(const LLVector3 &a, const LLVector3 &b, F32 u)
{
return LLVector3(
@@ -529,6 +545,21 @@ inline void update_min_max(LLVector3& min, LLVector3& max, const LLVector3& pos)
}
}
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];
}
}
}
inline F32 angle_between(const LLVector3& a, const LLVector3& b)
{
LLVector3 an = a;

View File

@@ -114,6 +114,7 @@ class LLColor4
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
@@ -595,6 +596,23 @@ inline LLColor4 lerp(const LLColor4 &a, const LLColor4 &b, F32 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];
}
return mV[3] < rhs.mV[3];
}
void LLColor4::clamp()
{