diff options
Diffstat (limited to 'indra/llprimitive')
-rwxr-xr-x | indra/llprimitive/llmodel.cpp | 143 | ||||
-rwxr-xr-x | indra/llprimitive/llmodel.h | 43 |
2 files changed, 175 insertions, 11 deletions
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index 81420fadb7..595f9aa307 100755 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -1881,24 +1881,29 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos) void LLModel::setConvexHullDecomposition( const LLModel::convex_hull_decomposition& decomp) { - mConvexHullDecomp = decomp; + mPhysics.mHull = decomp; + mPhysics.mMesh.clear(); + updateHullCenters(); +} - mHullCenter.resize(mConvexHullDecomp.size()); +void LLModel::updateHullCenters() +{ + mHullCenter.resize(mPhysics.mHull.size()); mHullPoints = 0; mCenterOfHullCenters.clear(); - for (U32 i = 0; i < decomp.size(); ++i) + for (U32 i = 0; i < mPhysics.mHull.size(); ++i) { LLVector3 cur_center; - for (U32 j = 0; j < decomp[i].size(); ++j) + for (U32 j = 0; j < mPhysics.mHull[i].size(); ++j) { - cur_center += decomp[i][j]; + cur_center += mPhysics.mHull[i][j]; } mCenterOfHullCenters += cur_center; - cur_center *= 1.f/decomp[i].size(); + cur_center *= 1.f/mPhysics.mHull[i].size(); mHullCenter[i] = cur_center; - mHullPoints += decomp[i].size(); + mHullPoints += mPhysics.mHull[i].size(); } mCenterOfHullCenters *= 1.f / mHullPoints; @@ -1944,12 +1949,15 @@ bool LLModel::loadModel(std::istream& is) std::ios::pos_type cur_pos = is.tellg();
loadSkinInfo(header, is);
is.seekg(cur_pos);
+ }
+
+ if (lod == LLModel::LOD_PHYSICS)
+ {
+ std::ios::pos_type cur_pos = is.tellg();
loadDecomposition(header, is);
is.seekg(cur_pos);
}
-
-
is.seekg(header[nm[lod]]["offset"].asInteger(), std::ios_base::cur);
if (unpackVolumeFaces(is, header[nm[lod]]["size"].asInteger()))
@@ -2019,6 +2027,22 @@ bool LLModel::loadSkinInfo(LLSD& header, std::istream &is) bool LLModel::loadDecomposition(LLSD& header, std::istream& is) { + S32 offset = header["decomposition"]["offset"].asInteger(); + S32 size = header["decomposition"]["size"].asInteger(); + + if (offset >= 0 && size > 0) + { + is.seekg(offset, std::ios_base::cur); + + LLSD data; + + if (unzip_llsd(data, is, size)) + { + mPhysics.fromLLSD(data); + updateHullCenters(); + } + } + return true; } @@ -2133,3 +2157,104 @@ LLSD LLMeshSkinInfo::asLLSD(bool include_joints) const return ret; } +LLModel::Decomposition::Decomposition(LLSD& data) +{ + fromLLSD(data); +} + +void LLModel::Decomposition::fromLLSD(LLSD& decomp) +{ + if (decomp.has("HullList")) + { + // updated for const-correctness. gcc is picky about this type of thing - Nyx + const LLSD::Binary& hulls = decomp["HullList"].asBinary(); + const LLSD::Binary& position = decomp["Position"].asBinary(); + + U16* p = (U16*) &position[0]; + + mHull.resize(hulls.size()); + + LLVector3 min; + LLVector3 max; + LLVector3 range; + + min.setValue(decomp["Min"]); + max.setValue(decomp["Max"]); + range = max-min; + + for (U32 i = 0; i < hulls.size(); ++i) + { + U16 count = (hulls[i] == 0) ? 256 : hulls[i]; + + for (U32 j = 0; j < count; ++j) + { + mHull[i].push_back(LLVector3( + (F32) p[0]/65535.f*range.mV[0]+min.mV[0], + (F32) p[1]/65535.f*range.mV[1]+min.mV[1], + (F32) p[2]/65535.f*range.mV[2]+min.mV[2])); + p += 3; + } + + } + } + + if (decomp.has("Hull")) + { + const LLSD::Binary& position = decomp["Hull"].asBinary(); + + U16* p = (U16*) &position[0]; + + LLVector3 min; + LLVector3 max; + LLVector3 range; + + min.setValue(decomp["Min"]); + max.setValue(decomp["Max"]); + range = max-min; + + U16 count = position.size()/6; + + for (U32 j = 0; j < count; ++j) + { + mBaseHull.push_back(LLVector3( + (F32) p[0]/65535.f*range.mV[0]+min.mV[0], + (F32) p[1]/65535.f*range.mV[1]+min.mV[1], + (F32) p[2]/65535.f*range.mV[2]+min.mV[2])); + p += 3; + } + } + else + { + //empty base hull mesh to indicate decomposition has been loaded + //but contains no base hull + mBaseHullMesh.clear();; + } + +} + +void LLModel::Decomposition::merge(const LLModel::Decomposition* rhs) +{ + if (!rhs) + { + return; + } + + if (mMeshID != rhs->mMeshID) + { + llerrs << "Attempted to merge with decomposition of some other mesh." << llendl; + } + + if (mBaseHull.empty()) + { //take base hull and decomposition from rhs + mHull = rhs->mHull; + mBaseHull = rhs->mBaseHull; + mMesh = rhs->mMesh; + mBaseHullMesh = rhs->mBaseHullMesh; + } + + if (mPhysicsShapeMesh.empty()) + { //take physics shape mesh from rhs + mPhysicsShapeMesh = rhs->mPhysicsShapeMesh; + } +} + diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h index 81be9d1835..e9450d2967 100755 --- a/indra/llprimitive/llmodel.h +++ b/indra/llprimitive/llmodel.h @@ -27,6 +27,7 @@ #ifndef LL_LLMODEL_H #define LL_LLMODEL_H +#include "llpointer.h" #include "llvolume.h" #include "v4math.h" #include "m4math.h" @@ -54,7 +55,6 @@ public: float mPelvisOffset; }; - class LLModel : public LLVolume { public: @@ -208,9 +208,10 @@ public: float mPelvisOffset; // convex hull decomposition S32 mDecompID; - convex_hull_decomposition mConvexHullDecomp; + void setConvexHullDecomposition( const convex_hull_decomposition& decomp); + void updateHullCenters(); LLVector3 mCenterOfHullCenters; std::vector<LLVector3> mHullCenter; @@ -219,6 +220,44 @@ public: //ID for storing this model in a .slm file S32 mLocalID; + class PhysicsMesh + { + public: + std::vector<LLVector3> mPositions; + std::vector<LLVector3> mNormals; + + void clear() + { + mPositions.clear(); + mNormals.clear(); + } + + bool empty() const + { + return mPositions.empty(); + } + }; + + class Decomposition + { + public: + Decomposition() { } + Decomposition(LLSD& data); + void fromLLSD(LLSD& data); + + void merge(const Decomposition* rhs); + + LLUUID mMeshID; + LLModel::convex_hull_decomposition mHull; + LLModel::hull mBaseHull; + + std::vector<LLModel::PhysicsMesh> mMesh; + LLModel::PhysicsMesh mBaseHullMesh; + LLModel::PhysicsMesh mPhysicsShapeMesh; + }; + + Decomposition mPhysics; + protected: void addVolumeFacesFromDomMesh(domMesh* mesh); virtual BOOL createVolumeFacesFromDomMesh(domMesh *mesh); |