diff options
Diffstat (limited to 'indra/llmath')
-rw-r--r-- | indra/llmath/llvolume.cpp | 506 | ||||
-rw-r--r-- | indra/llmath/llvolume.h | 34 | ||||
-rw-r--r-- | indra/llmath/llvolumemgr.cpp | 15 | ||||
-rw-r--r-- | indra/llmath/llvolumemgr.h | 1 | ||||
-rw-r--r-- | indra/llmath/m4math.cpp | 28 | ||||
-rw-r--r-- | indra/llmath/m4math.h | 2 | ||||
-rw-r--r-- | indra/llmath/v2math.cpp | 15 | ||||
-rw-r--r-- | indra/llmath/v2math.h | 3 |
8 files changed, 590 insertions, 14 deletions
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index df4c618ac1..de32070da1 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -46,6 +46,9 @@ #include "lldarray.h" #include "llvolume.h" #include "llstl.h" +#include "llsdserialize.h" +#include "zlib/zlib.h" + #define DEBUG_SILHOUETTE_BINORMALS 0 #define DEBUG_SILHOUETTE_NORMALS 0 // TomY: Use this to display normals using the silhouette @@ -1673,7 +1676,9 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mFaceMask = 0x0; mDetail = detail; mSculptLevel = -2; - + mIsTetrahedron = FALSE; + mLODScaleBias.setVec(1,1,1); + // set defaults if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE) { @@ -1688,7 +1693,8 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mGenerateSingleFace = generate_single_face; generate(); - if (mParams.getSculptID().isNull()) + + if (mParams.getSculptID().isNull() && params.getSculptType() == LL_SCULPT_TYPE_NONE) { createVolumeFaces(); } @@ -1839,6 +1845,427 @@ BOOL LLVolume::generate() return FALSE; } +bool LLVolumeFace::VertexData::operator<(const LLVolumeFace::VertexData& rhs)const +{ + const U8* l = (const U8*) this; + const U8* r = (const U8*) &rhs; + + for (U32 i = 0; i < sizeof(VertexData); ++i) + { + if (l[i] != r[i]) + { + return r[i] < l[i]; + } + } + + return false; +} + +bool LLVolumeFace::VertexData::operator==(const LLVolumeFace::VertexData& rhs)const +{ + const U8* l = (const U8*) this; + const U8* r = (const U8*) &rhs; + + for (U32 i = 0; i < sizeof(VertexData); ++i) + { + if (l[i] != r[i]) + { + return false; + } + } + + return true; +} + +bool LLVolumeFace::VertexData::compareNormal(const LLVolumeFace::VertexData& rhs, F32 angle_cutoff) const +{ + bool retval = false; + if (rhs.mPosition == mPosition && rhs.mTexCoord == mTexCoord) + { + F32 cur_angle = rhs.mNormal*mNormal; + + retval = cur_angle > angle_cutoff; + } + + return retval; +} + +BOOL LLVolume::createVolumeFacesFromFile(const std::string& file_name) +{ + std::ifstream is; + + is.open(file_name.c_str(), std::ifstream::in | std::ifstream::binary); + + BOOL success = createVolumeFacesFromStream(is); + + is.close(); + + return success; +} + +BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) +{ + mSculptLevel = -1; // default is an error occured + + LLSD header; + { + if (!LLSDSerialize::deserialize(header, is, 1024*1024*1024)) + { + llwarns << "Mesh header parse error. Not a valid mesh asset!" << llendl; + return FALSE; + } + } + + std::string nm[] = + { + "impostor", + "low_lod", + "medium_lod", + "high_lod" + }; + + S32 lod = llclamp((S32) mDetail, 0, 3); + + while (lod < 4 && + (header[nm[lod]]["offset"].asInteger() == -1 || + header[nm[lod]]["size"].asInteger() == 0 )) + { + ++lod; + } + + if (lod >= 4) + { + lod = llclamp((S32) mDetail, 0, 3); + + while (lod >= 0 && + (header[nm[lod]]["offset"].asInteger() == -1 || + header[nm[lod]]["size"].asInteger() == 0) ) + { + --lod; + } + + if (lod < 0) + { + llwarns << "Mesh header missing LOD offsets. Not a valid mesh asset!" << llendl; + return FALSE; + } + } + + is.seekg(header[nm[lod]]["offset"].asInteger(), std::ios_base::cur); + + return unpackVolumeFaces(is, header[nm[lod]]["size"].asInteger()); +} + +BOOL LLVolume::unpackVolumeFaces(std::istream& is, S32 size) +{ + U8* result = NULL; + U32 cur_size = 0; + + { + //input stream is now pointing at a zlib compressed block of LLSD + //decompress block + z_stream strm; + + const U32 CHUNK = 65536; + + U8 *in = new U8[size]; + is.read((char*) in, size); + + U8 out[CHUNK]; + + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = size; + strm.next_in = in; + + S32 ret = inflateInit(&strm); + + if (ret != Z_OK) + { + llerrs << "WTF?" << llendl; + } + + do + { + strm.avail_out = CHUNK; + strm.next_out = out; + ret = inflate(&strm, Z_NO_FLUSH); + if (ret == Z_STREAM_ERROR) + { + inflateEnd(&strm); + free(result); + delete [] in; + return FALSE; + } + + switch (ret) + { + case Z_NEED_DICT: + ret = Z_DATA_ERROR; + case Z_DATA_ERROR: + case Z_MEM_ERROR: + inflateEnd(&strm); + free(result); + delete [] in; + return FALSE; + break; + } + + U32 have = CHUNK-strm.avail_out; + + result = (U8*) realloc(result, cur_size + have); + memcpy(result+cur_size, out, have); + cur_size += have; + + } while (strm.avail_out == 0); + + inflateEnd(&strm); + delete [] in; + + if (ret != Z_STREAM_END) + { + free(result); + return FALSE; + } + } + + //result now points to the decompressed LLSD block + + LLSD mdl; + + { + std::string res_str((char*) result, cur_size); + std::istringstream istr(res_str); + + if (!LLSDSerialize::deserialize(mdl, istr, cur_size)) + { + llwarns << "not a valid mesh asset!" << llendl; + return FALSE; + } + } + + + free(result); + + + { + U32 face_count = mdl.size(); + + if (face_count == 0) + { + llerrs << "WTF?" << llendl; + } + + mVolumeFaces.resize(face_count); + + for (U32 i = 0; i < face_count; ++i) + { + LLSD::Binary pos = mdl[i]["Position"]; + LLSD::Binary norm = mdl[i]["Normal"]; + LLSD::Binary tc = mdl[i]["TexCoord0"]; + LLSD::Binary idx = mdl[i]["TriangleList"]; + + LLVolumeFace& face = mVolumeFaces[i]; + + face.mHasBinormals = FALSE; + + //copy out indices + face.mIndices.resize(idx.size()/2); + if (idx.empty() || face.mIndices.size() < 3) + { //why is there an empty index list? + llerrs <<"WTF?" << llendl; + continue; + } + + U16* indices = (U16*) &(idx[0]); + for (U32 j = 0; j < idx.size()/2; ++j) + { + face.mIndices[j] = indices[j]; + } + + //copy out vertices + U32 num_verts = pos.size()/(3*2); + face.mVertices.resize(num_verts); + + LLVector3 min_pos; + LLVector3 max_pos; + LLVector2 min_tc; + LLVector2 max_tc; + + min_pos.setValue(mdl[i]["PositionDomain"]["Min"]); + max_pos.setValue(mdl[i]["PositionDomain"]["Max"]); + min_tc.setValue(mdl[i]["TexCoord0Domain"]["Min"]); + max_tc.setValue(mdl[i]["TexCoord0Domain"]["Max"]); + + F32 scale = llclamp((F32) mdl[i]["Scale"].asReal(), 1.f, 10.f); + + LLVector3 pos_range = max_pos - min_pos; + LLVector2 tc_range = max_tc - min_tc; + + LLVector3& min = face.mExtents[0]; + LLVector3& max = face.mExtents[1]; + + min = max = LLVector3(0,0,0); + + for (U32 j = 0; j < num_verts; ++j) + { + U16* v = (U16*) &(pos[j*3*2]); + + face.mVertices[j].mPosition.setVec( + (F32) v[0] / 65535.f * pos_range.mV[0] + min_pos.mV[0], + (F32) v[1] / 65535.f * pos_range.mV[1] + min_pos.mV[1], + (F32) v[2] / 65535.f * pos_range.mV[2] + min_pos.mV[2]); + + face.mVertices[j].mPosition *= scale; + + if (j == 0) + { + min = max = face.mVertices[j].mPosition; + } + else + { + update_min_max(min,max,face.mVertices[j].mPosition); + } + + U16* n = (U16*) &(norm[j*3*2]); + + face.mVertices[j].mNormal.setVec( + (F32) n[0] / 65535.f * 2.f - 1.f, + (F32) n[1] / 65535.f * 2.f - 1.f, + (F32) n[2] / 65535.f * 2.f - 1.f); + + U16* t = (U16*) &(tc[j*2*2]); + + face.mVertices[j].mTexCoord.setVec( + (F32) t[0] / 65535.f * tc_range.mV[0] + min_tc.mV[0], + (F32) t[1] / 65535.f * tc_range.mV[1] + min_tc.mV[1]); + } + + } + } + + mSculptLevel = 0; // success! + return TRUE; +} + +void tetrahedron_set_normal(LLVolumeFace::VertexData* cv) +{ + LLVector3 nrm = (cv[1].mPosition-cv[0].mPosition)%(cv[2].mPosition-cv[0].mPosition); + + nrm.normVec(); + + cv[0].mNormal = nrm; + cv[1].mNormal = nrm; + cv[2].mNormal = nrm; +} + +BOOL LLVolume::isTetrahedron() +{ + return mIsTetrahedron; +} + +void LLVolume::makeTetrahedron() +{ + mVolumeFaces.clear(); + + LLVolumeFace face; + + F32 x = 0.25f; + LLVector3 p[] = + { //unit tetrahedron corners + LLVector3(x,x,x), + LLVector3(-x,-x,x), + LLVector3(-x,x,-x), + LLVector3(x,-x,-x) + }; + + face.mExtents[0].setVec(-x,-x,-x); + face.mExtents[1].setVec(x,x,x); + + LLVolumeFace::VertexData cv[3]; + + //set texture coordinates + cv[0].mTexCoord = LLVector2(0,0); + cv[1].mTexCoord = LLVector2(1,0); + cv[2].mTexCoord = LLVector2(0.5f, 0.5f*F_SQRT3); + + + //side 1 + cv[0].mPosition = p[1]; + cv[1].mPosition = p[0]; + cv[2].mPosition = p[2]; + + tetrahedron_set_normal(cv); + + face.mVertices.push_back(cv[0]); + face.mVertices.push_back(cv[1]); + face.mVertices.push_back(cv[2]); + + //side 2 + cv[0].mPosition = p[3]; + cv[1].mPosition = p[0]; + cv[2].mPosition = p[1]; + + tetrahedron_set_normal(cv); + + face.mVertices.push_back(cv[0]); + face.mVertices.push_back(cv[1]); + face.mVertices.push_back(cv[2]); + + //side 3 + cv[0].mPosition = p[3]; + cv[1].mPosition = p[1]; + cv[2].mPosition = p[2]; + + tetrahedron_set_normal(cv); + + face.mVertices.push_back(cv[0]); + face.mVertices.push_back(cv[1]); + face.mVertices.push_back(cv[2]); + + //side 4 + cv[0].mPosition = p[2]; + cv[1].mPosition = p[0]; + cv[2].mPosition = p[3]; + + tetrahedron_set_normal(cv); + + face.mVertices.push_back(cv[0]); + face.mVertices.push_back(cv[1]); + face.mVertices.push_back(cv[2]); + + //set index buffer + for (U32 i = 0; i < 12; i++) + { + face.mIndices.push_back(i); + } + + mVolumeFaces.push_back(face); + mSculptLevel = 0; + mIsTetrahedron = TRUE; +} + +void LLVolume::copyVolumeFaces(LLVolume* volume) +{ + mVolumeFaces = volume->mVolumeFaces; + mSculptLevel = 0; + mIsTetrahedron = FALSE; +} + + +S32 LLVolume::getNumFaces() const +{ + U8 sculpt_type = (mParams.getSculptType() & LL_SCULPT_TYPE_MASK); + + if (sculpt_type == LL_SCULPT_TYPE_MESH) + { + return LL_SCULPT_MESH_MAX_FACES; + } + + return (S32)mProfilep->mFaces.size(); +} + void LLVolume::createVolumeFaces() { @@ -1864,6 +2291,11 @@ void LLVolume::createVolumeFaces() LLProfile::Face& face = mProfilep->mFaces[i]; vf.mBeginS = face.mIndex; vf.mNumS = face.mCount; + if (vf.mNumS < 0) + { + llerrs << "Volume face corruption detected." << llendl; + } + vf.mBeginT = 0; vf.mNumT= getPath().mPath.size(); vf.mID = i; @@ -1907,6 +2339,10 @@ void LLVolume::createVolumeFaces() if (face.mFlat && vf.mNumS > 2) { //flat inner faces have to copy vert normals vf.mNumS = vf.mNumS*2; + if (vf.mNumS < 0) + { + llerrs << "Volume face corruption detected." << llendl; + } } } else @@ -2198,6 +2634,11 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, LLMemType m1(LLMemType::MTYPE_VOLUME); U8 sculpt_type = mParams.getSculptType(); + if (sculpt_type & LL_SCULPT_TYPE_MASK == LL_SCULPT_TYPE_MESH) + { + llerrs << "WTF?" << llendl; + } + BOOL data_is_empty = FALSE; if (sculpt_width == 0 || sculpt_height == 0 || sculpt_components < 3 || sculpt_data == NULL) @@ -2309,7 +2750,6 @@ bool LLVolumeParams::operator<(const LLVolumeParams ¶ms) const return mSculptID < params.mSculptID; } - return mSculptType < params.mSculptType; @@ -3367,6 +3807,20 @@ S32 LLVolume::getNumTriangleIndices() const return count; } + +S32 LLVolume::getNumTriangles() const +{ + U32 triangle_count = 0; + + for (S32 i = 0; i < getNumVolumeFaces(); ++i) + { + triangle_count += getVolumeFace(i).mIndices.size()/3; + } + + return triangle_count; +} + + //----------------------------------------------------------------------------- // generateSilhouetteVertices() //----------------------------------------------------------------------------- @@ -3379,22 +3833,29 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices, S32 face_mask) { LLMemType m1(LLMemType::MTYPE_VOLUME); - + vertices.clear(); normals.clear(); segments.clear(); + if (mParams.getSculptType() == LL_SCULPT_TYPE_MESH) + { + return; + } + S32 cur_index = 0; //for each face for (face_list_t::iterator iter = mVolumeFaces.begin(); iter != mVolumeFaces.end(); ++iter) { - const LLVolumeFace& face = *iter; + LLVolumeFace& face = *iter; - if (!(face_mask & (0x1 << cur_index++))) + if (!(face_mask & (0x1 << cur_index++)) || + face.mIndices.empty() || face.mEdge.empty()) { continue; } + if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) { } @@ -3594,6 +4055,8 @@ S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, 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++) { const LLVolumeFace &face = getVolumeFace((U32)i); @@ -4103,11 +4566,28 @@ BOOL LLVolumeParams::exportLegacyStream(std::ostream& output_stream) const return TRUE; } +LLSD LLVolumeParams::sculptAsLLSD() const +{ + LLSD sd = LLSD(); + sd["id"] = getSculptID(); + sd["type"] = getSculptType(); + + return sd; +} + +bool LLVolumeParams::sculptFromLLSD(LLSD& sd) +{ + 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; } @@ -4115,6 +4595,8 @@ bool LLVolumeParams::fromLLSD(LLSD& sd) { mPathParams.fromLLSD(sd["path"]); mProfileParams.fromLLSD(sd["profile"]); + sculptFromLLSD(sd["sculpt"]); + return true; } @@ -4157,6 +4639,12 @@ const F32 MIN_CONCAVE_PATH_WEDGE = 0.111111f; // 1/9 unity // 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(); @@ -5011,7 +5499,11 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) if (!partial_build) { mIndices.resize(num_indices); - mEdge.resize(num_indices); + + if (volume->getParams().getSculptType() != LL_SCULPT_TYPE_MESH) + { + mEdge.resize(num_indices); + } } else { diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 871b334452..e3ab648fe3 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -186,9 +186,13 @@ const U8 LL_SCULPT_TYPE_CYLINDER = 4; const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE | LL_SCULPT_TYPE_CYLINDER; +// need to change this (these) names +const U8 LL_SCULPT_TYPE_MESH = 5; + const U8 LL_SCULPT_FLAG_INVERT = 64; const U8 LL_SCULPT_FLAG_MIRROR = 128; +const S32 LL_SCULPT_MESH_MAX_FACES = 8; class LLProfileParams { @@ -575,6 +579,9 @@ public: 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); @@ -634,7 +641,6 @@ public: const F32& getSkew() const { return mPathParams.getSkew(); } const LLUUID& getSculptID() const { return mSculptID; } const U8& getSculptType() const { return mSculptType; } - BOOL isConvex() const; // 'begin' and 'end' should be in range [0, 1] (they will be clamped) @@ -798,7 +804,7 @@ public: BOOL create(LLVolume* volume, BOOL partial_build = FALSE); void createBinormals(); - + class VertexData { public: @@ -806,6 +812,10 @@ public: LLVector3 mNormal; LLVector3 mBinormal; LLVector2 mTexCoord; + + bool operator<(const VertexData& rhs) const; + bool operator==(const VertexData& rhs) const; + bool compareNormal(const VertexData& rhs, F32 angle_cutoff) const; }; enum @@ -851,8 +861,7 @@ class LLVolume : public LLRefCount { friend class LLVolumeLODGroup; -private: - LLVolume(const LLVolume&); // Don't implement +protected: ~LLVolume(); // use unref public: @@ -874,7 +883,7 @@ public: U8 getProfileType() const { return mParams.getProfileParams().getCurveType(); } U8 getPathType() const { return mParams.getPathParams().getCurveType(); } - S32 getNumFaces() const { return (S32)mProfilep->mFaces.size(); } + S32 getNumFaces() const; S32 getNumVolumeFaces() const { return mVolumeFaces.size(); } F32 getDetail() const { return mDetail; } const LLVolumeParams& getParams() const { return mParams; } @@ -896,12 +905,15 @@ public: BOOL isUnique() const { return mUnique; } S32 getSculptLevel() const { return mSculptLevel; } - + void setSculptLevel(S32 level) { mSculptLevel = level; } + S32 *getTriangleIndices(U32 &num_indices) const; // returns number of triangle indeces required for path/profile mesh S32 getNumTriangleIndices() const; + S32 getNumTriangles() const; + void generateSilhouetteVertices(std::vector<LLVector3> &vertices, std::vector<LLVector3> &normals, std::vector<S32> &segments, @@ -946,6 +958,8 @@ public: 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); + void copyVolumeFaces(LLVolume* volume); + private: void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type); F32 sculptGetSurfaceArea(); @@ -956,11 +970,19 @@ private: protected: BOOL generate(); void createVolumeFaces(); +public: + virtual BOOL createVolumeFacesFromFile(const std::string& file_name); + virtual BOOL createVolumeFacesFromStream(std::istream& is); + virtual BOOL unpackVolumeFaces(std::istream& is, S32 size); + + virtual void makeTetrahedron(); + virtual BOOL isTetrahedron(); protected: BOOL mUnique; F32 mDetail; S32 mSculptLevel; + BOOL mIsTetrahedron; LLVolumeParams mParams; LLPath *mPathp; diff --git a/indra/llmath/llvolumemgr.cpp b/indra/llmath/llvolumemgr.cpp index 53641fceab..419e0015ba 100644 --- a/indra/llmath/llvolumemgr.cpp +++ b/indra/llmath/llvolumemgr.cpp @@ -320,7 +320,7 @@ BOOL LLVolumeLODGroup::derefLOD(LLVolume *volumep) { llassert_always(mLODRefs[i] > 0); mLODRefs[i]--; -#if 1 // SJB: Possible opt: keep other lods around +#if 0 // SJB: Possible opt: keep other lods around if (!mLODRefs[i]) { mVolumeLODs[i] = NULL; @@ -375,6 +375,19 @@ F32 LLVolumeLODGroup::getVolumeScaleFromDetail(const S32 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; +} + F32 LLVolumeLODGroup::dump() { F32 usage = 0.f; diff --git a/indra/llmath/llvolumemgr.h b/indra/llmath/llvolumemgr.h index a78ea76a1a..f5dc4cd748 100644 --- a/indra/llmath/llvolumemgr.h +++ b/indra/llmath/llvolumemgr.h @@ -59,6 +59,7 @@ public: 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); diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp index d8e7b4aaf9..3700142982 100644 --- a/indra/llmath/m4math.cpp +++ b/indra/llmath/m4math.cpp @@ -428,6 +428,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 +785,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; diff --git a/indra/llmath/m4math.h b/indra/llmath/m4math.h index e74b7afe9b..6007b96bd9 100644 --- a/indra/llmath/m4math.h +++ b/indra/llmath/m4math.h @@ -159,6 +159,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 +237,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 diff --git a/indra/llmath/v2math.cpp b/indra/llmath/v2math.cpp index 555e1f92bb..220336e0c2 100644 --- a/indra/llmath/v2math.cpp +++ b/indra/llmath/v2math.cpp @@ -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(); +} + diff --git a/indra/llmath/v2math.h b/indra/llmath/v2math.h index 9fef8851cc..f9f1c024f2 100644 --- a/indra/llmath/v2math.h +++ b/indra/llmath/v2math.h @@ -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 |