diff options
Diffstat (limited to 'indra/llprimitive')
| -rwxr-xr-x | indra/llprimitive/llmodel.cpp | 464 | ||||
| -rwxr-xr-x | indra/llprimitive/llmodel.h | 79 | 
2 files changed, 425 insertions, 118 deletions
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index 3669fef0dc..595f9aa307 100755 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -775,43 +775,6 @@ BOOL LLModel::createVolumeFacesFromDomMesh(domMesh* mesh)  	return FALSE;  } - -BOOL LLModel::createVolumeFacesFromFile(const std::string& file_name) -{ -	DAE dae; -	domCOLLADA* dom = dae.open(file_name); -	if (dom) -	{ -		daeDatabase* db = dae.getDatabase(); - -		daeInt count = db->getElementCount(NULL, COLLADA_TYPE_MESH); -		 -		mVolumeFaces.clear(); -		mMaterialList.clear(); - -		for (daeInt idx = 0; idx < count; ++idx) -		{ -			domMesh* mesh = NULL; - -			db->getElement((daeElement**) &mesh, idx, NULL, COLLADA_TYPE_MESH); -			 -			if (mesh) -			{ -				addVolumeFacesFromDomMesh(mesh); -			} -		} - -		if (getNumVolumeFaces() > 0) -		{ -			optimizeVolumeFaces(); -			normalizeVolumeFaces(); -			return TRUE; -		} -	} - -	return FALSE; -} -  void LLModel::offsetMesh( const LLVector3& pivotPoint )  {  	LLVector4a pivot( pivotPoint[VX], pivotPoint[VY], pivotPoint[VZ] ); @@ -1352,16 +1315,6 @@ std::string LLModel::getElementLabel(daeElement *element)  }  //static  -LLModel* LLModel::loadModelFromDae(std::string filename) -{ -	LLVolumeParams volume_params; -	volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); -	LLModel* ret = new LLModel(volume_params, 0.f);  -	ret->createVolumeFacesFromFile(filename); -	return ret; -} - -//static   LLModel* LLModel::loadModelFromDomMesh(domMesh *mesh)  {  	LLVolumeParams volume_params; @@ -1473,49 +1426,7 @@ LLSD LLModel::writeModel(  	if (skinning)  	{ //write skinning block -		if (high->mJointList.size() != high->mInvBindMatrix.size()) -		{ -			llerrs << "WTF?" << llendl; -		} - -		for (U32 i = 0; i < high->mJointList.size(); ++i) -		{ -			mdl["skin"]["joint_names"][i] = high->mJointList[i]; - -			for (U32 j = 0; j < 4; j++) -			{ -				for (U32 k = 0; k < 4; k++) -				{ -					mdl["skin"]["inverse_bind_matrix"][i][j*4+k] = high->mInvBindMatrix[i].mMatrix[j][k];  -				} -			} -		} - -		for (U32 i = 0; i < 4; i++) -		{ -			for (U32 j = 0; j < 4; j++) -			{ -				mdl["skin"]["bind_shape_matrix"][i*4+j] = high->mBindShapeMatrix.mMatrix[i][j]; -			} -		} -		 -		 -		if ( upload_joints && high->mAlternateBindMatrix.size() > 0 ) -		{ -			for (U32 i = 0; i < high->mJointList.size(); ++i) -			{ -				for (U32 j = 0; j < 4; j++) -				{ -					for (U32 k = 0; k < 4; k++) -					{ -						mdl["skin"]["alt_inverse_bind_matrix"][i][j*4+k] = high->mAlternateBindMatrix[i].mMatrix[j][k];  -					} -				} -			} - -			mdl["skin"]["pelvis_offset"] = high->mPelvisOffset; -		} -		 +		mdl["skin"] = high->mSkinInfo.asLLSD(upload_joints);  	}  	if (!decomp.empty() || !base_hull.empty()) @@ -1897,12 +1808,6 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)  	return header;  } -//static  -LLModel* LLModel::loadModelFromAsset(std::string filename, S32 lod) -{ -	return NULL; -} -  LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)  {  	weight_map::iterator iter = mSkinWeights.find(pos); @@ -1976,27 +1881,380 @@ 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;  } +bool LLModel::loadModel(std::istream& is)
 +{
 +	mSculptLevel = -1;  // default is an error occured
 +
 +	LLSD header;
 +	{
 +		if (!LLSDSerialize::fromBinary(header, is, 1024*1024*1024))
 +		{
 +			llwarns << "Mesh header parse error.  Not a valid mesh asset!" << llendl;
 +			return false;
 +		}
 +	}
 +	
 +	std::string nm[] = 
 +	{
 +		"lowest_lod",
 +		"low_lod",
 +		"medium_lod",
 +		"high_lod",
 +		"physics_shape",
 +	};
 +
 +	const S32 MODEL_LODS = 5;
 +
 +	S32 lod = llclamp((S32) mDetail, 0, MODEL_LODS);
 +
 +	if (header[nm[lod]]["offset"].asInteger() == -1 || 
 +		header[nm[lod]]["size"].asInteger() == 0 )
 +	{ //cannot load requested LOD
 +		return false;
 +	}
 +
 +	bool has_skin = header["skin"]["offset"].asInteger() >=0 &&
 +					header["skin"]["size"].asInteger() > 0;
 +
 +	if (lod == LLModel::LOD_HIGH)
 +	{ //try to load skin info and decomp info
 +		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()))
 +	{
 +		if (has_skin)
 +		{ 
 +			//build out mSkinWeight from face info
 +			for (S32 i = 0; i < getNumVolumeFaces(); ++i)
 +			{
 +				const LLVolumeFace& face = getVolumeFace(i);
 +
 +				if (face.mWeights)
 +				{
 +					for (S32 j = 0; j < face.mNumVertices; ++j)
 +					{
 +						LLVector4a& w = face.mWeights[j];
 +
 +						std::vector<JointWeight> wght;
 +
 +						for (S32 k = 0; k < 4; ++k)
 +						{
 +							S32 idx = (S32) w[k];
 +							F32 f = w[k] - idx;
 +							if (f > 0.f)
 +							{
 +								wght.push_back(JointWeight(idx, f));
 +							}
 +						}
 +
 +						if (!wght.empty())
 +						{
 +							LLVector3 pos(face.mPositions[j].getF32ptr());
 +							mSkinWeights[pos] = wght;
 +						}
 +					}
 +				}
 +			}
 +		}
 +		return true;
 +	}
 +
 +	return false;
 +
 +}
 + + +bool LLModel::loadSkinInfo(LLSD& header, std::istream &is) +{ +	S32 offset = header["skin"]["offset"].asInteger(); +	S32 size = header["skin"]["size"].asInteger(); + +	if (offset >= 0 && size > 0) +	{ +		is.seekg(offset, std::ios_base::cur); + +		LLSD skin_data; + +		if (unzip_llsd(skin_data, is, size)) +		{ +			mSkinInfo.fromLLSD(skin_data); +			return true; +		} +	} + +	return false; +} + +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; +} + + +LLMeshSkinInfo::LLMeshSkinInfo(LLSD& skin) +{ +	fromLLSD(skin); +} + +void LLMeshSkinInfo::fromLLSD(LLSD& skin) +{ +	if (skin.has("joint_names")) +	{ +		for (U32 i = 0; i < skin["joint_names"].size(); ++i) +		{ +			mJointNames.push_back(skin["joint_names"][i]); +		} +	} + +	if (skin.has("inverse_bind_matrix")) +	{ +		for (U32 i = 0; i < skin["inverse_bind_matrix"].size(); ++i) +		{ +			LLMatrix4 mat; +			for (U32 j = 0; j < 4; j++) +			{ +				for (U32 k = 0; k < 4; k++) +				{ +					mat.mMatrix[j][k] = skin["inverse_bind_matrix"][i][j*4+k].asReal(); +				} +			} + +			mInvBindMatrix.push_back(mat); +		} +	} + +	if (skin.has("bind_shape_matrix")) +	{ +		for (U32 j = 0; j < 4; j++) +		{ +			for (U32 k = 0; k < 4; k++) +			{ +				mBindShapeMatrix.mMatrix[j][k] = skin["bind_shape_matrix"][j*4+k].asReal(); +			} +		} +	} + +	if (skin.has("alt_inverse_bind_matrix")) +	{ +		for (U32 i = 0; i < skin["alt_inverse_bind_matrix"].size(); ++i) +		{ +			LLMatrix4 mat; +			for (U32 j = 0; j < 4; j++) +			{ +				for (U32 k = 0; k < 4; k++) +				{ +					mat.mMatrix[j][k] = skin["alt_inverse_bind_matrix"][i][j*4+k].asReal(); +				} +			} +			 +			mAlternateBindMatrix.push_back(mat); +		} +	} + +	if (skin.has("pelvis_offset")) +	{ +		mPelvisOffset = skin["pelvis_offset"].asReal(); +	} +} + +LLSD LLMeshSkinInfo::asLLSD(bool include_joints) const +{ +	LLSD ret; + +	for (U32 i = 0; i < mJointNames.size(); ++i) +	{ +		ret["joint_names"][i] = mJointNames[i]; + +		for (U32 j = 0; j < 4; j++) +		{ +			for (U32 k = 0; k < 4; k++) +			{ +				ret["inverse_bind_matrix"][i][j*4+k] = mInvBindMatrix[i].mMatrix[j][k];  +			} +		} +	} + +	for (U32 i = 0; i < 4; i++) +	{ +		for (U32 j = 0; j < 4; j++) +		{ +			ret["bind_shape_matrix"][i*4+j] = mBindShapeMatrix.mMatrix[i][j]; +		} +	} +		 +	if ( include_joints && mAlternateBindMatrix.size() > 0 ) +	{ +		for (U32 i = 0; i < mJointNames.size(); ++i) +		{ +			for (U32 j = 0; j < 4; j++) +			{ +				for (U32 k = 0; k < 4; k++) +				{ +					ret["alt_inverse_bind_matrix"][i][j*4+k] = mAlternateBindMatrix[i].mMatrix[j][k];  +				} +			} +		} + +		ret["pelvis_offset"] = mPelvisOffset; +	} + +	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 addf527d8d..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" @@ -36,6 +37,24 @@ class domMesh;  #define MAX_MODEL_FACES 8 + +class LLMeshSkinInfo  +{ +public: +	LLUUID mMeshID; +	std::vector<std::string> mJointNames; +	std::vector<LLMatrix4> mInvBindMatrix; +	std::vector<LLMatrix4> mAlternateBindMatrix; +	std::map<std::string, U32> mJointMap; + +	LLMeshSkinInfo() { } +	LLMeshSkinInfo(LLSD& data); +	void fromLLSD(LLSD& data); +	LLSD asLLSD(bool include_joints) const; +	LLMatrix4 mBindShapeMatrix; +	float mPelvisOffset; +}; +  class LLModel : public LLVolume  {  public: @@ -58,6 +77,9 @@ public:  	LLModel(LLVolumeParams& params, F32 detail);  	~LLModel(); +	bool loadModel(std::istream& is); +	bool loadSkinInfo(LLSD& header, std::istream& is); +	bool loadDecomposition(LLSD& header, std::istream& is);  	static LLSD writeModel(  		std::string filename,  		LLModel* physics, @@ -98,8 +120,6 @@ public:  		LLSD& mdl,  		BOOL nowrite = FALSE); -	static LLModel* loadModelFromAsset(std::string filename, S32 lod); -	static LLModel* loadModelFromDae(std::string filename);  	static LLModel* loadModelFromDomMesh(domMesh* mesh);  	static std::string getElementLabel(daeElement* element);  	std::string getName() const; @@ -177,17 +197,8 @@ public:  	//get list of weight influences closest to given position  	weight_list& getJointInfluences(const LLVector3& pos); -	//should always be true that mJointList[mJointMap["foo"]] == "foo" - -	//map of joint names to joint index -	std::map<std::string, U32> mJointMap; - -	//list of joint names -	std::vector<std::string> mJointList; - -	LLMatrix4 mBindShapeMatrix; -	std::vector<LLMatrix4> mInvBindMatrix; -	std::vector<LLMatrix4> mAlternateBindMatrix; +	LLMeshSkinInfo mSkinInfo; +	  	std::string mRequestedLabel; // name requested in UI, if any.  	std::string mLabel; // name computed from dae. @@ -197,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; @@ -208,9 +220,46 @@ 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 createVolumeFacesFromFile(const std::string& file_name);  	virtual BOOL createVolumeFacesFromDomMesh(domMesh *mesh);  };  | 
