diff options
| -rwxr-xr-x | indra/llcommon/CMakeLists.txt | 2 | ||||
| -rw-r--r--[-rwxr-xr-x] | indra/llcommon/llcallbacklist.cpp (renamed from indra/newview/llcallbacklist.cpp) | 111 | ||||
| -rw-r--r--[-rwxr-xr-x] | indra/llcommon/llcallbacklist.h (renamed from indra/newview/llcallbacklist.h) | 21 | ||||
| -rwxr-xr-x | indra/llcommon/lldate.h | 1 | ||||
| -rwxr-xr-x | indra/llcommon/llinstancetracker.h | 1 | ||||
| -rwxr-xr-x | indra/llcommon/llstl.h | 4 | ||||
| -rwxr-xr-x | indra/llmath/llvolume.h | 5 | ||||
| -rwxr-xr-x | indra/llmath/m4math.cpp | 13 | ||||
| -rwxr-xr-x | indra/llmath/m4math.h | 5 | ||||
| -rwxr-xr-x | indra/llprimitive/CMakeLists.txt | 8 | ||||
| -rwxr-xr-x | indra/llprimitive/llmodel.cpp | 1290 | ||||
| -rwxr-xr-x | indra/llprimitive/llmodel.h | 128 | ||||
| -rwxr-xr-x | indra/llprimitive/lltextureentry.cpp | 9 | ||||
| -rwxr-xr-x | indra/llprimitive/lltextureentry.h | 4 | ||||
| -rwxr-xr-x | indra/newview/CMakeLists.txt | 2 | ||||
| -rwxr-xr-x | indra/newview/app_settings/settings.xml | 22 | ||||
| -rwxr-xr-x | indra/newview/llfloatermodelpreview.cpp | 2792 | ||||
| -rwxr-xr-x | indra/newview/llfloatermodelpreview.h | 121 | ||||
| -rwxr-xr-x | indra/newview/llmeshrepository.cpp | 281 | ||||
| -rwxr-xr-x | indra/newview/llmeshrepository.h | 50 | 
20 files changed, 1266 insertions, 3604 deletions
| diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 8767616a70..aad3bd64a2 100755 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -36,6 +36,7 @@ set(llcommon_SOURCE_FILES      llavatarname.cpp      llbase32.cpp      llbase64.cpp +    llcallbacklist.cpp      llcommon.cpp      llcommonutils.cpp      llcoros.cpp @@ -139,6 +140,7 @@ set(llcommon_HEADER_FILES      llboost.h      llchat.h      llclickaction.h +    llcallbacklist.h      llcommon.h      llcommonutils.h      llcoros.h diff --git a/indra/newview/llcallbacklist.cpp b/indra/llcommon/llcallbacklist.cpp index 79ec43dfe9..541ff75ee4 100755..100644 --- a/indra/newview/llcallbacklist.cpp +++ b/indra/llcommon/llcallbacklist.cpp @@ -24,16 +24,10 @@   * $/LicenseInfo$   */ -#include "llviewerprecompiledheaders.h" -  #include "llcallbacklist.h"  #include "lleventtimer.h" +#include "llerrorlegacy.h" -// Library includes -#include "llerror.h" - - -//  // Globals  //  LLCallbackList gIdleCallbacks; @@ -56,24 +50,24 @@ void LLCallbackList::addFunction( callback_t func, void *data)  {  	if (!func)  	{ -		llerrs << "LLCallbackList::addFunction - function is NULL" << llendl;  		return;  	}  	// only add one callback per func/data pair -	callback_pair_t t(func, data); -	callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t); -	if (iter == mCallbackList.end()) +	// +	if (containsFunction(func))  	{ -		mCallbackList.push_back(t); +		return;  	} +	 +	callback_pair_t t(func, data); +	mCallbackList.push_back(t);  } - -BOOL LLCallbackList::containsFunction( callback_t func, void *data) +bool LLCallbackList::containsFunction( callback_t func, void *data)  {  	callback_pair_t t(func, data); -	callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t); +	callback_list_t::iterator iter = find(func,data);  	if (iter != mCallbackList.end())  	{  		return TRUE; @@ -85,10 +79,9 @@ BOOL LLCallbackList::containsFunction( callback_t func, void *data)  } -BOOL LLCallbackList::deleteFunction( callback_t func, void *data) +bool LLCallbackList::deleteFunction( callback_t func, void *data)  { -	callback_pair_t t(func, data); -	callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t); +	callback_list_t::iterator iter = find(func,data);  	if (iter != mCallbackList.end())  	{  		mCallbackList.erase(iter); @@ -100,6 +93,13 @@ BOOL LLCallbackList::deleteFunction( callback_t func, void *data)  	}  } +inline  +LLCallbackList::callback_list_t::iterator +LLCallbackList::find(callback_t func, void *data) +{ +	callback_pair_t t(func, data); +	return std::find(mCallbackList.begin(), mCallbackList.end(), t); +}  void LLCallbackList::deleteAllFunctions()  { @@ -228,78 +228,3 @@ void doPeriodically(bool_func_t callable, F32 seconds)  {  	new BoolFuncEventTimer(callable, seconds);  } - -#ifdef _DEBUG - -void test1(void *data) -{ -	S32 *s32_data = (S32 *)data; -	llinfos << "testfunc1 " << *s32_data << llendl; -} - - -void test2(void *data) -{ -	S32 *s32_data = (S32 *)data; -	llinfos << "testfunc2 " << *s32_data << llendl; -} - - -void -LLCallbackList::test() -{ -	S32 a = 1; -	S32 b = 2; -	LLCallbackList *list = new LLCallbackList; - -	llinfos << "Testing LLCallbackList" << llendl; - -	if (!list->deleteFunction(NULL)) -	{ -		llinfos << "passed 1" << llendl; -	} -	else -	{ -		llinfos << "error, removed function from empty list" << llendl; -	} - -	// llinfos << "This should crash" << llendl; -	// list->addFunction(NULL); - -	list->addFunction(&test1, &a); -	list->addFunction(&test1, &a); - -	llinfos << "Expect: test1 1, test1 1" << llendl; -	list->callFunctions(); - -	list->addFunction(&test1, &b); -	list->addFunction(&test2, &b); - -	llinfos << "Expect: test1 1, test1 1, test1 2, test2 2" << llendl; -	list->callFunctions(); - -	if (list->deleteFunction(&test1, &b)) -	{ -		llinfos << "passed 3" << llendl; -	} -	else -	{ -		llinfos << "error removing function" << llendl; -	} - -	llinfos << "Expect: test1 1, test1 1, test2 2" << llendl; -	list->callFunctions(); - -	list->deleteAllFunctions(); - -	llinfos << "Expect nothing" << llendl; -	list->callFunctions(); - -	llinfos << "nothing :-)" << llendl; - -	delete list; - -	llinfos << "test complete" << llendl; -} - -#endif  // _DEBUG diff --git a/indra/newview/llcallbacklist.h b/indra/llcommon/llcallbacklist.h index 0516c9cdb4..89716cd74c 100755..100644 --- a/indra/newview/llcallbacklist.h +++ b/indra/llcommon/llcallbacklist.h @@ -28,27 +28,34 @@  #define LL_LLCALLBACKLIST_H  #include "llstl.h" +#include <boost/function.hpp> +#include <list>  class LLCallbackList  {  public:  	typedef void (*callback_t)(void*); + +	typedef std::pair< callback_t,void* >	callback_pair_t; +	// NOTE: It is confirmed that we DEPEND on the order provided by using a list :( +	// +	typedef std::list< callback_pair_t >	callback_list_t;   	LLCallbackList();  	~LLCallbackList(); -	void addFunction( callback_t func, void *data = NULL );		// register a callback, which will be called as func(data) -	BOOL containsFunction( callback_t func, void *data = NULL );	// true if list already contains the function/data pair -	BOOL deleteFunction( callback_t func, void *data = NULL );		// removes the first instance of this function/data pair from the list, false if not found -	void callFunctions();												// calls all functions +	void addFunction( callback_t func, void *data = NULL );			// register a callback, which will be called as func(data) +	bool containsFunction( callback_t func, void *data = NULL );	// true if list already contains the function/data pair +	bool deleteFunction( callback_t func, void *data = NULL );		// removes the first instance of this function/data pair from the list, false if not found +	void callFunctions();														// calls all functions  	void deleteAllFunctions();  	static void test();  protected: -	// Use a list so that the callbacks are ordered in case that matters -	typedef std::pair<callback_t,void*> callback_pair_t; -	typedef std::list<callback_pair_t > callback_list_t; + +	inline callback_list_t::iterator find(callback_t func, void *data); +  	callback_list_t	mCallbackList;  }; diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h index 7ff8b550ad..47635b30bc 100755 --- a/indra/llcommon/lldate.h +++ b/indra/llcommon/lldate.h @@ -33,6 +33,7 @@  #include <string>  #include "stdtypes.h" +#include "llpreprocessor.h"  /**    * @class LLDate diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index 55187d8325..b039290037 100755 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -305,7 +305,6 @@ protected:  	virtual ~LLInstanceTracker()  	{  		// it's unsafe to delete instances of this type while all instances are being iterated over. -		llassert_always(getStatic().sIterationNestDepth == 0);  		getSet_().erase(static_cast<T*>(this));  	} diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h index 0a39288f5a..6a539c2b91 100755 --- a/indra/llcommon/llstl.h +++ b/indra/llcommon/llstl.h @@ -27,6 +27,8 @@  #ifndef LL_LLSTL_H  #define LL_LLSTL_H +#include "stdtypes.h" +  #include <functional>  #include <algorithm>  #include <map> @@ -489,7 +491,7 @@ bool before(const std::type_info* lhs, const std::type_info* rhs)      return strcmp(lhs->name(), rhs->name()) < 0;  #else  // not Linux, or gcc 4.4+      // Just use before(), as we normally would -    return lhs->before(*rhs); +    return lhs->before(*rhs) ? true : false;  #endif  } diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 975227ea58..d2cb052043 100755 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -969,6 +969,7 @@ protected:  	~LLVolume(); // use unref  public: +	typedef std::vector<LLVolumeFace> face_list_t;  	struct FaceParams  	{ @@ -1041,6 +1042,10 @@ public:  																				// conversion if *(LLVolume*) to LLVolume&  	const LLVolumeFace &getVolumeFace(const S32 f) const {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE +	LLVolumeFace &getVolumeFace(const S32 f) {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE + +	face_list_t& getVolumeFaces() { return mVolumeFaces; } +  	U32					mFaceMask;			// bit array of which faces exist in this volume  	LLVector3			mLODScaleBias;		// vector for biasing LOD based on scale diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp index 6a1b4143cf..d89c482804 100755 --- a/indra/llmath/m4math.cpp +++ b/indra/llmath/m4math.cpp @@ -274,6 +274,19 @@ const LLMatrix4&	LLMatrix4::invert(void)  	return *this;  } +// Convenience func for simplifying comparison-heavy code by +// intentionally stomping values in [-FLT_EPS,FLT_EPS] to 0.0f +// +void LLMatrix4::condition(void) +{ +	U32 i; +	U32 j; +	for (i = 0; i < 3;i++) +		for (j = 0; j < 3;j++) +			mMatrix[i][j] = ((mMatrix[i][j] > -FLT_EPSILON) +							  && (mMatrix[i][j] < FLT_EPSILON)) ? 0.0f : mMatrix[i][j]; +} +  LLVector4 LLMatrix4::getFwdRow4() const  {  	return LLVector4(mMatrix[VX][VX], mMatrix[VX][VY], mMatrix[VX][VZ], mMatrix[VX][VW]); diff --git a/indra/llmath/m4math.h b/indra/llmath/m4math.h index a7dce10397..a77c5bc76d 100755 --- a/indra/llmath/m4math.h +++ b/indra/llmath/m4math.h @@ -180,6 +180,11 @@ public:  	const LLMatrix4& setTranslation(const LLVector4 &translation);  	const LLMatrix4& setTranslation(const LLVector3 &translation); +	// Convenience func for simplifying comparison-heavy code by +	// intentionally stomping values [-FLT_EPS,FLT_EPS] to 0.0 +	// +	void condition(void); +  	///////////////////////////  	//  	// Get properties of a matrix diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt index 0dd13916bf..590620e1b1 100755 --- a/indra/llprimitive/CMakeLists.txt +++ b/indra/llprimitive/CMakeLists.txt @@ -8,6 +8,7 @@ include(LLMath)  include(LLMessage)  include(LLXML)  include(LLPhysicsExtensions) +include(LLCharacter)  include_directories(      ${LLCOMMON_INCLUDE_DIRS} @@ -16,6 +17,7 @@ include_directories(      ${LLXML_INCLUDE_DIRS}      ${LIBS_PREBUILT_DIR}/include/collada      ${LIBS_PREBUILT_DIR}/include/collada/1.4 +    ${LLCHARACTER_INCLUDE_DIRS}      )  include_directories(SYSTEM      ${LLCOMMON_SYSTEM_INCLUDE_DIRS} @@ -24,11 +26,13 @@ include_directories(SYSTEM      )  set(llprimitive_SOURCE_FILES +    lldaeloader.cpp      llmaterialid.cpp      llmaterial.cpp      llmaterialtable.cpp      llmediaentry.cpp      llmodel.cpp +    llmodelloader.cpp      llprimitive.cpp      llprimtexturelist.cpp      lltextureanim.cpp @@ -41,13 +45,14 @@ set(llprimitive_SOURCE_FILES  set(llprimitive_HEADER_FILES      CMakeLists.txt - +    lldaeloader.h      legacy_object_types.h      llmaterial.h      llmaterialid.h      llmaterialtable.h      llmediaentry.h      llmodel.h +    llmodelloader.h      llprimitive.h      llprimtexturelist.h      lltextureanim.h @@ -73,6 +78,7 @@ target_link_libraries(llprimitive      ${LLMESSAGE_LIBRARIES}      ${LLXML_LIBRARIES}      ${LLPHYSICSEXTENSIONS_LIBRARIES} +    ${LLCHARACTER_LIBRARIES}      ) diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index 34e0483a83..5cc5dc5b97 100755 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -31,18 +31,6 @@  #include "llconvexdecomposition.h"  #include "llsdserialize.h"  #include "llvector4a.h" -#if LL_MSVC -#pragma warning (disable : 4263) -#pragma warning (disable : 4264) -#endif -#include "dae.h" -#include "dae/daeErrorHandler.h" -#include "dom/domConstants.h" -#include "dom/domMesh.h" -#if LL_MSVC -#pragma warning (default : 4263) -#pragma warning (default : 4264) -#endif  #ifdef LL_STANDALONE  # include <zlib.h> @@ -50,8 +38,6 @@  # include "zlib/zlib.h"  #endif - -  std::string model_names[] =  {  	"lowest_lod", @@ -65,7 +51,7 @@ const int MODEL_NAMES_LENGTH = sizeof(model_names) / sizeof(std::string);  LLModel::LLModel(LLVolumeParams& params, F32 detail)  	: LLVolume(params, detail), mNormalizedScale(1,1,1), mNormalizedTranslation(0,0,0) -	, mPelvisOffset( 0.0f ), mStatus(NO_ERRORS) +	, mPelvisOffset( 0.0f ), mStatus(NO_ERRORS), mSubmodelID(0)  {  	mDecompID = -1;  	mLocalID = -1; @@ -79,915 +65,105 @@ LLModel::~LLModel()  	}  } - -bool get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride, -					 domSource* &pos_source, domSource* &tc_source, domSource* &norm_source) +//static +std::string LLModel::getStatusString(U32 status)  { -	idx_stride = 0; +	const static std::string status_strings[(S32)INVALID_STATUS] = {"status_no_error", "status_vertex_number_overflow","bad_element"}; -	for (U32 j = 0; j < inputs.getCount(); ++j) +	if(status < INVALID_STATUS)  	{ -		idx_stride = llmax((S32) inputs[j]->getOffset(), idx_stride); - -		if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[j]->getSemantic()) == 0) -		{ //found vertex array -			const domURIFragmentType& uri = inputs[j]->getSource(); -			daeElementRef elem = uri.getElement(); -			domVertices* vertices = (domVertices*) elem.cast(); -			if ( !vertices ) -			{ -				return false; -			} -				 -			domInputLocal_Array& v_inp = vertices->getInput_array(); -			 -			 -			for (U32 k = 0; k < v_inp.getCount(); ++k) -			{ -				if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0) -				{ -					pos_offset = inputs[j]->getOffset(); - -					const domURIFragmentType& uri = v_inp[k]->getSource(); -					daeElementRef elem = uri.getElement(); -					pos_source = (domSource*) elem.cast(); -				} -				 -				if (strcmp(COMMON_PROFILE_INPUT_NORMAL, v_inp[k]->getSemantic()) == 0) -				{ -					norm_offset = inputs[j]->getOffset(); - -					const domURIFragmentType& uri = v_inp[k]->getSource(); -					daeElementRef elem = uri.getElement(); -					norm_source = (domSource*) elem.cast(); -				} -			} -		} - -		if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[j]->getSemantic()) == 0) +		if(status_strings[status] == std::string())  		{ -			//found normal array for this triangle list -			norm_offset = inputs[j]->getOffset(); -			const domURIFragmentType& uri = inputs[j]->getSource(); -			daeElementRef elem = uri.getElement(); -			norm_source = (domSource*) elem.cast(); -		} -		else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[j]->getSemantic()) == 0) -		{ //found texCoords -			tc_offset = inputs[j]->getOffset(); -			const domURIFragmentType& uri = inputs[j]->getSource(); -			daeElementRef elem = uri.getElement(); -			tc_source = (domSource*) elem.cast(); +			llerrs << "No valid status string for this status: " << (U32)status << llendl ;  		} +		return status_strings[status] ;  	} -	idx_stride += 1; -	 -	return true; -} - -LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domTrianglesRef& tri) -{ -	LLVolumeFace face; -	std::vector<LLVolumeFace::VertexData> verts; -	std::vector<U16> indices; -	 -	const domInputLocalOffset_Array& inputs = tri->getInput_array(); - -	S32 pos_offset = -1; -	S32 tc_offset = -1; -	S32 norm_offset = -1; - -	domSource* pos_source = NULL; -	domSource* tc_source = NULL; -	domSource* norm_source = NULL; - -	S32 idx_stride = 0; +	llerrs << "Invalid model status: " << (U32)status << llendl ; -	if ( !get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source) || !pos_source ) -	{ -		llwarns << "Could not find dom sources for basic geo data; invalid model." << llendl; -		return LLModel::BAD_ELEMENT; -	} +	return std::string() ; +} -	 -	domPRef p = tri->getP(); -	domListOfUInts& idx = p->getValue(); -	 -	domListOfFloats  dummy ; -	domListOfFloats& v = pos_source ? pos_source->getFloat_array()->getValue() : dummy ; -	domListOfFloats& tc = tc_source ? tc_source->getFloat_array()->getValue() : dummy ; -	domListOfFloats& n = norm_source ? norm_source->getFloat_array()->getValue() : dummy ; -	if (pos_source) -	{ -		face.mExtents[0].set(v[0], v[1], v[2]); -		face.mExtents[1].set(v[0], v[1], v[2]); -	} -	 -	LLVolumeFace::VertexMapData::PointMap point_map; +void LLModel::offsetMesh( const LLVector3& pivotPoint ) +{ +	LLVector4a pivot( pivotPoint[VX], pivotPoint[VY], pivotPoint[VZ] ); -	U32 index_count  = idx.getCount(); -	U32 vertex_count = pos_source  ? v.getCount()  : 0; -	U32 tc_count     = tc_source   ? tc.getCount() : 0; -	U32 norm_count   = norm_source ? n.getCount()  : 0; - -	for (U32 i = 0; i < index_count; i += idx_stride) -	{ -		LLVolumeFace::VertexData cv; -		if (pos_source) -		{ -			// guard against model data specifiying out of range indices or verts -			// -			if (((i + pos_offset) > index_count) -			 || ((idx[i+pos_offset]*3+2) > vertex_count)) -			{ -				llwarns << "Out of range index data; invalid model." << llendl; -				return LLModel::BAD_ELEMENT; -			} - -			cv.setPosition(LLVector4a(v[idx[i+pos_offset]*3+0], -								v[idx[i+pos_offset]*3+1], -								v[idx[i+pos_offset]*3+2])); - -			if (!cv.getPosition().isFinite3()) -			{ -				llwarns << "Nan positional data, invalid model." << llendl; -				return LLModel::BAD_ELEMENT; -			} -		} - -		if (tc_source) -		{ -			// guard against model data specifiying out of range indices or tcs -			// -			 -			if (((i + tc_offset) > index_count) -			 || ((idx[i+tc_offset]*2+1) > tc_count)) -			{ -				llwarns << "Out of range TC indices." << llendl; -				return LLModel::BAD_ELEMENT; -			} - -			cv.mTexCoord.setVec(tc[idx[i+tc_offset]*2+0], -								tc[idx[i+tc_offset]*2+1]); - -			if (!cv.mTexCoord.isFinite()) -			{ -				llwarns << "Found NaN while loading tex coords from DAE-Model, invalid model." << llendl; -				return LLModel::BAD_ELEMENT; -			} -		} -		 -		if (norm_source) -		{ -			// guard against model data specifiying out of range indices or norms -			// -			if (((i + norm_offset) > index_count) -				|| ((idx[i+norm_offset]*3+2) > norm_count)) -			{ -				llwarns << "Found out of range norm indices, invalid model." << llendl; -				return LLModel::BAD_ELEMENT; -			} - -			cv.setNormal(LLVector4a(n[idx[i+norm_offset]*3+0], -								n[idx[i+norm_offset]*3+1], -								n[idx[i+norm_offset]*3+2])); - -			if (!cv.getNormal().isFinite3()) -			{ -				llwarns << "Found NaN while loading normals from DAE-Model, invalid model." << llendl; -				return LLModel::BAD_ELEMENT; -			} -		} -		 -		BOOL found = FALSE; -			 -		LLVolumeFace::VertexMapData::PointMap::iterator point_iter; -		point_iter = point_map.find(LLVector3(cv.getPosition().getF32ptr())); -		 -		if (point_iter != point_map.end()) -		{ -			for (U32 j = 0; j < point_iter->second.size(); ++j) -			{ -				if ((point_iter->second)[j] == cv) -				{ -					found = TRUE; -					indices.push_back((point_iter->second)[j].mIndex); -					break; -				} -			} -		} - -		if (!found) -		{ -			update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition()); -			verts.push_back(cv); -			if (verts.size() >= 65535) -			{ -				//llerrs << "Attempted to write model exceeding 16-bit index buffer limitation." << llendl; -				return LLModel::VERTEX_NUMBER_OVERFLOW ; -			} -			U16 index = (U16) (verts.size()-1); -			indices.push_back(index); - -			LLVolumeFace::VertexMapData d; -			d.setPosition(cv.getPosition()); -			d.mTexCoord = cv.mTexCoord; -			d.setNormal(cv.getNormal()); -			d.mIndex = index; -			if (point_iter != point_map.end()) -			{ -				point_iter->second.push_back(d); -			} -			else -			{ -				point_map[LLVector3(d.getPosition().getF32ptr())].push_back(d); -			} -		} - -		if (indices.size()%3 == 0 && verts.size() >= 65532) -		{ -			face_list.push_back(face); -			face_list.rbegin()->fillFromLegacyData(verts, indices); -			LLVolumeFace& new_face = *face_list.rbegin(); -			if (!norm_source) -			{ -				//ll_aligned_free_16(new_face.mNormals); -				new_face.mNormals = NULL; -			} - -			if (!tc_source) -			{ -				//ll_aligned_free_16(new_face.mTexCoords); -				new_face.mTexCoords = NULL; -			} - -			face = LLVolumeFace(); -			point_map.clear(); -		} -	} - -	if (!verts.empty()) +	for (std::vector<LLVolumeFace>::iterator faceIt = mVolumeFaces.begin(); faceIt != mVolumeFaces.end(); )  	{ -		std::string material; - -		if (tri->getMaterial()) -		{ -			material = std::string(tri->getMaterial()); -		} +		std::vector<LLVolumeFace>:: iterator currentFaceIt = faceIt++; +		LLVolumeFace& face = *currentFaceIt; +		LLVector4a *pos = (LLVector4a*) face.mPositions; -		materials.push_back(material); -		face_list.push_back(face); - -		face_list.rbegin()->fillFromLegacyData(verts, indices); -		LLVolumeFace& new_face = *face_list.rbegin(); -		if (!norm_source) -		{ -			//ll_aligned_free_16(new_face.mNormals); -			new_face.mNormals = NULL; -		} - -		if (!tc_source) +		for (U32 i=0; i<face.mNumVertices; ++i )  		{ -			//ll_aligned_free_16(new_face.mTexCoords); -			new_face.mTexCoords = NULL; +			pos[i].add( pivot );  		}  	} - -	return LLModel::NO_ERRORS ;  } -LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domPolylistRef& poly) +void LLModel::optimizeVolumeFaces()  { -	domPRef p = poly->getP(); -	domListOfUInts& idx = p->getValue(); - -	if (idx.getCount() == 0) -	{ -		return LLModel::NO_ERRORS ; -	} - -	const domInputLocalOffset_Array& inputs = poly->getInput_array(); - - -	domListOfUInts& vcount = poly->getVcount()->getValue(); -	 -	S32 pos_offset = -1; -	S32 tc_offset = -1; -	S32 norm_offset = -1; - -	domSource* pos_source = NULL; -	domSource* tc_source = NULL; -	domSource* norm_source = NULL; - -	S32 idx_stride = 0; - -	if (!get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source)) -	{ -		llwarns << "Could not get DOM sources for basic geo data, invalid model." << llendl; -		return LLModel::BAD_ELEMENT; -	} - -	LLVolumeFace face; - -	std::vector<U16> indices; -	std::vector<LLVolumeFace::VertexData> verts; - -	domListOfFloats v; -	domListOfFloats tc; -	domListOfFloats n; - -	if (pos_source) -	{ -		v = pos_source->getFloat_array()->getValue(); -		face.mExtents[0].set(v[0], v[1], v[2]); -		face.mExtents[1].set(v[0], v[1], v[2]); -	} - -	if (tc_source) -	{ -		tc = tc_source->getFloat_array()->getValue(); -	} - -	if (norm_source) -	{ -		n = norm_source->getFloat_array()->getValue(); -	} -	 -	LLVolumeFace::VertexMapData::PointMap point_map; - -	U32 index_count  = idx.getCount(); -	U32 vertex_count = pos_source  ? v.getCount()  : 0; -	U32 tc_count     = tc_source   ? tc.getCount() : 0; -	U32 norm_count   = norm_source ? n.getCount()  : 0; - -	U32 cur_idx = 0; -	for (U32 i = 0; i < vcount.getCount(); ++i) -	{ //for each polygon -		U32 first_index = 0; -		U32 last_index = 0; -		for (U32 j = 0; j < vcount[i]; ++j) -		{ //for each vertex - -			LLVolumeFace::VertexData cv; - -			if (pos_source) -			{ -				// guard against model data specifiying out of range indices or verts -				// -				if (((cur_idx + pos_offset) > index_count) -				 || ((idx[cur_idx+pos_offset]*3+2) > vertex_count)) -				{ -					llwarns << "Out of range position indices, invalid model." << llendl; -					return LLModel::BAD_ELEMENT; -				} - -				cv.getPosition().set(v[idx[cur_idx+pos_offset]*3+0], -									v[idx[cur_idx+pos_offset]*3+1], -									v[idx[cur_idx+pos_offset]*3+2]); - -				if (!cv.getPosition().isFinite3()) -				{ -					llwarns << "Found NaN while loading positions from DAE-Model, invalid model." << llendl; -					return LLModel::BAD_ELEMENT; -				} - -			} - -			if (tc_source) -			{ -				// guard against model data specifiying out of range indices or tcs -				// -				if (((cur_idx + tc_offset) > index_count) -				 || ((idx[cur_idx+tc_offset]*2+1) > tc_count)) -				{ -					llwarns << "Out of range TC indices, invalid model." << llendl; -					return LLModel::BAD_ELEMENT; -				} - -				cv.mTexCoord.setVec(tc[idx[cur_idx+tc_offset]*2+0], -									tc[idx[cur_idx+tc_offset]*2+1]); - -				if (!cv.mTexCoord.isFinite()) -				{ -					llwarns << "Found NaN while loading tex coords from DAE-Model, invalid model." << llendl; -					return LLModel::BAD_ELEMENT; -				} -			} -			 -			if (norm_source) -			{ -				// guard against model data specifiying out of range indices or norms -				// -				if (((cur_idx + norm_offset) > index_count) -				 || ((idx[cur_idx+norm_offset]*3+2) > norm_count)) -				{ -					llwarns << "Out of range norm indices, invalid model." << llendl; -					return LLModel::BAD_ELEMENT; -				} - -				cv.getNormal().set(n[idx[cur_idx+norm_offset]*3+0], -									n[idx[cur_idx+norm_offset]*3+1], -									n[idx[cur_idx+norm_offset]*3+2]); - -				if (!cv.getNormal().isFinite3()) -				{ -					llwarns << "Found NaN while loading normals from DAE-Model, invalid model." << llendl; -					return LLModel::BAD_ELEMENT; -				} -			} -			 -			cur_idx += idx_stride; -			 -			BOOL found = FALSE; -				 -			LLVolumeFace::VertexMapData::PointMap::iterator point_iter; -			LLVector3 pos3(cv.getPosition().getF32ptr()); -			point_iter = point_map.find(pos3); -			 -			if (point_iter != point_map.end()) -			{ -				for (U32 k = 0; k < point_iter->second.size(); ++k) -				{ -					if ((point_iter->second)[k] == cv) -					{ -						found = TRUE; -						U32 index = (point_iter->second)[k].mIndex; -						if (j == 0) -						{ -							first_index = index; -						} -						else if (j == 1) -						{ -							last_index = index; -						} -						else -						{ -							indices.push_back(first_index); -							indices.push_back(last_index); -							indices.push_back(index); -							last_index = index; -						} - -						break; -					} -				} -			} - -			if (!found) -			{ -				update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition()); -				verts.push_back(cv); -				if (verts.size() >= 65535) -				{ -					//llerrs << "Attempted to write model exceeding 16-bit index buffer limitation." << llendl; -					return LLModel::VERTEX_NUMBER_OVERFLOW ; -				} -				U16 index = (U16) (verts.size()-1); -			 -				if (j == 0) -				{ -					first_index = index; -				} -				else if (j == 1) -				{ -					last_index = index; -				} -				else -				{ -					indices.push_back(first_index); -					indices.push_back(last_index); -					indices.push_back(index); -					last_index = index; -				}	 - -				LLVolumeFace::VertexMapData d; -				d.setPosition(cv.getPosition()); -				d.mTexCoord = cv.mTexCoord; -				d.setNormal(cv.getNormal()); -				d.mIndex = index; -				if (point_iter != point_map.end()) -				{ -					point_iter->second.push_back(d); -				} -				else -				{ -					point_map[pos3].push_back(d); -				} -			} - -			if (indices.size()%3 == 0 && indices.size() >= 65532) -			{ -				face_list.push_back(face); -				face_list.rbegin()->fillFromLegacyData(verts, indices); -				LLVolumeFace& new_face = *face_list.rbegin(); -				if (!norm_source) -				{ -					//ll_aligned_free_16(new_face.mNormals); -					new_face.mNormals = NULL; -				} - -				if (!tc_source) -				{ -					//ll_aligned_free_16(new_face.mTexCoords); -					new_face.mTexCoords = NULL; -				} - -				face = LLVolumeFace(); -				verts.clear(); -				indices.clear(); -				point_map.clear(); -			} -		} -	} - -	if (!verts.empty()) +	for (U32 i = 0; i < getNumVolumeFaces(); ++i)  	{ -		std::string material; - -		if (poly->getMaterial()) -		{ -			material = std::string(poly->getMaterial()); -		} -	 -		materials.push_back(material); -		face_list.push_back(face); -		face_list.rbegin()->fillFromLegacyData(verts, indices); - -		LLVolumeFace& new_face = *face_list.rbegin(); -		if (!norm_source) -		{ -			//ll_aligned_free_16(new_face.mNormals); -			new_face.mNormals = NULL; -		} - -		if (!tc_source) -		{ -			//ll_aligned_free_16(new_face.mTexCoords); -			new_face.mTexCoords = NULL; -		} +		mVolumeFaces[i].optimize();  	} - -	return LLModel::NO_ERRORS ;  } -LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domPolygonsRef& poly) +struct MaterialBinding  { -	LLVolumeFace face; -	std::vector<U16> indices; -	std::vector<LLVolumeFace::VertexData> verts; - -	const domInputLocalOffset_Array& inputs = poly->getInput_array(); - -	S32 v_offset = -1; -	S32 n_offset = -1; -	S32 t_offset = -1; - -	domListOfFloats* v = NULL; -	domListOfFloats* n = NULL; -	domListOfFloats* t = NULL; -	 -	U32 stride = 0; -	for (U32 i = 0; i < inputs.getCount(); ++i) -	{ -		stride = llmax((U32) inputs[i]->getOffset()+1, stride); - -		if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[i]->getSemantic()) == 0) -		{ //found vertex array -			v_offset = inputs[i]->getOffset(); - -			const domURIFragmentType& uri = inputs[i]->getSource(); -			daeElementRef elem = uri.getElement(); -			domVertices* vertices = (domVertices*) elem.cast(); -			if (!vertices) -			{ -				llwarns << "Could not find vertex source, invalid model." << llendl; -				return LLModel::BAD_ELEMENT; -			} -			domInputLocal_Array& v_inp = vertices->getInput_array(); - -			for (U32 k = 0; k < v_inp.getCount(); ++k) -			{ -				if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0) -				{ -					const domURIFragmentType& uri = v_inp[k]->getSource(); -					daeElementRef elem = uri.getElement(); -					domSource* src = (domSource*) elem.cast(); -					if (!src) -					{ -						llwarns << "Could not find DOM source, invalid model." << llendl; -						return LLModel::BAD_ELEMENT; -					} -					v = &(src->getFloat_array()->getValue()); -				} -			} -		} -		else if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[i]->getSemantic()) == 0) -		{ -			n_offset = inputs[i]->getOffset(); -			//found normal array for this triangle list -			const domURIFragmentType& uri = inputs[i]->getSource(); -			daeElementRef elem = uri.getElement(); -			domSource* src = (domSource*) elem.cast(); -			if (!src) -			{ -				llwarns << "Could not find DOM source, invalid model." << llendl; -				return LLModel::BAD_ELEMENT; -			} -			n = &(src->getFloat_array()->getValue()); -		} -		else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[i]->getSemantic()) == 0 && inputs[i]->getSet() == 0) -		{ //found texCoords -			t_offset = inputs[i]->getOffset(); -			const domURIFragmentType& uri = inputs[i]->getSource(); -			daeElementRef elem = uri.getElement(); -			domSource* src = (domSource*) elem.cast(); -			if (!src) -			{ -				llwarns << "Could not find DOM source, invalid model." << llendl; -				return LLModel::BAD_ELEMENT; -			} -			t = &(src->getFloat_array()->getValue()); -		} -	} - -	domP_Array& ps = poly->getP_array(); - -	//make a triangle list in <verts> -	for (U32 i = 0; i < ps.getCount(); ++i) -	{ //for each polygon -		domListOfUInts& idx = ps[i]->getValue(); -		for (U32 j = 0; j < idx.getCount()/stride; ++j) -		{ //for each vertex -			if (j > 2) -			{ -				U32 size = verts.size(); -				LLVolumeFace::VertexData v0 = verts[size-3]; -				LLVolumeFace::VertexData v1 = verts[size-1]; - -				verts.push_back(v0); -				verts.push_back(v1); -			} - -			LLVolumeFace::VertexData vert; - - -			if (v) -			{ -				U32 v_idx = idx[j*stride+v_offset]*3; -				v_idx = llclamp(v_idx, (U32) 0, (U32) v->getCount()); -				vert.getPosition().set(v->get(v_idx), -								v->get(v_idx+1), -								v->get(v_idx+2)); - -				if (!vert.getPosition().isFinite3()) -				{ -					llwarns << "Found NaN while loading position data from DAE-Model, invalid model." << llendl; -					return LLModel::BAD_ELEMENT; -				} -			} -			 -			//bounds check n and t lookups because some FBX to DAE converters -			//use negative indices and empty arrays to indicate data does not exist -			//for a particular channel -			if (n && n->getCount() > 0) -			{ -				U32 n_idx = idx[j*stride+n_offset]*3; -				n_idx = llclamp(n_idx, (U32) 0, (U32) n->getCount()); -				vert.getNormal().set(n->get(n_idx), -								n->get(n_idx+1), -								n->get(n_idx+2)); - -				if (!vert.getNormal().isFinite3()) -				{ -					llwarns << "Found NaN while loading normals from DAE-Model, invalid model." << llendl; -					return LLModel::BAD_ELEMENT; -				} -			} -			else -			{ -				vert.getNormal().clear(); -			} - -			 -			if (t && t->getCount() > 0) -			{ -				U32 t_idx = idx[j*stride+t_offset]*2; -				t_idx = llclamp(t_idx, (U32) 0, (U32) t->getCount()); -				vert.mTexCoord.setVec(t->get(t_idx), -								t->get(t_idx+1));								 - -				if (!vert.mTexCoord.isFinite()) -				{ -					llwarns << "Found NaN while loading tex coords from DAE-Model, invalid model." << llendl; -					return LLModel::BAD_ELEMENT; -				} -			} -			else -			{ -				vert.mTexCoord.clear(); -			} - -						 -			verts.push_back(vert); -		} -	} - -	if (verts.empty()) -	{ -		return LLModel::NO_ERRORS; -	} - -	face.mExtents[0] = verts[0].getPosition(); -	face.mExtents[1] = verts[0].getPosition(); -	 -	//create a map of unique vertices to indices -	std::map<LLVolumeFace::VertexData, U32> vert_idx; - -	U32 cur_idx = 0; -	for (U32 i = 0; i < verts.size(); ++i) -	{ -		std::map<LLVolumeFace::VertexData, U32>::iterator iter = vert_idx.find(verts[i]); -		if (iter == vert_idx.end()) -		{ -			vert_idx[verts[i]] = cur_idx++; -		} -	} - -	//build vertex array from map -	std::vector<LLVolumeFace::VertexData> new_verts; -	new_verts.resize(vert_idx.size()); - -	for (std::map<LLVolumeFace::VertexData, U32>::iterator iter = vert_idx.begin(); iter != vert_idx.end(); ++iter) -	{ -		new_verts[iter->second] = iter->first; -		update_min_max(face.mExtents[0], face.mExtents[1], iter->first.getPosition()); -	} - -	//build index array from map -	indices.resize(verts.size()); - -	for (U32 i = 0; i < verts.size(); ++i) -	{ -		indices[i] = vert_idx[verts[i]]; -	} - -	// DEBUG just build an expanded triangle list -	/*for (U32 i = 0; i < verts.size(); ++i) -	{ -		indices.push_back((U16) i); -		update_min_max(face.mExtents[0], face.mExtents[1], verts[i].getPosition()); -	}*/ - -    if (!new_verts.empty()) -	{ -		std::string material; - -		if (poly->getMaterial()) -		{ -			material = std::string(poly->getMaterial()); -		} - -		materials.push_back(material); -		face_list.push_back(face); -		face_list.rbegin()->fillFromLegacyData(new_verts, indices); - -		LLVolumeFace& new_face = *face_list.rbegin(); -		if (!n) -		{ -			//ll_aligned_free_16(new_face.mNormals); -			new_face.mNormals = NULL; -		} - -		if (!t) -		{ -			//ll_aligned_free_16(new_face.mTexCoords); -			new_face.mTexCoords = NULL; -		} -	} - -	return LLModel::NO_ERRORS ; -} +	int				index; +	std::string		matName; +}; -//static -std::string LLModel::getStatusString(U32 status) +struct MaterialSort  { -	const static std::string status_strings[(S32)INVALID_STATUS] = {"status_no_error", "status_vertex_number_overflow","bad_element"}; - -	if(status < INVALID_STATUS) +	bool operator()(const MaterialBinding& lhs, const MaterialBinding& rhs)  	{ -		if(status_strings[status] == std::string()) -		{ -			llerrs << "No valid status string for this status: " << (U32)status << llendl ; -		} -		return status_strings[status] ; +		return LLStringUtil::compareInsensitive(lhs.matName, rhs.matName) < 0;  	} +}; -	llerrs << "Invalid model status: " << (U32)status << llendl ; - -	return std::string() ; -} - -void LLModel::addVolumeFacesFromDomMesh(domMesh* mesh) +void LLModel::sortVolumeFacesByMaterialName()  { -	domTriangles_Array& tris = mesh->getTriangles_array(); -		 -	for (U32 i = 0; i < tris.getCount(); ++i) +	std::vector<MaterialBinding> bindings; +	bindings.resize(mVolumeFaces.size()); +	for (int i = 0; i < bindings.size(); i++)  	{ -		domTrianglesRef& tri = tris.get(i); - -		mStatus = load_face_from_dom_triangles(mVolumeFaces, mMaterialList, tri); -		 -		if(mStatus != NO_ERRORS) -		{ -			mVolumeFaces.clear() ; -			mMaterialList.clear() ; -			return ; //abort -		} +		bindings[i].index = i; +		bindings[i].matName = mMaterialList[i];  	} +	std::sort(bindings.begin(), bindings.end(), MaterialSort()); +	std::vector< LLVolumeFace > new_faces; -	domPolylist_Array& polys = mesh->getPolylist_array(); -	for (U32 i = 0; i < polys.getCount(); ++i) +	// remap the faces to be in the same order the mats now are... +	// +	new_faces.resize(bindings.size()); +	for (int i = 0; i < bindings.size(); i++)  	{ -		domPolylistRef& poly = polys.get(i); -		mStatus = load_face_from_dom_polylist(mVolumeFaces, mMaterialList, poly); - -		if(mStatus != NO_ERRORS) -		{ -			mVolumeFaces.clear() ; -			mMaterialList.clear() ; -			return ; //abort -		} +		new_faces[i] = mVolumeFaces[bindings[i].index]; +		mMaterialList[i] = bindings[i].matName;  	} -	 -	domPolygons_Array& polygons = mesh->getPolygons_array(); -	 -	for (U32 i = 0; i < polygons.getCount(); ++i) -	{ -		domPolygonsRef& poly = polygons.get(i); -		mStatus = load_face_from_dom_polygons(mVolumeFaces, mMaterialList, poly); -		if(mStatus != NO_ERRORS) -		{ -			mVolumeFaces.clear() ; -			mMaterialList.clear() ; -			return ; //abort -		} -	} -  +	mVolumeFaces = new_faces;	  } -BOOL LLModel::createVolumeFacesFromDomMesh(domMesh* mesh) +void LLModel::trimVolumeFacesToSize(U32 new_count, LLVolume::face_list_t* remainder)  { -	if (mesh) -	{ -		mVolumeFaces.clear(); -		mMaterialList.clear(); - -		addVolumeFacesFromDomMesh(mesh); -		 -		if (getNumVolumeFaces() > 0) -		{ -			normalizeVolumeFaces(); -			optimizeVolumeFaces(); -			 -			if (getNumVolumeFaces() > 0) -			{ -				return TRUE; -			} -		} -	} -	else -	{	 -		llwarns << "no mesh found" << llendl; -	} -	 -	return FALSE; -} +	llassert(new_count <= LL_SCULPT_MESH_MAX_FACES); -void LLModel::offsetMesh( const LLVector3& pivotPoint ) -{ -	LLVector4a pivot( pivotPoint[VX], pivotPoint[VY], pivotPoint[VZ] ); -	 -	for (std::vector<LLVolumeFace>::iterator faceIt = mVolumeFaces.begin(); faceIt != mVolumeFaces.end(); ) +	if (new_count && (getNumVolumeFaces() > new_count))  	{ -		std::vector<LLVolumeFace>:: iterator currentFaceIt = faceIt++; -		LLVolumeFace& face = *currentFaceIt; -		LLVector4a *pos = (LLVector4a*) face.mPositions; -		 -		for (U32 i=0; i<face.mNumVertices; ++i ) +		// Copy out remaining volume faces for alternative handling, if provided +		// +		if (remainder)  		{ -			pos[i].add( pivot ); -		} -	} -} +			(*remainder).assign(mVolumeFaces.begin() + new_count, mVolumeFaces.end()); +		}		 -void LLModel::optimizeVolumeFaces() -{ -	for (U32 i = 0; i < getNumVolumeFaces(); ++i) -	{ -		mVolumeFaces[i].optimize(); +		// Trim down to the final set of volume faces (now stuffed to the gills!) +		// +		mVolumeFaces.resize(new_count);  	}  } @@ -1001,11 +177,6 @@ void LLModel::optimizeVolumeFaces()  // within the unit cube.  void LLModel::normalizeVolumeFaces()  { - -	// ensure we don't have too many faces -	if (mVolumeFaces.size() > LL_SCULPT_MESH_MAX_FACES) -		mVolumeFaces.resize(LL_SCULPT_MESH_MAX_FACES); -	  	if (!mVolumeFaces.empty())  	{  		LLVector4a min, max; @@ -1472,68 +643,10 @@ void LLModel::generateNormals(F32 angle_cutoff)  	}  } -//static -std::string LLModel::getElementLabel(daeElement *element) -{ // try to get a decent label for this element -	// if we have a name attribute, use it -	std::string name = element->getAttribute("name"); -	if (name.length()) -	{ -		return name; -	} - -	// if we have an ID attribute, use it -	if (element->getID()) -	{ -		return std::string(element->getID()); -	} - -	// if we have a parent, use it -	daeElement* parent = element->getParent(); -	if (parent) -	{ -		// if parent has a name, use it -		std::string name = parent->getAttribute("name"); -		if (name.length()) -		{ -			return name; -		} - -		// if parent has an ID, use it -		if (parent->getID()) -		{ -			return std::string(parent->getID()); -		} -	} - -	// try to use our type -	daeString element_name = element->getElementName(); -	if (element_name) -	{ -		return std::string(element_name); -	} - -	// if all else fails, use "object" -	return std::string("object"); -} - -//static  -LLModel* LLModel::loadModelFromDomMesh(domMesh *mesh) -{ -	LLVolumeParams volume_params; -	volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); -	LLModel* ret = new LLModel(volume_params, 0.f);  -	ret->createVolumeFacesFromDomMesh(mesh); -	ret->mLabel = getElementLabel(mesh); -	return ret; -}  std::string LLModel::getName() const  { -	if (!mRequestedLabel.empty()) -		return mRequestedLabel; -	else -		return mLabel; +    return mRequestedLabel.empty() ? mLabel : mRequestedLabel;  }  //static @@ -1548,7 +661,8 @@ LLSD LLModel::writeModel(  	BOOL upload_skin,  	BOOL upload_joints,  	BOOL nowrite, -	BOOL as_slm) +	BOOL as_slm, +	int submodel_id)  {  	LLSD mdl; @@ -1577,6 +691,14 @@ LLSD LLModel::writeModel(  			model[LLModel::LOD_PHYSICS] = NULL;  		}  	} +	else if (submodel_id) +	{ +		const LLModel::Decomposition fake_decomp; +		mdl["secondary"] = true; +        mdl["submodel_id"] = submodel_id; +		mdl["physics_convex"] = fake_decomp.asLLSD(); +		model[LLModel::LOD_PHYSICS] = NULL; +	}  	if (as_slm)  	{ //save material list names @@ -1588,7 +710,7 @@ LLSD LLModel::writeModel(  	for (U32 idx = 0; idx < MODEL_NAMES_LENGTH; ++idx)  	{ -		if (model[idx] && model[idx]->getNumVolumeFaces() > 0) +		if (model[idx] && (model[idx]->getNumVolumeFaces() > 0) && model[idx]->getVolumeFace(0).mPositions != NULL)  		{  			LLVector3 min_pos = LLVector3(model[idx]->getVolumeFace(0).mPositions[0].getF32ptr());  			LLVector3 max_pos = min_pos; @@ -1821,6 +943,11 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite, BO  		}  	} +    if (mdl.has("submodel_id")) +	{ //write out submodel id +        header["submodel_id"] = (LLSD::Integer)mdl["submodel_id"]; +	} +  	std::string out[MODEL_NAMES_LENGTH];  	for (S32 i = 0; i < MODEL_NAMES_LENGTH; i++) @@ -2004,7 +1131,9 @@ bool LLModel::loadModel(std::istream& is)  		}  	} -	std::string nm[] =  +	mSubmodelID = header.has("submodel_id") ? header["submodel_id"].asInteger() : false; + +	std::string lod_name[] =   	{  		"lowest_lod",  		"low_lod", @@ -2017,8 +1146,8 @@ bool LLModel::loadModel(std::istream& is)  	S32 lod = llclamp((S32) mDetail, 0, MODEL_LODS); -	if (header[nm[lod]]["offset"].asInteger() == -1 ||  -		header[nm[lod]]["size"].asInteger() == 0 ) +	if (header[lod_name[lod]]["offset"].asInteger() == -1 ||  +		header[lod_name[lod]]["size"].asInteger() == 0 )  	{ //cannot load requested LOD  		llwarns << "LoD data is invalid!" << llendl;  		return false; @@ -2027,23 +1156,23 @@ bool LLModel::loadModel(std::istream& is)  	bool has_skin = header["skin"]["offset"].asInteger() >=0 &&  					header["skin"]["size"].asInteger() > 0; -	if (lod == LLModel::LOD_HIGH) +	if ((lod == LLModel::LOD_HIGH) && !mSubmodelID)  	{ //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_HIGH || lod == LLModel::LOD_PHYSICS) +	if ((lod == LLModel::LOD_HIGH || lod == LLModel::LOD_PHYSICS) && !mSubmodelID)  	{  		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); +	is.seekg(header[lod_name[lod]]["offset"].asInteger(), std::ios_base::cur); -	if (unpackVolumeFaces(is, header[nm[lod]]["size"].asInteger())) +	if (unpackVolumeFaces(is, header[lod_name[lod]]["size"].asInteger()))  	{  		if (has_skin)  		{  @@ -2109,8 +1238,10 @@ bool LLModel::isMaterialListSubset( LLModel* ref )  				break;  			}										  		} +  		if (!foundRef)  		{ +            llinfos << "Could not find material " << mMaterialList[src] << " in reference model " << ref->mLabel << llendl;  			return false;  		}  	} @@ -2161,41 +1292,42 @@ bool LLModel::matchMaterialOrder(LLModel* ref, int& refFaceCnt, int& modelFaceCn  	for (U32 i = 0; i < mMaterialList.size(); i++)  	{  		index_map[ref->mMaterialList[i]] = i; -		if (!reorder) -		{ //if any material name does not match reference, we need to reorder -			reorder = ref->mMaterialList[i] != mMaterialList[i]; -		} +		//if any material name does not match reference, we need to reorder +		reorder |= ref->mMaterialList[i] != mMaterialList[i];  		base_mat.insert(ref->mMaterialList[i]);  		cur_mat.insert(mMaterialList[i]);  	} -	if (reorder &&  -		base_mat == cur_mat) //don't reorder if material name sets don't match +	if (reorder &&  (base_mat == cur_mat)) //don't reorder if material name sets don't match  	{  		std::vector<LLVolumeFace> new_face_list; -		new_face_list.resize(mVolumeFaces.size()); +		new_face_list.resize(mMaterialList.size());  		std::vector<std::string> new_material_list; -		new_material_list.resize(mVolumeFaces.size()); +		new_material_list.resize(mMaterialList.size());  		//rebuild face list so materials have the same order   		//as the reference model  		for (U32 i = 0; i < mMaterialList.size(); ++i)  		{   			U32 ref_idx = index_map[mMaterialList[i]]; -			new_face_list[ref_idx] = mVolumeFaces[i]; +			if (i < mVolumeFaces.size()) +			{ +				new_face_list[ref_idx] = mVolumeFaces[i]; +			}  			new_material_list[ref_idx] = mMaterialList[i];  		}  		llassert(new_material_list == ref->mMaterialList);  		mVolumeFaces = new_face_list; -	} -	//override material list with reference model ordering -	mMaterialList = ref->mMaterialList; +		//override material list with reference model ordering +		mMaterialList = ref->mMaterialList; +	} +	  	return true;  } @@ -2226,7 +1358,7 @@ bool LLModel::loadDecomposition(LLSD& header, std::istream& is)  	S32 offset = header["physics_convex"]["offset"].asInteger();  	S32 size = header["physics_convex"]["size"].asInteger(); -	if (offset >= 0 && size > 0) +	if (offset >= 0 && size > 0 && !mSubmodelID)  	{  		is.seekg(offset, std::ios_base::cur); @@ -2634,3 +1766,227 @@ void LLModel::Decomposition::merge(const LLModel::Decomposition* rhs)  	}  } +bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a& c, F32 tolerance) +{ +	// small area check +	{ +		LLVector4a edge1; edge1.setSub( a, b ); +		LLVector4a edge2; edge2.setSub( a, c ); +		////////////////////////////////////////////////////////////////////////// +		/// Linden Modified +		////////////////////////////////////////////////////////////////////////// + +		// If no one edge is more than 10x longer than any other edge, we weaken +		// the tolerance by a factor of 1e-4f. + +		LLVector4a edge3; edge3.setSub( c, b ); +		const F32 len1sq = edge1.dot3(edge1).getF32(); +		const F32 len2sq = edge2.dot3(edge2).getF32(); +		const F32 len3sq = edge3.dot3(edge3).getF32(); +		bool abOK = (len1sq <= 100.f * len2sq) && (len1sq <= 100.f * len3sq); +		bool acOK = (len2sq <= 100.f * len1sq) && (len1sq <= 100.f * len3sq); +		bool cbOK = (len3sq <= 100.f * len1sq) && (len1sq <= 100.f * len2sq); +		if ( abOK && acOK && cbOK ) +		{ +			tolerance *= 1e-4f; +		} + +		////////////////////////////////////////////////////////////////////////// +		/// End Modified +		////////////////////////////////////////////////////////////////////////// + +		LLVector4a cross; cross.setCross3( edge1, edge2 ); + +		LLVector4a edge1b; edge1b.setSub( b, a ); +		LLVector4a edge2b; edge2b.setSub( b, c ); +		LLVector4a crossb; crossb.setCross3( edge1b, edge2b ); + +		if ( ( cross.dot3(cross).getF32() < tolerance ) || ( crossb.dot3(crossb).getF32() < tolerance )) +		{ +			return true; +		} +	} + +	// point triangle distance check +	{ +		LLVector4a Q; Q.setSub(a, b); +		LLVector4a R; R.setSub(c, b); + +		const F32 QQ = dot3fpu(Q, Q); +		const F32 RR = dot3fpu(R, R); +		const F32 QR = dot3fpu(R, Q); + +		volatile F32 QQRR = QQ * RR; +		volatile F32 QRQR = QR * QR; +		F32 Det = (QQRR - QRQR); + +		if( Det == 0.0f ) +		{ +			return true; +		} +	} + +	return false; +} + +bool validate_face(const LLVolumeFace& face) +{ +	for (U32 i = 0; i < face.mNumIndices; ++i) +	{ +		if (face.mIndices[i] >= face.mNumVertices) +		{ +			llwarns << "Face has invalid index." << llendl; +			return false; +		} +	} + +	if (face.mNumIndices % 3 != 0 || face.mNumIndices == 0) +	{ +		llwarns << "Face has invalid number of indices." << llendl; +		return false; +	} + +	/*const LLVector4a scale(0.5f); + +	for (U32 i = 0; i < face.mNumIndices; i+=3) +	{ +		U16 idx1 = face.mIndices[i]; +		U16 idx2 = face.mIndices[i+1]; +		U16 idx3 = face.mIndices[i+2]; + +		LLVector4a v1; v1.setMul(face.mPositions[idx1], scale); +		LLVector4a v2; v2.setMul(face.mPositions[idx2], scale); +		LLVector4a v3; v3.setMul(face.mPositions[idx3], scale); + +		if (ll_is_degenerate(v1,v2,v3)) +		{ +			llwarns << "Degenerate face found!" << llendl; +			return false; +		} +	}*/ + +	return true; +} + +bool validate_model(const LLModel* mdl) +{ +	if (mdl->getNumVolumeFaces() == 0) +	{ +		llwarns << "Model has no faces!" << llendl; +		return false; +	} + +	for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i) +	{ +		if (mdl->getVolumeFace(i).mNumVertices == 0) +		{ +			llwarns << "Face has no vertices." << llendl; +			return false; +		} + +		if (mdl->getVolumeFace(i).mNumIndices == 0) +		{ +			llwarns << "Face has no indices." << llendl; +			return false; +		} + +		if (!validate_face(mdl->getVolumeFace(i))) +		{ +			return false; +		} +	} + +	return true; +} + +LLModelInstance::LLModelInstance(LLSD& data) +	: LLModelInstanceBase() +{ +	mLocalMeshID = data["mesh_id"].asInteger(); +	mLabel = data["label"].asString(); +	mTransform.setValue(data["transform"]); + +	for (U32 i = 0; i < data["material"].size(); ++i) +	{ +		LLImportMaterial mat(data["material"][i]); +		mMaterial[mat.mBinding] = mat; +	} +} + + +LLSD LLModelInstance::asLLSD() +{	 +	LLSD ret; + +	ret["mesh_id"] = mModel->mLocalID; +	ret["label"] = mLabel; +	ret["transform"] = mTransform.getValue(); + +	U32 i = 0; +	for (std::map<std::string, LLImportMaterial>::iterator iter = mMaterial.begin(); iter != mMaterial.end(); ++iter) +	{ +		ret["material"][i++] = iter->second.asLLSD(); +	} + +	return ret; +} + + +LLImportMaterial::~LLImportMaterial() +{ +} + +LLImportMaterial::LLImportMaterial(LLSD& data) +{ +	mDiffuseMapFilename = data["diffuse"]["filename"].asString(); +	mDiffuseMapLabel = data["diffuse"]["label"].asString(); +	mDiffuseColor.setValue(data["diffuse"]["color"]); +	mFullbright = data["fullbright"].asBoolean(); +	mBinding = data["binding"].asString(); +} + + +LLSD LLImportMaterial::asLLSD() +{ +	LLSD ret; + +	ret["diffuse"]["filename"] = mDiffuseMapFilename; +	ret["diffuse"]["label"] = mDiffuseMapLabel; +	ret["diffuse"]["color"] = mDiffuseColor.getValue(); +	ret["fullbright"] = mFullbright; +	ret["binding"] = mBinding; + +	return ret; +} + +bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const +{ + +	if (mDiffuseMapID != rhs.mDiffuseMapID) +	{ +		return mDiffuseMapID < rhs.mDiffuseMapID; +	} + +	if (mDiffuseMapFilename != rhs.mDiffuseMapFilename) +	{ +		return mDiffuseMapFilename < rhs.mDiffuseMapFilename; +	} + +	if (mDiffuseMapLabel != rhs.mDiffuseMapLabel) +	{ +		return mDiffuseMapLabel < rhs.mDiffuseMapLabel; +	} + +	if (mDiffuseColor != rhs.mDiffuseColor) +	{ +		return mDiffuseColor < rhs.mDiffuseColor; +	} + +	if (mBinding != rhs.mBinding) +	{ +		return mBinding < rhs.mBinding; +	} + +	return mFullbright < rhs.mFullbright; +} + diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h index aaafc55258..d1570c16f5 100755 --- a/indra/llprimitive/llmodel.h +++ b/indra/llprimitive/llmodel.h @@ -138,15 +138,16 @@ public:  		BOOL upload_skin,  		BOOL upload_joints,  		BOOL nowrite = FALSE, -		BOOL as_slm = FALSE); +		BOOL as_slm = FALSE, +		int submodel_id = 0);  	static LLSD writeModelToStream(  		std::ostream& ostr,  		LLSD& mdl,  		BOOL nowrite = FALSE, BOOL as_slm = FALSE); +	 +	void ClearFacesAndMaterials() { mVolumeFaces.clear(); mMaterialList.clear(); } -	static LLModel* loadModelFromDomMesh(domMesh* mesh); -	static std::string getElementLabel(daeElement* element);  	std::string getName() const;  	std::string getMetric() const {return mMetric;}  	EModelStatus getStatus() const {return mStatus;} @@ -169,20 +170,25 @@ public:  	void addFace(const LLVolumeFace& face); +	void sortVolumeFacesByMaterialName();  	void normalizeVolumeFaces(); +	void trimVolumeFacesToSize(U32 new_count = LL_SCULPT_MESH_MAX_FACES, LLVolume::face_list_t* remainder = NULL);  	void optimizeVolumeFaces();  	void offsetMesh( const LLVector3& pivotPoint );  	void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out);  	LLVector3 getTransformedCenter(const LLMatrix4& mat); - +	  	//reorder face list based on mMaterialList in this and reference so   	//order matches that of reference (material ordering touchup)  	bool matchMaterialOrder(LLModel* ref, int& refFaceCnt, int& modelFaceCnt );  	bool isMaterialListSubset( LLModel* ref );  	bool needToAddFaces( LLModel* ref, int& refFaceCnt, int& modelFaceCnt ); -	 -	std::vector<std::string> mMaterialList; +	typedef std::vector<std::string> material_list; + +	material_list mMaterialList; + +	material_list& getMaterialList() { return mMaterialList; }  	//data used for skin weights  	class JointWeight @@ -275,9 +281,115 @@ public:  	Decomposition mPhysics;  	EModelStatus mStatus ; + +	int mSubmodelID; +}; + +typedef std::vector<LLPointer<LLModel> >	model_list; +typedef std::queue<LLPointer<LLModel> >	model_queue; + +class LLModelMaterialBase +{ +public:	 +	std::string mDiffuseMapFilename; +	std::string mDiffuseMapLabel; +	std::string mBinding; +	LLColor4		mDiffuseColor; +	bool			mFullbright; + +	LLModelMaterialBase()  +		: mFullbright(false)  +	{  +		mDiffuseColor.set(1,1,1,1); +	} +}; + +class LLImportMaterial : public LLModelMaterialBase +{ +public: +    friend class LLMeshUploadThread; +    friend class LLModelPreview; +     +    bool operator<(const LLImportMaterial ¶ms) const; +     +    LLImportMaterial() : LLModelMaterialBase() +    { +        mDiffuseColor.set(1,1,1,1); +    } +     +    LLImportMaterial(LLSD& data); +    virtual ~LLImportMaterial(); +     +    LLSD asLLSD(); +     +    const LLUUID&	getDiffuseMap() const					{ return mDiffuseMapID;		} +    void				setDiffuseMap(const LLUUID& texId)	{ mDiffuseMapID = texId;	} +      protected: -	void addVolumeFacesFromDomMesh(domMesh* mesh); -	virtual BOOL createVolumeFacesFromDomMesh(domMesh *mesh); +     +    LLUUID		mDiffuseMapID; +    void*			mOpaqueData;	// allow refs to viewer/platform-specific structs for each material +    // currently only stores an LLPointer< LLViewerFetchedTexture > > to +    // maintain refs to textures associated with each material for free +    // ref counting.  }; +typedef std::map<std::string, LLImportMaterial> material_map; + +class LLModelInstanceBase +{ +public: +	LLPointer<LLModel> mModel; +	LLPointer<LLModel> mLOD[5]; +	LLUUID mMeshID; + +	LLMatrix4 mTransform; +	material_map mMaterial; + +	LLModelInstanceBase(LLModel* model, LLMatrix4& transform, material_map& materials) +		: mModel(model), mTransform(transform), mMaterial(materials) +	{ +	} + +	LLModelInstanceBase() +		: mModel(NULL) +	{ +	} +}; + +typedef std::vector<LLModelInstanceBase> model_instance_list; + +class LLModelInstance : public LLModelInstanceBase +{ +public: +	std::string mLabel; +	LLUUID mMeshID; +	S32 mLocalMeshID; + +	LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, material_map& materials) +		: LLModelInstanceBase(model, transform, materials), mLabel(label) +	{ +		mLocalMeshID = -1; +	} + +	LLModelInstance(LLSD& data); + +	LLSD asLLSD(); +}; + +#define LL_DEGENERACY_TOLERANCE  1e-7f + +inline F32 dot3fpu(const LLVector4a& a, const LLVector4a& b) +{ +	volatile F32 p0 = a[0] * b[0]; +	volatile F32 p1 = a[1] * b[1]; +	volatile F32 p2 = a[2] * b[2]; +	return p0 + p1 + p2; +} + +bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a& c, F32 tolerance = LL_DEGENERACY_TOLERANCE); + +bool validate_face(const LLVolumeFace& face); +bool validate_model(const LLModel* mdl); +  #endif //LL_LLMODEL_H diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp index 0db75a0e82..9e822e495c 100755 --- a/indra/llprimitive/lltextureentry.cpp +++ b/indra/llprimitive/lltextureentry.cpp @@ -191,6 +191,13 @@ bool LLTextureEntry::operator==(const LLTextureEntry &rhs) const  	return(true);  } +bool LLTextureEntry::operator <(const LLTextureEntry &rhs) const +{ +	if (mID < rhs.mID) return(true); +	if (mMaterialID < rhs.mMaterialID) return (true); +	return(false); +} +  LLSD LLTextureEntry::asLLSD() const  {  	LLSD sd; @@ -545,7 +552,7 @@ S32 LLTextureEntry::setMaterialID(const LLMaterialID& pMaterialID)  		{  			mMaterialUpdatePending = true;  			mMaterialID = pMaterialID; -			return TEM_CHANGE_TEXTURE; +			return TEM_CHANGE_NONE;  		}  		mMaterialUpdatePending = false; diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h index 19edcaa27d..a40c3988f2 100755 --- a/indra/llprimitive/lltextureentry.h +++ b/indra/llprimitive/lltextureentry.h @@ -89,6 +89,10 @@ public:  	bool operator==(const LLTextureEntry &rhs) const;  	bool operator!=(const LLTextureEntry &rhs) const; +	 +	// Added to allow use with std::map +	// +	bool operator <(const LLTextureEntry &rhs) const;  	LLSD asLLSD() const;  	void asLLSD(LLSD& sd) const; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 0bf0152b30..889e26b532 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -132,7 +132,6 @@ set(viewer_SOURCE_FILES      llbreadcrumbview.cpp      llbrowsernotification.cpp      llbuycurrencyhtml.cpp -    llcallbacklist.cpp      llcallingcard.cpp      llcapabilitylistener.cpp      llcaphttpsender.cpp @@ -720,7 +719,6 @@ set(viewer_HEADER_FILES      llbox.h      llbreadcrumbview.h      llbuycurrencyhtml.h -    llcallbacklist.h      llcallingcard.h      llcapabilitylistener.h      llcapabilityprovider.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index de11309394..4343c7f70c 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -2,6 +2,28 @@  <llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:noNamespaceSchemaLocation="llsd.xsd">  <map> +  <key>ImporterDebug</key> +  <map> +    <key>Comment</key> +    <string>Enable debug output to more precisely identify sources of import errors. Warning: the output can slow down import on many machines.</string> +    <key>Persist</key> +    <integer>0</integer> +    <key>Type</key> +    <string>Integer</string> +    <key>Value</key> +    <integer>0</integer> +  </map> +  <key>IMShowTime</key> +  <map> +    <key>Comment</key> +    <string>Enable(disable) timestamp showing in the chat.</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>Boolean</string> +    <key>Value</key> +    <integer>1</integer> +  </map>      <key>IMShowTime</key>      <map>        <key>Comment</key> diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 855836af7a..01809d38c1 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -26,35 +26,8 @@  #include "llviewerprecompiledheaders.h" -#if LL_MSVC -#pragma warning (disable : 4263) -#pragma warning (disable : 4264) -#endif -#include "dae.h" -//#include "dom.h" -#include "dom/domAsset.h" -#include "dom/domBind_material.h" -#include "dom/domCOLLADA.h" -#include "dom/domConstants.h" -#include "dom/domController.h" -#include "dom/domEffect.h" -#include "dom/domGeometry.h" -#include "dom/domInstance_geometry.h" -#include "dom/domInstance_material.h" -#include "dom/domInstance_node.h" -#include "dom/domInstance_effect.h" -#include "dom/domMaterial.h" -#include "dom/domMatrix.h" -#include "dom/domNode.h" -#include "dom/domProfile_COMMON.h" -#include "dom/domRotate.h" -#include "dom/domScale.h" -#include "dom/domTranslate.h" -#include "dom/domVisual_scene.h" -#if LL_MSVC -#pragma warning (default : 4263) -#pragma warning (default : 4264) -#endif +#include "llmodelloader.h" +#include "lldaeloader.h"  #include "llfloatermodelpreview.h" @@ -112,16 +85,13 @@  #include "llanimationstates.h"  #include "llviewernetwork.h"  #include "llviewershadermgr.h" +  #include "glod/glod.h"  #include <boost/algorithm/string.hpp> - -const S32 SLM_SUPPORTED_VERSION = 3; -  //static  S32 LLFloaterModelPreview::sUploadAmount = 10;  LLFloaterModelPreview* LLFloaterModelPreview::sInstance = NULL; -std::list<LLModelLoader*> LLModelLoader::sActiveLoaderList;  const S32 PREVIEW_BORDER_WIDTH = 2;  const S32 PREVIEW_RESIZE_HANDLE_SIZE = S32(RESIZE_HANDLE_WIDTH * OO_SQRT2) + PREVIEW_BORDER_WIDTH; @@ -207,190 +177,37 @@ std::string lod_label_name[NUM_LOD+1] =  	"I went off the end of the lod_label_name array.  Me so smart."  }; -std::string colladaVersion[VERSIONTYPE_COUNT+1] =  -{ -	"1.4.0", -	"1.4.1", -	"Unsupported" -}; - - -#define LL_DEGENERACY_TOLERANCE  1e-7f - -inline F32 dot3fpu(const LLVector4a& a, const LLVector4a& b) -{ -    volatile F32 p0 = a[0] * b[0]; -    volatile F32 p1 = a[1] * b[1]; -    volatile F32 p2 = a[2] * b[2]; -    return p0 + p1 + p2; -} - -bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a& c, F32 tolerance = LL_DEGENERACY_TOLERANCE) -{ -        // small area check -        { -                LLVector4a edge1; edge1.setSub( a, b ); -                LLVector4a edge2; edge2.setSub( a, c ); -                ////////////////////////////////////////////////////////////////////////// -                /// Linden Modified -                ////////////////////////////////////////////////////////////////////////// - -                // If no one edge is more than 10x longer than any other edge, we weaken -                // the tolerance by a factor of 1e-4f. - -                LLVector4a edge3; edge3.setSub( c, b ); -				const F32 len1sq = edge1.dot3(edge1).getF32(); -                const F32 len2sq = edge2.dot3(edge2).getF32(); -                const F32 len3sq = edge3.dot3(edge3).getF32(); -                bool abOK = (len1sq <= 100.f * len2sq) && (len1sq <= 100.f * len3sq); -                bool acOK = (len2sq <= 100.f * len1sq) && (len1sq <= 100.f * len3sq); -                bool cbOK = (len3sq <= 100.f * len1sq) && (len1sq <= 100.f * len2sq); -                if ( abOK && acOK && cbOK ) -                { -                        tolerance *= 1e-4f; -                } - -                ////////////////////////////////////////////////////////////////////////// -                /// End Modified -                ////////////////////////////////////////////////////////////////////////// - -                LLVector4a cross; cross.setCross3( edge1, edge2 ); - -                LLVector4a edge1b; edge1b.setSub( b, a ); -                LLVector4a edge2b; edge2b.setSub( b, c ); -                LLVector4a crossb; crossb.setCross3( edge1b, edge2b ); - -                if ( ( cross.dot3(cross).getF32() < tolerance ) || ( crossb.dot3(crossb).getF32() < tolerance )) -                { -                        return true; -                } -        } - -        // point triangle distance check -        { -                LLVector4a Q; Q.setSub(a, b); -                LLVector4a R; R.setSub(c, b); - -                const F32 QQ = dot3fpu(Q, Q); -                const F32 RR = dot3fpu(R, R); -                const F32 QR = dot3fpu(R, Q); - -                volatile F32 QQRR = QQ * RR; -                volatile F32 QRQR = QR * QR; -                F32 Det = (QQRR - QRQR); - -                if( Det == 0.0f ) -                { -                        return true; -                } -        } - -        return false; -} - -bool validate_face(const LLVolumeFace& face) +BOOL stop_gloderror()  { +	GLuint error = glodGetError(); -	for (U32 v = 0; v < face.mNumVertices; v++) -	{ -		if(face.mPositions && !face.mPositions[v].isFinite3()) -		{ -			llwarns << "NaN position data in face found!" << llendl; -			return false; -		} - -		if(face.mNormals && !face.mNormals[v].isFinite3()) -		{ -			llwarns << "NaN normal data in face found!" << llendl; -			return false; -		} -	} - -	for (U32 i = 0; i < face.mNumIndices; ++i) -	{ -		if (face.mIndices[i] >= face.mNumVertices) -		{ -			llwarns << "Face has invalid index." << llendl; -			return false; -		} -	} - -	if (face.mNumIndices % 3 != 0 || face.mNumIndices == 0) +	if (error != GLOD_NO_ERROR)  	{ -		llwarns << "Face has invalid number of indices." << llendl; -		return false; +		llwarns << "GLOD error detected, cannot generate LOD: " << std::hex << error << llendl; +		return TRUE;  	} - -	/*const LLVector4a scale(0.5f); - - -	for (U32 i = 0; i < face.mNumIndices; i+=3) -	{ -		U16 idx1 = face.mIndices[i]; -		U16 idx2 = face.mIndices[i+1]; -		U16 idx3 = face.mIndices[i+2]; - -		LLVector4a v1; v1.setMul(face.mPositions[idx1], scale); -		LLVector4a v2; v2.setMul(face.mPositions[idx2], scale); -		LLVector4a v3; v3.setMul(face.mPositions[idx3], scale); - -		if (ll_is_degenerate(v1,v2,v3)) -		{ -			llwarns << "Degenerate face found!" << llendl; -			return false; -		} -	}*/ -	return true; +	return FALSE;  } -bool validate_model(const LLModel* mdl) +LLViewerFetchedTexture* bindMaterialDiffuseTexture(const LLImportMaterial& material)  { -	if (mdl->getNumVolumeFaces() == 0) -	{ -		llwarns << "Model has no faces!" << llendl; -		return false; -	} +	LLViewerFetchedTexture *texture = LLViewerTextureManager::getFetchedTexture(material.getDiffuseMap(), FTT_DEFAULT, TRUE, LLGLTexture::BOOST_PREVIEW); -	for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i) +	if (texture)  	{ -		if (mdl->getVolumeFace(i).mNumVertices == 0) -		{ -			llwarns << "Face has no vertices." << llendl; -			return false; -		} - -		if (mdl->getVolumeFace(i).mNumIndices == 0) -		{ -			llwarns << "Face has no indices." << llendl; -			return false; -		} - -		if (!validate_face(mdl->getVolumeFace(i))) +		if (texture->getDiscardLevel() > -1)  		{ -			return false; +			gGL.getTexUnit(0)->bind(texture, true); +			return texture;  		}  	} -	return true; -} - -BOOL stop_gloderror() -{ -	GLuint error = glodGetError(); - -	if (error != GLOD_NO_ERROR) -	{ -		llwarns << "GLOD error detected, cannot generate LOD: " << std::hex << error << llendl; -		return TRUE; -	} - -	return FALSE; +	return NULL;  } -  LLMeshFilePicker::LLMeshFilePicker(LLModelPreview* mp, S32 lod) -	: LLFilePickerThread(LLFilePicker::FFLOAD_COLLADA) +: LLFilePickerThread(LLFilePicker::FFLOAD_COLLADA)  	{  		mMP = mp;  		mLOD = lod; @@ -401,6 +218,29 @@ void LLMeshFilePicker::notify(const std::string& filename)  	mMP->loadModel(mFile, mLOD);  } +void FindModel(LLModelLoader::scene& scene, const std::string& name_to_match, LLModel*& baseModelOut, LLMatrix4& matOut) +{ +    LLModelLoader::scene::iterator base_iter = scene.begin(); +    bool found = false; +    while (!found && (base_iter != scene.end())) +    { +        matOut = base_iter->first; + +        LLModelLoader::model_instance_list::iterator base_instance_iter = base_iter->second.begin(); +        while (!found && (base_instance_iter != base_iter->second.end())) +        { +		    LLModelInstance& base_instance = *base_instance_iter++;					    		     +            LLModel* base_model = base_instance.mModel; +          +            if (base_model && (base_model->mLabel == name_to_match)) +            { +                baseModelOut = base_model; +                return; +            } +        } +        base_iter++; +    } +}  //-----------------------------------------------------------------------------  // LLFloaterModelPreview() @@ -535,16 +375,9 @@ BOOL LLFloaterModelPreview::postBuild()  	mUploadBtn = getChild<LLButton>("ok_btn");  	mCalculateBtn = getChild<LLButton>("calculate_btn"); -	if (LLConvexDecomposition::getInstance() != NULL) -	{ -		mCalculateBtn->setClickedCallback(boost::bind(&LLFloaterModelPreview::onClickCalculateBtn, this)); +	mCalculateBtn->setClickedCallback(boost::bind(&LLFloaterModelPreview::onClickCalculateBtn, this)); -		toggleCalculateButton(true); -	} -	else -	{ -		mCalculateBtn->setEnabled(false); -	} +	toggleCalculateButton(true);  	return TRUE;  } @@ -801,7 +634,7 @@ void LLFloaterModelPreview::draw()  		else  		if ( mModelPreview->getLoadState() == LLModelLoader::ERROR_PARSING )  		{ -			childSetTextArg("status", "[STATUS]", getString("status_parse_error")); +			childSetTextArg("status", "[STATUS]", getString("status_parse_error_dae"));  			toggleCalculateButton(false);  		}  		else @@ -1311,1813 +1144,6 @@ void LLFloaterModelPreview::onMouseCaptureLostModelPreview(LLMouseHandler* handl  }  //----------------------------------------------------------------------------- -// LLModelLoader -//----------------------------------------------------------------------------- -LLModelLoader::LLModelLoader( std::string filename, S32 lod, LLModelPreview* preview, JointTransformMap& jointMap,  -							  std::deque<std::string>& jointsFromNodes ) -: mJointList( jointMap ) -, mJointsFromNode( jointsFromNodes ) -, LLThread("Model Loader"), mFilename(filename), mLod(lod), mPreview(preview), mFirstTransform(TRUE), mNumOfFetchingTextures(0) -{ -	mJointMap["mPelvis"] = "mPelvis"; -	mJointMap["mTorso"] = "mTorso"; -	mJointMap["mChest"] = "mChest"; -	mJointMap["mNeck"] = "mNeck"; -	mJointMap["mHead"] = "mHead"; -	mJointMap["mSkull"] = "mSkull"; -	mJointMap["mEyeRight"] = "mEyeRight"; -	mJointMap["mEyeLeft"] = "mEyeLeft"; -	mJointMap["mCollarLeft"] = "mCollarLeft"; -	mJointMap["mShoulderLeft"] = "mShoulderLeft"; -	mJointMap["mElbowLeft"] = "mElbowLeft"; -	mJointMap["mWristLeft"] = "mWristLeft"; -	mJointMap["mCollarRight"] = "mCollarRight"; -	mJointMap["mShoulderRight"] = "mShoulderRight"; -	mJointMap["mElbowRight"] = "mElbowRight"; -	mJointMap["mWristRight"] = "mWristRight"; -	mJointMap["mHipRight"] = "mHipRight"; -	mJointMap["mKneeRight"] = "mKneeRight"; -	mJointMap["mAnkleRight"] = "mAnkleRight"; -	mJointMap["mFootRight"] = "mFootRight"; -	mJointMap["mToeRight"] = "mToeRight"; -	mJointMap["mHipLeft"] = "mHipLeft"; -	mJointMap["mKneeLeft"] = "mKneeLeft"; -	mJointMap["mAnkleLeft"] = "mAnkleLeft"; -	mJointMap["mFootLeft"] = "mFootLeft"; -	mJointMap["mToeLeft"] = "mToeLeft"; - -	mJointMap["avatar_mPelvis"] = "mPelvis"; -	mJointMap["avatar_mTorso"] = "mTorso"; -	mJointMap["avatar_mChest"] = "mChest"; -	mJointMap["avatar_mNeck"] = "mNeck"; -	mJointMap["avatar_mHead"] = "mHead"; -	mJointMap["avatar_mSkull"] = "mSkull"; -	mJointMap["avatar_mEyeRight"] = "mEyeRight"; -	mJointMap["avatar_mEyeLeft"] = "mEyeLeft"; -	mJointMap["avatar_mCollarLeft"] = "mCollarLeft"; -	mJointMap["avatar_mShoulderLeft"] = "mShoulderLeft"; -	mJointMap["avatar_mElbowLeft"] = "mElbowLeft"; -	mJointMap["avatar_mWristLeft"] = "mWristLeft"; -	mJointMap["avatar_mCollarRight"] = "mCollarRight"; -	mJointMap["avatar_mShoulderRight"] = "mShoulderRight"; -	mJointMap["avatar_mElbowRight"] = "mElbowRight"; -	mJointMap["avatar_mWristRight"] = "mWristRight"; -	mJointMap["avatar_mHipRight"] = "mHipRight"; -	mJointMap["avatar_mKneeRight"] = "mKneeRight"; -	mJointMap["avatar_mAnkleRight"] = "mAnkleRight"; -	mJointMap["avatar_mFootRight"] = "mFootRight"; -	mJointMap["avatar_mToeRight"] = "mToeRight"; -	mJointMap["avatar_mHipLeft"] = "mHipLeft"; -	mJointMap["avatar_mKneeLeft"] = "mKneeLeft"; -	mJointMap["avatar_mAnkleLeft"] = "mAnkleLeft"; -	mJointMap["avatar_mFootLeft"] = "mFootLeft"; -	mJointMap["avatar_mToeLeft"] = "mToeLeft"; - - -	mJointMap["hip"] = "mPelvis"; -	mJointMap["abdomen"] = "mTorso"; -	mJointMap["chest"] = "mChest"; -	mJointMap["neck"] = "mNeck"; -	mJointMap["head"] = "mHead"; -	mJointMap["figureHair"] = "mSkull"; -	mJointMap["lCollar"] = "mCollarLeft"; -	mJointMap["lShldr"] = "mShoulderLeft"; -	mJointMap["lForeArm"] = "mElbowLeft"; -	mJointMap["lHand"] = "mWristLeft"; -	mJointMap["rCollar"] = "mCollarRight"; -	mJointMap["rShldr"] = "mShoulderRight"; -	mJointMap["rForeArm"] = "mElbowRight"; -	mJointMap["rHand"] = "mWristRight"; -	mJointMap["rThigh"] = "mHipRight"; -	mJointMap["rShin"] = "mKneeRight"; -	mJointMap["rFoot"] = "mFootRight"; -	mJointMap["lThigh"] = "mHipLeft"; -	mJointMap["lShin"] = "mKneeLeft"; -	mJointMap["lFoot"] = "mFootLeft"; - -	if (mPreview) -	{ -		//only try to load from slm if viewer is configured to do so and this is the  -		//initial model load (not an LoD or physics shape) -		mTrySLM = gSavedSettings.getBOOL("MeshImportUseSLM") && mPreview->mUploadData.empty(); -		mPreview->setLoadState(STARTING); -	} -	else -	{ -		mTrySLM = false; -	} - -	assert_main_thread(); -	sActiveLoaderList.push_back(this) ; -} - -LLModelLoader::~LLModelLoader() -{ -	assert_main_thread(); -	sActiveLoaderList.remove(this); -} - -void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform) -{ -	LLVector4a box[] = -	{ -		LLVector4a(-1, 1,-1), -		LLVector4a(-1, 1, 1), -		LLVector4a(-1,-1,-1), -		LLVector4a(-1,-1, 1), -		LLVector4a( 1, 1,-1), -		LLVector4a( 1, 1, 1), -		LLVector4a( 1,-1,-1), -		LLVector4a( 1,-1, 1), -	}; - -	for (S32 j = 0; j < model->getNumVolumeFaces(); ++j) -	{ -		const LLVolumeFace& face = model->getVolumeFace(j); - -		LLVector4a center; -		center.setAdd(face.mExtents[0], face.mExtents[1]); -		center.mul(0.5f); -		LLVector4a size; -		size.setSub(face.mExtents[1],face.mExtents[0]); -		size.mul(0.5f); - -		for (U32 i = 0; i < 8; i++) -		{ -			LLVector4a t; -			t.setMul(size, box[i]); -			t.add(center); - -			LLVector4a v; - -			mat.affineTransform(t, v); - -			if (first_transform) -			{ -				first_transform = FALSE; -				min = max = v; -			} -			else -			{ -				update_min_max(min, max, v); -			} -		} -	} -} - -void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, BOOL& first_transform) -{ -	LLVector4a mina, maxa; -	LLMatrix4a mata; - -	mata.loadu(mat); -	mina.load3(min.mV); -	maxa.load3(max.mV); - -	stretch_extents(model, mata, mina, maxa, first_transform); - -	min.set(mina.getF32ptr()); -	max.set(maxa.getF32ptr()); -} - -void LLModelLoader::run() -{ -	doLoadModel(); -	doOnIdleOneTime(boost::bind(&LLModelLoader::loadModelCallback,this)); -} - -bool LLModelLoader::doLoadModel() -{ -	//first, look for a .slm file of the same name that was modified later -	//than the .dae - -	if (mTrySLM) -	{ -		std::string filename = mFilename; -			 -		std::string::size_type i = filename.rfind("."); -		if (i != std::string::npos) -		{ -			filename.replace(i, filename.size()-1, ".slm"); -			llstat slm_status; -			if (LLFile::stat(filename, &slm_status) == 0) -			{ //slm file exists -				llstat dae_status; -				if (LLFile::stat(mFilename, &dae_status) != 0 || -					dae_status.st_mtime < slm_status.st_mtime) -				{ -					if (loadFromSLM(filename)) -					{ //slm successfully loaded, if this fails, fall through and -						//try loading from dae - -						mLod = -1; //successfully loading from an slm implicitly sets all  -									//LoDs -						return true; -					} -				} -			}	 -		} -	} - -	//no suitable slm exists, load from the .dae file -	DAE dae; -	domCOLLADA* dom = dae.open(mFilename); -	 -	if (!dom) -	{ -		llinfos<<" Error with dae - traditionally indicates a corrupt file."<<llendl; -		setLoadState( ERROR_PARSING ); -		return false; -	} -	//Dom version -	daeString domVersion = dae.getDomVersion(); -	std::string sldom(domVersion); -	llinfos<<"Collada Importer Version: "<<sldom<<llendl; -	//Dae version -	domVersionType docVersion = dom->getVersion(); -	//0=1.4 -	//1=1.4.1 -	//2=Currently unsupported, however may work -	if (docVersion > 1 )  -	{  -		docVersion = VERSIONTYPE_COUNT; -	} -	llinfos<<"Dae version "<<colladaVersion[docVersion]<<llendl; -	 -	 -	daeDatabase* db = dae.getDatabase(); -	 -	daeInt count = db->getElementCount(NULL, COLLADA_TYPE_MESH); -	 -	daeDocument* doc = dae.getDoc(mFilename); -	if (!doc) -	{ -		llwarns << "can't find internal doc" << llendl; -		return false; -	} -	 -	daeElement* root = doc->getDomRoot(); -	if (!root) -	{ -		llwarns << "document has no root" << llendl; -		return false; -	} -	 -	//Verify some basic properties of the dae -	//1. Basic validity check on controller  -	U32 controllerCount = (int) db->getElementCount( NULL, "controller" ); -	bool result = false; -	for ( int i=0; i<controllerCount; ++i ) -	{ -		domController* pController = NULL; -		db->getElement( (daeElement**) &pController, i , NULL, "controller" ); -		result = mPreview->verifyController( pController ); -		if (!result) -		{ -			setLoadState( ERROR_PARSING ); -			return true; -		} -	} - - -	//get unit scale -	mTransform.setIdentity(); -	 -	domAsset::domUnit* unit = daeSafeCast<domAsset::domUnit>(root->getDescendant(daeElement::matchType(domAsset::domUnit::ID()))); -	 -	if (unit) -	{ -		F32 meter = unit->getMeter(); -		mTransform.mMatrix[0][0] = meter; -		mTransform.mMatrix[1][1] = meter; -		mTransform.mMatrix[2][2] = meter; -	} -	 -	//get up axis rotation -	LLMatrix4 rotation; -	 -	domUpAxisType up = UPAXISTYPE_Y_UP;  // default is Y_UP -	domAsset::domUp_axis* up_axis = -	daeSafeCast<domAsset::domUp_axis>(root->getDescendant(daeElement::matchType(domAsset::domUp_axis::ID()))); -	 -	if (up_axis) -	{ -		up = up_axis->getValue(); -	} -	 -	if (up == UPAXISTYPE_X_UP) -	{ -		rotation.initRotation(0.0f, 90.0f * DEG_TO_RAD, 0.0f); -	} -	else if (up == UPAXISTYPE_Y_UP) -	{ -		rotation.initRotation(90.0f * DEG_TO_RAD, 0.0f, 0.0f); -	} -	 -	rotation *= mTransform; -	mTransform = rotation; -	 -	 -	for (daeInt idx = 0; idx < count; ++idx) -	{ //build map of domEntities to LLModel -		domMesh* mesh = NULL; -		db->getElement((daeElement**) &mesh, idx, NULL, COLLADA_TYPE_MESH); -		 -		if (mesh) -		{ -			LLPointer<LLModel> model = LLModel::loadModelFromDomMesh(mesh); -			 -			if(model->getStatus() != LLModel::NO_ERRORS) -			{ -				setLoadState(ERROR_PARSING + model->getStatus()) ; -				return false; //abort -			} - -			if (model.notNull() && validate_model(model)) -			{ -				mModelList.push_back(model); -				mModel[mesh] = model; -			} -		} -	} -	 -	count = db->getElementCount(NULL, COLLADA_TYPE_SKIN); -	for (daeInt idx = 0; idx < count; ++idx) -	{ //add skinned meshes as instances -		domSkin* skin = NULL; -		db->getElement((daeElement**) &skin, idx, NULL, COLLADA_TYPE_SKIN); -		 -		if (skin) -		{ -			domGeometry* geom = daeSafeCast<domGeometry>(skin->getSource().getElement()); -			 -			if (geom) -			{ -				domMesh* mesh = geom->getMesh(); -				if (mesh) -				{ -					LLModel* model = mModel[mesh]; -					if (model) -					{ -						LLVector3 mesh_scale_vector; -						LLVector3 mesh_translation_vector; -						model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector); -						 -						LLMatrix4 normalized_transformation; -						normalized_transformation.setTranslation(mesh_translation_vector); -						 -						LLMatrix4 mesh_scale; -						mesh_scale.initScale(mesh_scale_vector); -						mesh_scale *= normalized_transformation; -						normalized_transformation = mesh_scale; -						 -						glh::matrix4f inv_mat((F32*) normalized_transformation.mMatrix); -						inv_mat = inv_mat.inverse(); -						LLMatrix4 inverse_normalized_transformation(inv_mat.m); -						 -						domSkin::domBind_shape_matrix* bind_mat = skin->getBind_shape_matrix(); -						 -						if (bind_mat) -						{ //get bind shape matrix -							domFloat4x4& dom_value = bind_mat->getValue(); -							 -							LLMeshSkinInfo& skin_info = model->mSkinInfo; - -							for (int i = 0; i < 4; i++) -							{ -								for(int j = 0; j < 4; j++) -								{ -									skin_info.mBindShapeMatrix.mMatrix[i][j] = dom_value[i + j*4]; -								} -							} -							 -							LLMatrix4 trans = normalized_transformation; -							trans *= skin_info.mBindShapeMatrix; -							skin_info.mBindShapeMatrix = trans;							 -						} -										 -											 -						//Some collada setup for accessing the skeleton -						daeElement* pElement = 0; -						dae.getDatabase()->getElement( &pElement, 0, 0, "skeleton" ); -						 -						//Try to get at the skeletal instance controller -						domInstance_controller::domSkeleton* pSkeleton = daeSafeCast<domInstance_controller::domSkeleton>( pElement ); -						bool missingSkeletonOrScene = false; -						 -						//If no skeleton, do a breadth-first search to get at specific joints -						bool rootNode = false; -						 -						//Need to test for a skeleton that does not have a root node -						//This occurs when your instance controller does not have an associated scene  -						if ( pSkeleton ) -						{ -							daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement(); -							if ( pSkeletonRootNode ) -							{ -								rootNode = true; -							} - -						} -						if ( !pSkeleton || !rootNode ) -						{ -							daeElement* pScene = root->getDescendant("visual_scene"); -							if ( !pScene ) -							{ -								llwarns<<"No visual scene - unable to parse bone offsets "<<llendl; -								missingSkeletonOrScene = true; -							} -							else -							{ -								//Get the children at this level -								daeTArray< daeSmartRef<daeElement> > children = pScene->getChildren(); -								S32 childCount = children.getCount(); -								 -								//Process any children that are joints -								//Not all children are joints, some code be ambient lights, cameras, geometry etc.. -								for (S32 i = 0; i < childCount; ++i) -								{ -									domNode* pNode = daeSafeCast<domNode>(children[i]); -									if ( isNodeAJoint( pNode ) ) -									{ -										processJointNode( pNode, mJointList ); -									} -								} -							} -						} -						else -							//Has Skeleton -						{ -							//Get the root node of the skeleton -							daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement(); -							if ( pSkeletonRootNode ) -							{ -								//Once we have the root node - start acccessing it's joint components -								const int jointCnt = mJointMap.size(); -								std::map<std::string, std::string> :: const_iterator jointIt = mJointMap.begin(); -								 -								//Loop over all the possible joints within the .dae - using the allowed joint list in the ctor. -								for ( int i=0; i<jointCnt; ++i, ++jointIt ) -								{ -									//Build a joint for the resolver to work with -									char str[64]={0}; -									sprintf(str,"./%s",(*jointIt).first.c_str() ); -									//llwarns<<"Joint "<< str <<llendl; -									 -									//Setup the resolver -                                    daeSIDResolver resolver( pSkeletonRootNode, str ); -									 -                                    //Look for the joint -                                    domNode* pJoint = daeSafeCast<domNode>( resolver.getElement() ); -                                    if ( pJoint ) -                                    { -										//Pull out the translate id and store it in the jointTranslations map -										daeSIDResolver jointResolverA( pJoint, "./translate" ); -										domTranslate* pTranslateA = daeSafeCast<domTranslate>( jointResolverA.getElement() ); -										daeSIDResolver jointResolverB( pJoint, "./location" ); -										domTranslate* pTranslateB = daeSafeCast<domTranslate>( jointResolverB.getElement() ); -										 -										LLMatrix4 workingTransform; -										 -										//Translation via SID -										if ( pTranslateA ) -										{ -											extractTranslation( pTranslateA, workingTransform ); -										} -										else -										if ( pTranslateB ) -										{ -											extractTranslation( pTranslateB, workingTransform ); -										} -										else -										{ -											//Translation via child from element -											daeElement* pTranslateElement = getChildFromElement( pJoint, "translate" ); -											if ( pTranslateElement && pTranslateElement->typeID() != domTranslate::ID() ) -											{ -												llwarns<< "The found element is not a translate node" <<llendl; -												missingSkeletonOrScene = true; -											} -											else -											if ( pTranslateElement ) -											{ -												extractTranslationViaElement( pTranslateElement, workingTransform ); -											} -											else -											{ -												extractTranslationViaSID( pJoint, workingTransform ); -											} - -										} -										 -										//Store the joint transform w/respect to it's name. -										mJointList[(*jointIt).second.c_str()] = workingTransform; -                                    } -								} -								 -								//If anything failed in regards to extracting the skeleton, joints or translation id, -								//mention it -								if ( missingSkeletonOrScene  ) -								{ -									llwarns<< "Partial jointmap found in asset - did you mean to just have a partial map?" << llendl; -								} -							}//got skeleton? -						} -						 -						 -						domSkin::domJoints* joints = skin->getJoints(); -						 -						domInputLocal_Array& joint_input = joints->getInput_array(); -						 -						for (size_t i = 0; i < joint_input.getCount(); ++i) -						{ -							domInputLocal* input = joint_input.get(i); -							xsNMTOKEN semantic = input->getSemantic(); -							 -							if (strcmp(semantic, COMMON_PROFILE_INPUT_JOINT) == 0) -							{ //found joint source, fill model->mJointMap and model->mSkinInfo.mJointNames -								daeElement* elem = input->getSource().getElement(); -								 -								domSource* source = daeSafeCast<domSource>(elem); -								if (source) -								{ -									 -									 -									domName_array* names_source = source->getName_array(); -									 -									if (names_source) -									{ -										domListOfNames &names = names_source->getValue(); -										 -										for (size_t j = 0; j < names.getCount(); ++j) -										{ -											std::string name(names.get(j)); -											if (mJointMap.find(name) != mJointMap.end()) -											{ -												name = mJointMap[name]; -											} -											model->mSkinInfo.mJointNames.push_back(name); -											model->mSkinInfo.mJointMap[name] = j; -										} -									} -									else -									{ -										domIDREF_array* names_source = source->getIDREF_array(); -										if (names_source) -										{ -											xsIDREFS& names = names_source->getValue(); -											 -											for (size_t j = 0; j < names.getCount(); ++j) -											{ -												std::string name(names.get(j).getID()); -												if (mJointMap.find(name) != mJointMap.end()) -												{ -													name = mJointMap[name]; -												} -												model->mSkinInfo.mJointNames.push_back(name); -												model->mSkinInfo.mJointMap[name] = j; -											} -										} -									} -								} -							} -							else if (strcmp(semantic, COMMON_PROFILE_INPUT_INV_BIND_MATRIX) == 0) -							{ //found inv_bind_matrix array, fill model->mInvBindMatrix -								domSource* source = daeSafeCast<domSource>(input->getSource().getElement()); -								if (source) -								{ -									domFloat_array* t = source->getFloat_array(); -									if (t) -									{ -										domListOfFloats& transform = t->getValue(); -										S32 count = transform.getCount()/16; -										 -										for (S32 k = 0; k < count; ++k) -										{ -											LLMatrix4 mat; -											 -											for (int i = 0; i < 4; i++) -											{ -												for(int j = 0; j < 4; j++) -												{ -													mat.mMatrix[i][j] = transform[k*16 + i + j*4]; -												} -											} -											 -											model->mSkinInfo.mInvBindMatrix.push_back(mat);											 -										} -									} -								} -							} -						} -						 -						//Now that we've parsed the joint array, let's determine if we have a full rig -						//(which means we have all the joint sthat are required for an avatar versus -						//a skinned asset attached to a node in a file that contains an entire skeleton, -						//but does not use the skeleton).						 -						buildJointToNodeMappingFromScene( root ); -						mPreview->critiqueRigForUploadApplicability( model->mSkinInfo.mJointNames ); -										 -						if ( !missingSkeletonOrScene ) -						{ -							//Set the joint translations on the avatar - if it's a full mapping -							//The joints are reset in the dtor -							if ( mPreview->getRigWithSceneParity() ) -							{	 -								std::map<std::string, std::string> :: const_iterator masterJointIt = mJointMap.begin(); -								std::map<std::string, std::string> :: const_iterator masterJointItEnd = mJointMap.end(); -								for (;masterJointIt!=masterJointItEnd;++masterJointIt ) -								{ -									std::string lookingForJoint = (*masterJointIt).first.c_str(); -									 -									if ( mJointList.find( lookingForJoint ) != mJointList.end() ) -									{ -										//llinfos<<"joint "<<lookingForJoint.c_str()<<llendl; -										LLMatrix4 jointTransform = mJointList[lookingForJoint]; -										LLJoint* pJoint = mPreview->getPreviewAvatar()->getJoint( lookingForJoint ); -										if ( pJoint ) -										{    -											pJoint->storeCurrentXform( jointTransform.getTranslation() );												 -										} -										else -										{ -											//Most likely an error in the asset. -											llwarns<<"Tried to apply joint position from .dae, but it did not exist in the avatar rig." << llendl; -										} -									} -								} -							} -						} //missingSkeletonOrScene -						 -						 -						//We need to construct the alternate bind matrix (which contains the new joint positions) -						//in the same order as they were stored in the joint buffer. The joints associated -						//with the skeleton are not stored in the same order as they are in the exported joint buffer. -						//This remaps the skeletal joints to be in the same order as the joints stored in the model. -						std::vector<std::string> :: const_iterator jointIt  = model->mSkinInfo.mJointNames.begin(); -						const int jointCnt = model->mSkinInfo.mJointNames.size(); -						for ( int i=0; i<jointCnt; ++i, ++jointIt ) -						{ -							std::string lookingForJoint = (*jointIt).c_str(); -							//Look for the joint xform that we extracted from the skeleton, using the jointIt as the key -							//and store it in the alternate bind matrix -							if ( mJointList.find( lookingForJoint ) != mJointList.end() ) -							{ -								LLMatrix4 jointTransform = mJointList[lookingForJoint]; -								LLMatrix4 newInverse = model->mSkinInfo.mInvBindMatrix[i]; -								newInverse.setTranslation( mJointList[lookingForJoint].getTranslation() ); -								model->mSkinInfo.mAlternateBindMatrix.push_back( newInverse ); -							} -							else -							{ -								llwarns<<"Possibly misnamed/missing joint [" <<lookingForJoint.c_str()<<" ] "<<llendl; -							} -						} -						 -						//grab raw position array -						 -						domVertices* verts = mesh->getVertices(); -						if (verts) -						{ -							domInputLocal_Array& inputs = verts->getInput_array(); -							for (size_t i = 0; i < inputs.getCount() && model->mPosition.empty(); ++i) -							{ -								if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_POSITION) == 0) -								{ -									domSource* pos_source = daeSafeCast<domSource>(inputs[i]->getSource().getElement()); -									if (pos_source) -									{ -										domFloat_array* pos_array = pos_source->getFloat_array(); -										if (pos_array) -										{ -											domListOfFloats& pos = pos_array->getValue(); -											 -											for (size_t j = 0; j < pos.getCount(); j += 3) -											{ -												if (pos.getCount() <= j+2) -												{ -													llerrs << "Invalid position array size." << llendl; -												} -												 -												LLVector3 v(pos[j], pos[j+1], pos[j+2]); -												 -												//transform from COLLADA space to volume space -												v = v * inverse_normalized_transformation; -												 -												model->mPosition.push_back(v); -											} -										} -									} -								} -							} -						} -						 -						//grab skin weights array -						domSkin::domVertex_weights* weights = skin->getVertex_weights(); -						if (weights) -						{ -							domInputLocalOffset_Array& inputs = weights->getInput_array(); -							domFloat_array* vertex_weights = NULL; -							for (size_t i = 0; i < inputs.getCount(); ++i) -							{ -								if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_WEIGHT) == 0) -								{ -									domSource* weight_source = daeSafeCast<domSource>(inputs[i]->getSource().getElement()); -									if (weight_source) -									{ -										vertex_weights = weight_source->getFloat_array(); -									} -								} -							} -							 -							if (vertex_weights) -							{ -								domListOfFloats& w = vertex_weights->getValue(); -								domListOfUInts& vcount = weights->getVcount()->getValue(); -								domListOfInts& v = weights->getV()->getValue(); -								 -								U32 c_idx = 0; -								for (size_t vc_idx = 0; vc_idx < vcount.getCount(); ++vc_idx) -								{ //for each vertex -									daeUInt count = vcount[vc_idx]; -									 -									//create list of weights that influence this vertex -									LLModel::weight_list weight_list; -									 -									for (daeUInt i = 0; i < count; ++i) -									{ //for each weight -										daeInt joint_idx = v[c_idx++]; -										daeInt weight_idx = v[c_idx++]; -										 -										if (joint_idx == -1) -										{ -											//ignore bindings to bind_shape_matrix -											continue; -										} -										 -										F32 weight_value = w[weight_idx]; -										 -										weight_list.push_back(LLModel::JointWeight(joint_idx, weight_value)); -									} -									 -									//sort by joint weight -									std::sort(weight_list.begin(), weight_list.end(), LLModel::CompareWeightGreater()); -									 -									std::vector<LLModel::JointWeight> wght; -									 -									F32 total = 0.f; -									 -									for (U32 i = 0; i < llmin((U32) 4, (U32) weight_list.size()); ++i) -									{ //take up to 4 most significant weights -										if (weight_list[i].mWeight > 0.f) -										{ -											wght.push_back( weight_list[i] ); -											total += weight_list[i].mWeight; -										} -									} -									 -									F32 scale = 1.f/total; -									if (scale != 1.f) -									{ //normalize weights -										for (U32 i = 0; i < wght.size(); ++i) -										{ -											wght[i].mWeight *= scale; -										} -									} -									 -									model->mSkinWeights[model->mPosition[vc_idx]] = wght; -								} -								 -								//add instance to scene for this model -								 -								LLMatrix4 transformation = mTransform; -								// adjust the transformation to compensate for mesh normalization -								 -								LLMatrix4 mesh_translation; -								mesh_translation.setTranslation(mesh_translation_vector); -								mesh_translation *= transformation; -								transformation = mesh_translation; -								 -								LLMatrix4 mesh_scale; -								mesh_scale.initScale(mesh_scale_vector); -								mesh_scale *= transformation; -								transformation = mesh_scale; -								 -								std::map<std::string, LLImportMaterial> materials; -								for (U32 i = 0; i < model->mMaterialList.size(); ++i) -								{ -									materials[model->mMaterialList[i]] = LLImportMaterial(); -								} -								mScene[transformation].push_back(LLModelInstance(model, model->mLabel, transformation, materials)); -								stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform); -							} -						} -					} -				} -			} -		} -	} -	 -	daeElement* scene = root->getDescendant("visual_scene"); -	 -	if (!scene) -	{ -		llwarns << "document has no visual_scene" << llendl; -		setLoadState( ERROR_PARSING ); -		return true; -	} -	 -	setLoadState( DONE ); - -	bool badElement = false; -	 -	processElement( scene, badElement ); -	 -	if ( badElement ) -	{ -		setLoadState( ERROR_PARSING ); -	} -	 -	return true; -} - -void LLModelLoader::setLoadState(U32 state) -{ -	if (mPreview) -	{ -		mPreview->setLoadState(state); -	} -} - -bool LLModelLoader::loadFromSLM(const std::string& filename) -{  -	//only need to populate mScene with data from slm -	llstat stat; - -	if (LLFile::stat(filename, &stat)) -	{ //file does not exist -		return false; -	} - -	S32 file_size = (S32) stat.st_size; -	 -	llifstream ifstream(filename, std::ifstream::in | std::ifstream::binary); -	LLSD data; -	LLSDSerialize::fromBinary(data, ifstream, file_size); -	ifstream.close(); - -	//build model list for each LoD -	model_list model[LLModel::NUM_LODS]; - -	if (data["version"].asInteger() != SLM_SUPPORTED_VERSION) -	{  //unsupported version -		return false; -	} - -	LLSD& mesh = data["mesh"]; - -	LLVolumeParams volume_params; -	volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); - -	for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod) -	{ -		for (U32 i = 0; i < mesh.size(); ++i) -		{ -			std::stringstream str(mesh[i].asString()); -			LLPointer<LLModel> loaded_model = new LLModel(volume_params, (F32) lod); -			if (loaded_model->loadModel(str)) -			{ -				loaded_model->mLocalID = i; -				model[lod].push_back(loaded_model); - -				if (lod == LLModel::LOD_HIGH && !loaded_model->mSkinInfo.mJointNames.empty()) -				{  -					//check to see if rig is valid					 -					mPreview->critiqueRigForUploadApplicability( loaded_model->mSkinInfo.mJointNames );					 -				} -			} -		} -	}	 - -	if (model[LLModel::LOD_HIGH].empty()) -	{ //failed to load high lod -		return false; -	} - -	// Set name. -	std::string name = data["name"]; -	if (!name.empty()) -	{ -		model[LLModel::LOD_HIGH][0]->mLabel = name; -	} -	 - -	//load instance list -	model_instance_list instance_list; - -	LLSD& instance = data["instance"]; - -	for (U32 i = 0; i < instance.size(); ++i) -	{ -		//deserialize instance list -		instance_list.push_back(LLModelInstance(instance[i])); - -		//match up model instance pointers -		S32 idx = instance_list[i].mLocalMeshID; - -		for (U32 lod = 0; lod < LLModel::NUM_LODS; ++lod) -		{ -			if (!model[lod].empty()) -			{ -				instance_list[i].mLOD[lod] = model[lod][idx]; -			} -		} - -		instance_list[i].mModel = model[LLModel::LOD_HIGH][idx]; -	} - - -	//convert instance_list to mScene -	mFirstTransform = TRUE; -	for (U32 i = 0; i < instance_list.size(); ++i) -	{ -		LLModelInstance& cur_instance = instance_list[i]; -		mScene[cur_instance.mTransform].push_back(cur_instance); -		stretch_extents(cur_instance.mModel, cur_instance.mTransform, mExtents[0], mExtents[1], mFirstTransform); -	} -	 -	setLoadState( DONE ); - -	return true; -} - -//static -bool LLModelLoader::isAlive(LLModelLoader* loader) -{ -	if(!loader) -	{ -		return false ; -	} - -	std::list<LLModelLoader*>::iterator iter = sActiveLoaderList.begin() ; -	for(; iter != sActiveLoaderList.end() && (*iter) != loader; ++iter) ; -	 -	return *iter == loader ; -} - -void LLModelLoader::loadModelCallback() -{ -	assert_main_thread(); - -	if (mPreview) -	{ -		mPreview->loadModelCallback(mLod);	 -	} - -	while (!isStopped()) -	{ //wait until this thread is stopped before deleting self -		apr_sleep(100); -	} - -	//doubel check if "this" is valid before deleting it, in case it is aborted during running. -	if(!isAlive(this)) -	{ -		return ; -	} - -	//cleanup model loader -	if (mPreview) -	{ -		mPreview->mModelLoader = NULL; -	} - -	delete this; -} -//----------------------------------------------------------------------------- -// buildJointToNodeMappingFromScene() -//----------------------------------------------------------------------------- -void LLModelLoader::buildJointToNodeMappingFromScene( daeElement* pRoot ) -{ -	daeElement* pScene = pRoot->getDescendant("visual_scene"); -	if ( pScene ) -	{ -		daeTArray< daeSmartRef<daeElement> > children = pScene->getChildren(); -		S32 childCount = children.getCount(); -		for (S32 i = 0; i < childCount; ++i) -		{ -			domNode* pNode = daeSafeCast<domNode>(children[i]); -			processJointToNodeMapping( pNode );			 -		} -	} -} -//----------------------------------------------------------------------------- -// processJointToNodeMapping() -//----------------------------------------------------------------------------- -void LLModelLoader::processJointToNodeMapping( domNode* pNode ) -{ -	if ( isNodeAJoint( pNode ) ) -	{ -		//1.Store the parent -		std::string nodeName = pNode->getName(); -		if ( !nodeName.empty() ) -		{ -			mJointsFromNode.push_front( pNode->getName() ); -		} -		//2. Handle the kiddo's -		processChildJoints( pNode ); -	} -	else -	{ -		//Determine if the're any children wrt to this failed node. -		//This occurs when an armature is exported and ends up being what essentially amounts to -		//as the root for the visual_scene -		if ( pNode )  -		{ -			processChildJoints( pNode ); -		} -		else  -		{ -			llinfos<<"Node is NULL"<<llendl; -		} - -	} -} -//----------------------------------------------------------------------------- -// processChildJoint() -//----------------------------------------------------------------------------- -void LLModelLoader::processChildJoints( domNode* pParentNode ) -{	 -	daeTArray< daeSmartRef<daeElement> > childOfChild = pParentNode->getChildren(); -	S32 childOfChildCount = childOfChild.getCount(); -	for (S32 i = 0; i < childOfChildCount; ++i) -	{ -		domNode* pChildNode = daeSafeCast<domNode>( childOfChild[i] ); -		if ( pChildNode ) -		{ -			processJointToNodeMapping( pChildNode ); -		} -	} -} - -//----------------------------------------------------------------------------- -// critiqueRigForUploadApplicability() -//----------------------------------------------------------------------------- -void LLModelPreview::critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset ) -{ -	critiqueJointToNodeMappingFromScene(); -	 -	//Determines the following use cases for a rig: -	//1. It is suitable for upload with skin weights & joint positions, or -	//2. It is suitable for upload as standard av with just skin weights -	 -	bool isJointPositionUploadOK = isRigSuitableForJointPositionUpload( jointListFromAsset ); -	bool isRigLegacyOK			 = isRigLegacy( jointListFromAsset ); - -	//It's OK that both could end up being true, both default to false -	if ( isJointPositionUploadOK ) -	{ -		setRigValidForJointPositionUpload( true ); -	} - -	if ( isRigLegacyOK)  -	{	 -		setLegacyRigValid( true ); -	} - -} -//----------------------------------------------------------------------------- -// critiqueJointToNodeMappingFromScene() -//----------------------------------------------------------------------------- -void LLModelPreview::critiqueJointToNodeMappingFromScene( void  ) -{ -	//Do the actual nodes back the joint listing from the dae? -	//if yes then this is a fully rigged asset, otherwise it's just a partial rig -	 -	std::deque<std::string>::iterator jointsFromNodeIt = mJointsFromNode.begin(); -	std::deque<std::string>::iterator jointsFromNodeEndIt = mJointsFromNode.end(); -	bool result = true; - -	if ( !mJointsFromNode.empty() ) -	{ -		for ( ;jointsFromNodeIt!=jointsFromNodeEndIt;++jointsFromNodeIt ) -		{ -			std::string name = *jointsFromNodeIt; -			if ( mJointTransformMap.find( name ) != mJointTransformMap.end() ) -			{ -				continue; -			} -			else -			{ -				llinfos<<"critiqueJointToNodeMappingFromScene is missing a: "<<name<<llendl; -				result = false;				 -			} -		} -	} -	else -	{ -		result = false; -	} - -	//Determines the following use cases for a rig: -	//1. Full av rig  w/1-1 mapping from the scene and joint array -	//2. Partial rig but w/o parity between the scene and joint array -	if ( result ) -	{		 -		setRigWithSceneParity( true ); -	}	 -} -//----------------------------------------------------------------------------- -// isRigLegacy() -//----------------------------------------------------------------------------- -bool LLModelPreview::isRigLegacy( const std::vector<std::string> &jointListFromAsset ) -{ -	//No joints in asset -	if ( jointListFromAsset.size() == 0 ) -	{ -		return false; -	} - -	bool result = false; - -	std::deque<std::string> :: const_iterator masterJointIt = mMasterLegacyJointList.begin();	 -	std::deque<std::string> :: const_iterator masterJointEndIt = mMasterLegacyJointList.end(); -	 -	std::vector<std::string> :: const_iterator modelJointIt = jointListFromAsset.begin();	 -	std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromAsset.end(); -	 -	for ( ;masterJointIt!=masterJointEndIt;++masterJointIt ) -	{ -		result = false; -		modelJointIt = jointListFromAsset.begin(); - -		for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt ) -		{ -			if ( *masterJointIt == *modelJointIt ) -			{ -				result = true; -				break; -			}			 -		}		 -		if ( !result ) -		{ -			llinfos<<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< llendl; -			break; -		} -	}	 -	return result; -} -//----------------------------------------------------------------------------- -// isRigSuitableForJointPositionUpload() -//----------------------------------------------------------------------------- -bool LLModelPreview::isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset ) -{ -	bool result = false; - -	std::deque<std::string> :: const_iterator masterJointIt = mMasterJointList.begin();	 -	std::deque<std::string> :: const_iterator masterJointEndIt = mMasterJointList.end(); -	 -	std::vector<std::string> :: const_iterator modelJointIt = jointListFromAsset.begin();	 -	std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromAsset.end(); -	 -	for ( ;masterJointIt!=masterJointEndIt;++masterJointIt ) -	{ -		result = false; -		modelJointIt = jointListFromAsset.begin(); - -		for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt ) -		{ -			if ( *masterJointIt == *modelJointIt ) -			{ -				result = true; -				break; -			}			 -		}		 -		if ( !result ) -		{ -			llinfos<<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< llendl; -			break; -		} -	}	 -	return result; -} - - -//called in the main thread -void LLModelLoader::loadTextures() -{ -	BOOL is_paused = isPaused() ; -	pause() ; //pause the loader  - -	for(scene::iterator iter = mScene.begin(); iter != mScene.end(); ++iter) -	{ -		for(U32 i = 0 ; i < iter->second.size(); i++) -		{ -			for(std::map<std::string, LLImportMaterial>::iterator j = iter->second[i].mMaterial.begin(); -				j != iter->second[i].mMaterial.end(); ++j) -			{ -				LLImportMaterial& material = j->second; - -				if(!material.mDiffuseMapFilename.empty()) -				{ -					material.mDiffuseMap =  -						LLViewerTextureManager::getFetchedTextureFromUrl("file://" + material.mDiffuseMapFilename, FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_PREVIEW); -					material.mDiffuseMap->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, mPreview, NULL, FALSE); -					material.mDiffuseMap->forceToSaveRawImage(0, F32_MAX); -					mNumOfFetchingTextures++ ; -				} -			} -		} -	} - -	if(!is_paused) -	{ -		unpause() ; -	} -} - -//----------------------------------------------------------------------------- -// isNodeAJoint() -//----------------------------------------------------------------------------- -bool LLModelLoader::isNodeAJoint( domNode* pNode ) -{ -	if ( !pNode ) -	{ -		llinfos<<"Created node is NULL"<<llendl; -		return false; -	} -	 -	if ( pNode->getName() == NULL ) -	{ -		llinfos<<"Parsed node has no name "<<llendl; -		//Attempt to write the node id, if possible (aids in debugging the visual scene) -		if ( pNode->getId() ) -		{ -			llinfos<<"Parsed node ID: "<<pNode->getId()<<llendl; -		} -		return false; -	} - -	if ( mJointMap.find( pNode->getName() )  != mJointMap.end() ) -	{ -		return true; -	} - -	return false; -} -//----------------------------------------------------------------------------- -// verifyCount -//----------------------------------------------------------------------------- -bool LLModelPreview::verifyCount( int expected, int result ) -{ -	if ( expected != result ) -	{ -		llinfos<< "Error: (expected/got)"<<expected<<"/"<<result<<"verts"<<llendl; -		return false; -	} -	return true; -} -//----------------------------------------------------------------------------- -// verifyController -//----------------------------------------------------------------------------- -bool LLModelPreview::verifyController( domController* pController ) -{	 - -	bool result = true; - -	domSkin* pSkin = pController->getSkin(); - -	if ( pSkin ) -	{ -		xsAnyURI & uri = pSkin->getSource(); -		domElement* pElement = uri.getElement(); - -		if ( !pElement ) -		{ -			llinfos<<"Can't resolve skin source"<<llendl; -			return false; -		} - -		daeString type_str = pElement->getTypeName(); -		if ( stricmp(type_str, "geometry") == 0 ) -		{	 -			//Skin is reference directly by geometry and get the vertex count from skin -			domSkin::domVertex_weights* pVertexWeights = pSkin->getVertex_weights(); -			U32 vertexWeightsCount = pVertexWeights->getCount(); -			domGeometry* pGeometry = (domGeometry*) (domElement*) uri.getElement(); -			domMesh* pMesh = pGeometry->getMesh();				 -			 -			if ( pMesh ) -			{ -				//Get vertex count from geometry -				domVertices* pVertices = pMesh->getVertices(); -				if ( !pVertices ) -				{  -					llinfos<<"No vertices!"<<llendl; -					return false; -				} - -				if ( pVertices ) -				{ -					xsAnyURI src = pVertices->getInput_array()[0]->getSource(); -					domSource* pSource = (domSource*) (domElement*) src.getElement(); -					U32 verticesCount = pSource->getTechnique_common()->getAccessor()->getCount(); -					result = verifyCount( verticesCount, vertexWeightsCount ); -					if ( !result ) -					{ -						return result; -					} -				} -			}	 - -			U32 vcountCount = (U32) pVertexWeights->getVcount()->getValue().getCount(); -			result = verifyCount( vcountCount, vertexWeightsCount );	 -			if ( !result ) -			{ -				return result; -			} - -			domInputLocalOffset_Array& inputs = pVertexWeights->getInput_array(); -			U32 sum = 0; -			for (size_t i=0; i<vcountCount; i++) -			{ -				sum += pVertexWeights->getVcount()->getValue()[i]; -			} -			result = verifyCount( sum * inputs.getCount(), (domInt) pVertexWeights->getV()->getValue().getCount() ); -		} -	} -	 -	return result; -} - -//----------------------------------------------------------------------------- -// extractTranslation() -//----------------------------------------------------------------------------- -void LLModelLoader::extractTranslation( domTranslate* pTranslate, LLMatrix4& transform ) -{ -	domFloat3 jointTrans = pTranslate->getValue(); -	LLVector3 singleJointTranslation( jointTrans[0], jointTrans[1], jointTrans[2] ); -	transform.setTranslation( singleJointTranslation ); -} -//----------------------------------------------------------------------------- -// extractTranslationViaElement() -//----------------------------------------------------------------------------- -void LLModelLoader::extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform ) -{ -	if ( pTranslateElement ) -	{ -		domTranslate* pTranslateChild = dynamic_cast<domTranslate*>( pTranslateElement ); -		domFloat3 translateChild = pTranslateChild->getValue(); -		LLVector3 singleJointTranslation( translateChild[0], translateChild[1], translateChild[2] ); -		transform.setTranslation( singleJointTranslation ); -	}	 -} -//----------------------------------------------------------------------------- -// extractTranslationViaSID() -//----------------------------------------------------------------------------- -void LLModelLoader::extractTranslationViaSID( daeElement* pElement, LLMatrix4& transform ) -{ -	if ( pElement ) -	{	 -		daeSIDResolver resolver( pElement, "./transform" ); -		domMatrix* pMatrix = daeSafeCast<domMatrix>( resolver.getElement() ); -		//We are only extracting out the translational component atm -		LLMatrix4 workingTransform; -		if ( pMatrix ) -		{ -			domFloat4x4 domArray = pMatrix->getValue();									 -			for ( int i = 0; i < 4; i++ ) -			{ -				for( int j = 0; j < 4; j++ ) -				{ -					workingTransform.mMatrix[i][j] = domArray[i + j*4]; -				} -			} -			LLVector3 trans = workingTransform.getTranslation(); -			transform.setTranslation( trans );	 -		} -	} -	else -	{ -		llwarns<<"Element is nonexistent - empty/unsupported node."<<llendl; -	} -} -//----------------------------------------------------------------------------- -// processJointNode() -//----------------------------------------------------------------------------- -void LLModelLoader::processJointNode( domNode* pNode, JointTransformMap& jointTransforms ) -{ -	if (pNode->getName() == NULL) -	{ -		llwarns << "nameless node, can't process" << llendl; -		return; -	} - -	//llwarns<<"ProcessJointNode# Node:" <<pNode->getName()<<llendl; - -	//1. handle the incoming node - extract out translation via SID or element - -	LLMatrix4 workingTransform; - -	//Pull out the translate id and store it in the jointTranslations map -	daeSIDResolver jointResolverA( pNode, "./translate" ); -	domTranslate* pTranslateA = daeSafeCast<domTranslate>( jointResolverA.getElement() ); -	daeSIDResolver jointResolverB( pNode, "./location" ); -	domTranslate* pTranslateB = daeSafeCast<domTranslate>( jointResolverB.getElement() ); - -	//Translation via SID was successful -	if ( pTranslateA ) -	{ -		extractTranslation( pTranslateA, workingTransform ); -	} -	else -	if ( pTranslateB ) -	{ -		extractTranslation( pTranslateB, workingTransform ); -	} -	else -	{ -		//Translation via child from element -		daeElement* pTranslateElement = getChildFromElement( pNode, "translate" ); -		if ( !pTranslateElement || pTranslateElement->typeID() != domTranslate::ID() ) -		{ -			//llwarns<< "The found element is not a translate node" <<llendl; -			daeSIDResolver jointResolver( pNode, "./matrix" ); -			domMatrix* pMatrix = daeSafeCast<domMatrix>( jointResolver.getElement() ); -			if ( pMatrix ) -			{ -				//llinfos<<"A matrix SID was however found!"<<llendl; -				domFloat4x4 domArray = pMatrix->getValue();									 -				for ( int i = 0; i < 4; i++ ) -				{ -					for( int j = 0; j < 4; j++ ) -					{ -						workingTransform.mMatrix[i][j] = domArray[i + j*4]; -					} -				} -			} -			else -			{ -				llwarns<< "The found element is not translate or matrix node - most likely a corrupt export!" <<llendl; -			} -		} -		else -		{ -			extractTranslationViaElement( pTranslateElement, workingTransform ); -		} -	} - -	//Store the working transform relative to the nodes name. -	jointTransforms[ pNode->getName() ] = workingTransform; - -	//2. handle the nodes children - -	//Gather and handle the incoming nodes children -	daeTArray< daeSmartRef<daeElement> > childOfChild = pNode->getChildren(); -	S32 childOfChildCount = childOfChild.getCount(); - -	for (S32 i = 0; i < childOfChildCount; ++i) -	{ -		domNode* pChildNode = daeSafeCast<domNode>( childOfChild[i] ); -		if ( pChildNode ) -		{ -			processJointNode( pChildNode, jointTransforms ); -		} -	} -} -//----------------------------------------------------------------------------- -// getChildFromElement() -//----------------------------------------------------------------------------- -daeElement* LLModelLoader::getChildFromElement( daeElement* pElement, std::string const & name ) -{ -    daeElement* pChildOfElement = pElement->getChild( name.c_str() ); -	if ( pChildOfElement ) -	{ -		return pChildOfElement; -	} -	llwarns<< "Could not find a child [" << name << "] for the element: \"" << pElement->getAttribute("id") << "\"" << llendl; -    return NULL; -} - -void LLModelLoader::processElement( daeElement* element, bool& badElement ) -{ -	LLMatrix4 saved_transform = mTransform; - -	domTranslate* translate = daeSafeCast<domTranslate>(element); -	if (translate) -	{ -		domFloat3 dom_value = translate->getValue(); - -		LLMatrix4 translation; -		translation.setTranslation(LLVector3(dom_value[0], dom_value[1], dom_value[2])); - -		translation *= mTransform; -		mTransform = translation; -	} - -	domRotate* rotate = daeSafeCast<domRotate>(element); -	if (rotate) -	{ -		domFloat4 dom_value = rotate->getValue(); - -		LLMatrix4 rotation; -		rotation.initRotTrans(dom_value[3] * DEG_TO_RAD, LLVector3(dom_value[0], dom_value[1], dom_value[2]), LLVector3(0, 0, 0)); - -		rotation *= mTransform; -		mTransform = rotation; -	} - -	domScale* scale = daeSafeCast<domScale>(element); -	if (scale) -	{ -		domFloat3 dom_value = scale->getValue(); - - -		LLVector3 scale_vector = LLVector3(dom_value[0], dom_value[1], dom_value[2]); -		scale_vector.abs(); // Set all values positive, since we don't currently support mirrored meshes -		LLMatrix4 scaling; -		scaling.initScale(scale_vector); - -		scaling *= mTransform; -		mTransform = scaling; -	} - -	domMatrix* matrix = daeSafeCast<domMatrix>(element); -	if (matrix) -	{ -		domFloat4x4 dom_value = matrix->getValue(); - -		LLMatrix4 matrix_transform; - -		for (int i = 0; i < 4; i++) -		{ -			for(int j = 0; j < 4; j++) -			{ -				matrix_transform.mMatrix[i][j] = dom_value[i + j*4]; -			} -		} - -		matrix_transform *= mTransform; -		mTransform = matrix_transform; -	} - -	domInstance_geometry* instance_geo = daeSafeCast<domInstance_geometry>(element); -	if (instance_geo) -	{ -		domGeometry* geo = daeSafeCast<domGeometry>(instance_geo->getUrl().getElement()); -		if (geo) -		{ -			domMesh* mesh = daeSafeCast<domMesh>(geo->getDescendant(daeElement::matchType(domMesh::ID()))); -			if (mesh) -			{ -				LLModel* model = mModel[mesh]; -				if (model) -				{ -					LLMatrix4 transformation = mTransform; - -					if (mTransform.determinant() < 0) -					{ //negative scales are not supported -						llinfos << "Negative scale detected, unsupported transform.  domInstance_geometry: " << LLModel::getElementLabel(instance_geo) << llendl; -						badElement = true; -					} -					 -					std::map<std::string, LLImportMaterial> materials = getMaterials(model, instance_geo); - -					// adjust the transformation to compensate for mesh normalization -					LLVector3 mesh_scale_vector; -					LLVector3 mesh_translation_vector; -					model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector); - -					LLMatrix4 mesh_translation; -					mesh_translation.setTranslation(mesh_translation_vector); -					mesh_translation *= transformation; -					transformation = mesh_translation; - -					LLMatrix4 mesh_scale; -					mesh_scale.initScale(mesh_scale_vector); -					mesh_scale *= transformation; -					transformation = mesh_scale; - -					std::string label = getElementLabel(instance_geo); -					mScene[transformation].push_back(LLModelInstance(model, label, transformation, materials)); - -					stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform); -				} -			} -		} -		else  -		{ -			llinfos<<"Unable to resolve geometry URL."<<llendl; -			badElement = true;			 -		} - -	} - -	domInstance_node* instance_node = daeSafeCast<domInstance_node>(element); -	if (instance_node) -	{ -		daeElement* instance = instance_node->getUrl().getElement(); -		if (instance) -		{ -			processElement(instance,badElement); -		} -	} - -	//process children -	daeTArray< daeSmartRef<daeElement> > children = element->getChildren(); -	int childCount = children.getCount(); -	for (S32 i = 0; i < childCount; i++) -	{ -		processElement(children[i],badElement); -	} - -	domNode* node = daeSafeCast<domNode>(element); -	if (node) -	{ //this element was a node, restore transform before processiing siblings -		mTransform = saved_transform; -	} -} - -std::map<std::string, LLImportMaterial> LLModelLoader::getMaterials(LLModel* model, domInstance_geometry* instance_geo) -{ -	std::map<std::string, LLImportMaterial> materials; -	for (int i = 0; i < model->mMaterialList.size(); i++) -	{ -		LLImportMaterial import_material; - -		domInstance_material* instance_mat = NULL; - -		domBind_material::domTechnique_common* technique = -		daeSafeCast<domBind_material::domTechnique_common>(instance_geo->getDescendant(daeElement::matchType(domBind_material::domTechnique_common::ID()))); - -		if (technique) -		{ -			daeTArray< daeSmartRef<domInstance_material> > inst_materials = technique->getChildrenByType<domInstance_material>(); -			for (int j = 0; j < inst_materials.getCount(); j++) -			{ -				std::string symbol(inst_materials[j]->getSymbol()); - -				if (symbol == model->mMaterialList[i]) // found the binding -				{ -					instance_mat = inst_materials[j]; -				} -			} -		} - -		if (instance_mat) -		{ -			domMaterial* material = daeSafeCast<domMaterial>(instance_mat->getTarget().getElement()); -			if (material) -			{ -				domInstance_effect* instance_effect = -				daeSafeCast<domInstance_effect>(material->getDescendant(daeElement::matchType(domInstance_effect::ID()))); -				if (instance_effect) -				{ -					domEffect* effect = daeSafeCast<domEffect>(instance_effect->getUrl().getElement()); -					if (effect) -					{ -						domProfile_COMMON* profile = -						daeSafeCast<domProfile_COMMON>(effect->getDescendant(daeElement::matchType(domProfile_COMMON::ID()))); -						if (profile) -						{ -							import_material = profileToMaterial(profile); -						} -					} -				} -			} -		} - -		import_material.mBinding = model->mMaterialList[i]; -		materials[model->mMaterialList[i]] = import_material; -	} - -	return materials; -} - -LLImportMaterial LLModelLoader::profileToMaterial(domProfile_COMMON* material) -{ -	LLImportMaterial mat; -	mat.mFullbright = FALSE; - -	daeElement* diffuse = material->getDescendant("diffuse"); -	if (diffuse) -	{ -		domCommon_color_or_texture_type_complexType::domTexture* texture = -		daeSafeCast<domCommon_color_or_texture_type_complexType::domTexture>(diffuse->getDescendant("texture")); -		if (texture) -		{ -			domCommon_newparam_type_Array newparams = material->getNewparam_array(); -			for (S32 i = 0; i < newparams.getCount(); i++) -			{ -				domFx_surface_common* surface = newparams[i]->getSurface(); -				if (surface) -				{ -					domFx_surface_init_common* init = surface->getFx_surface_init_common(); -					if (init) -					{ -						domFx_surface_init_from_common_Array init_from = init->getInit_from_array(); - -						if (init_from.getCount() > i) -						{ -							domImage* image = daeSafeCast<domImage>(init_from[i]->getValue().getElement()); -							if (image) -							{ -								// we only support init_from now - embedded data will come later -								domImage::domInit_from* init = image->getInit_from(); -								if (init) -								{									 -									mat.mDiffuseMapFilename = cdom::uriToNativePath(init->getValue().str()); -									mat.mDiffuseMapLabel = getElementLabel(material); -								} -							} -						} -					} -				} -			} -		} - -		domCommon_color_or_texture_type_complexType::domColor* color = -		daeSafeCast<domCommon_color_or_texture_type_complexType::domColor>(diffuse->getDescendant("color")); -		if (color) -		{ -			domFx_color_common domfx_color = color->getValue(); -			LLColor4 value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]); -			mat.mDiffuseColor = value; -		} -	} - -	daeElement* emission = material->getDescendant("emission"); -	if (emission) -	{ -		LLColor4 emission_color = getDaeColor(emission); -		if (((emission_color[0] + emission_color[1] + emission_color[2]) / 3.0) > 0.25) -		{ -			mat.mFullbright = TRUE; -		} -	} - -	return mat; -} - -// try to get a decent label for this element -std::string LLModelLoader::getElementLabel(daeElement *element) -{ -	// if we have a name attribute, use it -	std::string name = element->getAttribute("name"); -	if (name.length()) -	{ -		return name; -	} - -	// if we have an ID attribute, use it -	if (element->getID()) -	{ -		return std::string(element->getID()); -	} - -	// if we have a parent, use it -	daeElement* parent = element->getParent(); -	if (parent) -	{ -		// if parent has a name, use it -		std::string name = parent->getAttribute("name"); -		if (name.length()) -		{ -			return name; -		} - -		// if parent has an ID, use it -		if (parent->getID()) -		{ -			return std::string(parent->getID()); -		} -	} - -	// try to use our type -	daeString element_name = element->getElementName(); -	if (element_name) -	{ -		return std::string(element_name); -	} - -	// if all else fails, use "object" -	return std::string("object"); -} - -LLColor4 LLModelLoader::getDaeColor(daeElement* element) -{ -	LLColor4 value; -	domCommon_color_or_texture_type_complexType::domColor* color = -	daeSafeCast<domCommon_color_or_texture_type_complexType::domColor>(element->getDescendant("color")); -	if (color) -	{ -		domFx_color_common domfx_color = color->getValue(); -		value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]); -	} - -	return value; -} - -//-----------------------------------------------------------------------------  // LLModelPreview  //----------------------------------------------------------------------------- @@ -3171,51 +1197,20 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)  	glodInit(); -	//move into joint mapper class -	//1. joints for joint offset verification -	mMasterJointList.push_front("mPelvis"); -	mMasterJointList.push_front("mTorso"); -	mMasterJointList.push_front("mChest"); -	mMasterJointList.push_front("mNeck"); -	mMasterJointList.push_front("mHead"); -	mMasterJointList.push_front("mCollarLeft"); -	mMasterJointList.push_front("mShoulderLeft"); -	mMasterJointList.push_front("mElbowLeft"); -	mMasterJointList.push_front("mWristLeft"); -	mMasterJointList.push_front("mCollarRight"); -	mMasterJointList.push_front("mShoulderRight"); -	mMasterJointList.push_front("mElbowRight"); -	mMasterJointList.push_front("mWristRight"); -	mMasterJointList.push_front("mHipRight"); -	mMasterJointList.push_front("mKneeRight"); -	mMasterJointList.push_front("mFootRight"); -	mMasterJointList.push_front("mHipLeft"); -	mMasterJointList.push_front("mKneeLeft"); -	mMasterJointList.push_front("mFootLeft"); -	//2. legacy joint list - used to verify rigs that will not be using joint offsets -	mMasterLegacyJointList.push_front("mPelvis"); -	mMasterLegacyJointList.push_front("mTorso"); -	mMasterLegacyJointList.push_front("mChest"); -	mMasterLegacyJointList.push_front("mNeck"); -	mMasterLegacyJointList.push_front("mHead"); -	mMasterLegacyJointList.push_front("mHipRight"); -	mMasterLegacyJointList.push_front("mKneeRight"); -	mMasterLegacyJointList.push_front("mFootRight"); -	mMasterLegacyJointList.push_front("mHipLeft"); -	mMasterLegacyJointList.push_front("mKneeLeft"); -	mMasterLegacyJointList.push_front("mFootLeft"); -  	createPreviewAvatar();  }  LLModelPreview::~LLModelPreview()  { -	if (mModelLoader) -	{ -		mModelLoader->mPreview = NULL; -		mModelLoader = NULL; -	} -	//*HACK : *TODO : turn this back on when we understand why this crashes +	// glod apparently has internal mem alignment issues that are angering +	// the heap-check code in windows, these should be hunted down in that +	// TP code, if possible +	// +	// kernel32.dll!HeapFree()  + 0x14 bytes	 +	// msvcr100.dll!free(void * pBlock)  Line 51	C +	// glod.dll!glodGetGroupParameteriv()  + 0x119 bytes	 +	// glod.dll!glodShutdown()  + 0x77 bytes	 +	//  	//glodShutdown();  } @@ -3281,7 +1276,9 @@ U32 LLModelPreview::calcResourceCost()  					   decomp,  					   mFMP->childGetValue("upload_skin").asBoolean(),  					   mFMP->childGetValue("upload_joints").asBoolean(), -					   TRUE); +					   TRUE, +						FALSE, +						instance.mModel->mSubmodelID);  			num_hulls += decomp.mHull.size();  			for (U32 i = 0; i < decomp.mHull.size(); ++i) @@ -3348,29 +1345,9 @@ void LLModelPreview::rebuildUploadData()  	F32 max_scale = 0.f; -	//reorder materials to match mBaseModel -	for (U32 i = 0; i < LLModel::NUM_LODS-1; i++) -	{ -		if (mBaseModel.size() == mModel[i].size()) -		{ -			for (U32 j = 0; j < mBaseModel.size(); ++j) -			{ -				 -				int refFaceCnt = 0; -				int modelFaceCnt = 0; -				 -				if ( !mModel[i][j]->matchMaterialOrder(mBaseModel[j], refFaceCnt, modelFaceCnt ) ) -				{ -					setLoadState( LLModelLoader::ERROR_MATERIALS ); -					mFMP->childDisable( "calculate_btn" ); -				} -			} -		} -	} -  	for (LLModelLoader::scene::iterator iter = mBaseScene.begin(); iter != mBaseScene.end(); ++iter)  	{ //for each transform in scene -		LLMatrix4 mat = iter->first; +		LLMatrix4 mat		= iter->first;  		// compute position  		LLVector3 position = LLVector3(0, 0, 0) * mat; @@ -3387,41 +1364,176 @@ void LLModelPreview::rebuildUploadData()  		mat *= scale_mat; -		for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter) -		{ //for each instance with said transform applied -			LLModelInstance instance = *model_iter; +		for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end();) +		{ //for each instance with said transform applied  +			LLModelInstance instance = *model_iter++;  			LLModel* base_model = instance.mModel; -			if (base_model) +			if (base_model && !requested_name.empty())  			{  				base_model->mRequestedLabel = requested_name;  				base_model->mMetric = metric;  			} -			S32 idx = 0; -			for (idx = 0; idx < mBaseModel.size(); ++idx) -			{  //find reference instance for this model -				if (mBaseModel[idx] == base_model) -				{ -					break; -				} +            for (int i = LLModel::NUM_LODS - 1; i >= LLModel::LOD_IMPOSTOR; i--) +			{ // Fill LOD slots by finding matching meshes by label with name extensions +              // in the appropriate scene for each LOD. This fixes all kinds of issues +              // where the indexed method below fails in spectacular fashion. +              // If you don't take the time to name your LOD and PHYS meshes +              // with the name of their corresponding mesh in the HIGH LOD, +              // then the indexed method will be attempted below. + +                LLModel* lod_model = NULL; +                LLMatrix4 transform; + +                std::string name_to_match = instance.mLabel; +                llassert(!name_to_match.empty()); + +                switch (i) +                { +                    case LLModel::LOD_IMPOSTOR: name_to_match += "_LOD0"; break; +                    case LLModel::LOD_LOW:      name_to_match += "_LOD1"; break; +		            case LLModel::LOD_MEDIUM:   name_to_match += "_LOD2"; break; +                    case LLModel::LOD_PHYSICS:  name_to_match += "_PHYS"; break; +                    case LLModel::LOD_HIGH:                               break; +                } + +                FindModel(mScene[i], name_to_match, lod_model, transform); + +                S32 importerDebug = gSavedSettings.getS32("ImporterDebug");                     + +                // Fall back to old method of index-based association if +                // we could not find a match based on the mesh names +                // +                if (lod_model) +                { +                     +                    if (i == LLModel::LOD_PHYSICS) +                    { +                        if (importerDebug > 0) +                        { +                            llinfos << "Assigning collision for " << instance.mLabel << " to match " << lod_model->mLabel << llendl; +                        } +                        instance.mLOD[i] = lod_model; +                    } +                    else +                    { +                        if (importerDebug > 0) +                        { +                            llinfos << "Assigning LOD" << i << " for " << instance.mLabel << " to found match " << lod_model->mLabel << llendl; +                        } +                        instance.mLOD[i] = lod_model; +                    } +                } +                else +                { +                    int searchLOD = (i > LLModel::LOD_HIGH) ? LLModel::LOD_HIGH : i; +                    while ((searchLOD <= LLModel::LOD_HIGH) && !lod_model) +                    { +                        std::string name_to_match = instance.mLabel; +                        llassert(!name_to_match.empty()); + +                        switch (searchLOD) +                        { +                            case LLModel::LOD_IMPOSTOR: name_to_match += "_LOD0"; break; +                            case LLModel::LOD_LOW:      name_to_match += "_LOD1"; break; +		                    case LLModel::LOD_MEDIUM:   name_to_match += "_LOD2"; break; +                            case LLModel::LOD_PHYSICS:  name_to_match += "_PHYS"; break; +                            case LLModel::LOD_HIGH:                               break; +                        } + +                        // See if we can find an appropriately named model in LOD 'searchLOD' +                        // +                        FindModel(mScene[searchLOD], name_to_match, lod_model, transform); +                        searchLOD++; +                    } + +                    // Fall back to old method of index-based association if +                    // we could not find a match based on the mesh names at all. +                    // +                    if (lod_model) +                    { +                        if (i == LLModel::LOD_PHYSICS) +                        { +                            if (importerDebug > 0) +                            {                          +                                llinfos << "Falling back collision for " << instance.mLabel << " to " << lod_model->mLabel << llendl; +                            } +                            instance.mLOD[i] = lod_model; +                        } +                        else +                        { +                            if (importerDebug > 0) +                            { +                                llinfos << "Falling back LOD" << i << " for " << instance.mLabel << " to found " << lod_model->mLabel << llendl; +                            } +                            instance.mLOD[i] = lod_model; +                        } +                    } +                    else +                    { +                        S32 idx = 0; +			            for (idx = 0; idx < mBaseModel.size(); ++idx) +			            {  //find reference instance for this model +				            if (mBaseModel[idx] == base_model) +				            { +                                if (importerDebug > 0) +                                { +                                    llinfos << "Falling back to model index " << idx << " for LOD " << i << " of " << instance.mLabel << llendl; +                                } +					            break; +				            } +			            } + +                        // If the model list for the current LOD includes that index... +                        // +					    if (mModel[i].size() > idx) +					    {                               +                            // Assign that index from the model list for our LOD as the LOD model for this instance +                            // +                            lod_model = mModel[i][idx]; +						    instance.mLOD[i] = lod_model; +                            if (i == LLModel::LOD_PHYSICS) +                            { +                                if (importerDebug > 0) +                                { +                                    llinfos << "Indexed fallback to model index " << idx << ": LOD " << i << " named " << lod_model->mLabel << " for collision for " << instance.mLabel <<  llendl; +                                } +                            } +                            else +                            { +                                if (importerDebug > 0) +                                { +                                    llinfos << "Indexed fallback to model index " << idx << " LOD " << i << " named " << lod_model->mLabel << " for LOD " << i << " for " << instance.mLabel << llendl; +                                } +                            } +					    } +                        else +                        { +                            if (importerDebug > 0) +                            { +                                llinfos << "List of models for LOD " << i << " did not include index " << idx <<  llendl; +                            } +                        } +                    } +                }  			} -			if(idx < mBaseModel.size()) -			{ -				for (U32 i = 0; i < LLModel::NUM_LODS; i++) -				{ //fill LOD slots based on reference model index -					if (mModel[i].size() > idx) -					{ -						instance.mLOD[i] = mModel[i][idx]; -					} -					else -					{ -						instance.mLOD[i] = NULL; -					} +            LLModel* high_lod_model = instance.mLOD[LLModel::LOD_HIGH]; +            llassert(high_lod_model); + +            for (U32 i = 0; i < LLModel::NUM_LODS-1; i++) +	        {				 +				int refFaceCnt = 0; +				int modelFaceCnt = 0; +                llassert(instance.mLOD[i]); +				if (instance.mLOD[i] && !instance.mLOD[i]->matchMaterialOrder(high_lod_model, refFaceCnt, modelFaceCnt ) ) +				{ +					setLoadState( LLModelLoader::ERROR_MATERIALS ); +					mFMP->childDisable( "calculate_btn" );  				} -			} +	        }  			instance.mTransform = mat;  			mUploadData.push_back(instance);  		} @@ -3493,7 +1605,6 @@ void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinw  			meshes.insert(instance.mModel);  			std::stringstream str; -  			LLModel::Decomposition& decomp =  				instance.mLOD[LLModel::LOD_PHYSICS].notNull() ?   				instance.mLOD[LLModel::LOD_PHYSICS]->mPhysics :  @@ -3506,8 +1617,8 @@ void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinw  				instance.mLOD[LLModel::LOD_LOW],   				instance.mLOD[LLModel::LOD_IMPOSTOR],   				decomp,  -				save_skinweights, save_joint_positions, FALSE, TRUE); - +				save_skinweights, save_joint_positions, +                FALSE, TRUE, instance.mModel->mSubmodelID);  			data["mesh"][instance.mModel->mLocalID] = str.str();  		} @@ -3575,7 +1686,16 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable  		clearGLODGroup();  	} -	mModelLoader = new LLModelLoader(filename, lod, this, mJointTransformMap, mJointsFromNode ); +	mModelLoader = new LLDAELoader( +		filename, +		lod,  +		&LLModelPreview::loadedCallback, +		&LLModelPreview::lookupJointByName, +		&LLModelPreview::loadTextures, +		&LLModelPreview::stateChangedCallback, +		this, +		mJointTransformMap, +		mJointsFromNode );	  	if (force_disable_slm)  	{ @@ -3683,9 +1803,15 @@ void LLModelPreview::loadModelCallback(S32 lod)  	if(getLoadState() >= LLModelLoader::ERROR_PARSING)  	{  		mLoading = false ; +		mModelLoader = NULL;  		return ;  	} +	// Copy determinations about rig so UI will reflect them +	// +	setRigValidForJointPositionUpload(mModelLoader->isRigValidForJointPositionUpload()); +	setLegacyRigValid(mModelLoader->isLegacyRigValid()); +  	mModelLoader->loadTextures() ;  	if (lod == -1) @@ -3720,6 +1846,11 @@ void LLModelPreview::loadModelCallback(S32 lod)  						//override displayed model with current LoD  						list_iter->mModel = list_iter->mLOD[lod]; +						if (!list_iter->mModel) +						{ +							continue; +						} +  						//add current model to current LoD's model list (LLModel::mLocalID makes a good vector index)  						S32 idx = list_iter->mModel->mLocalID; @@ -3728,7 +1859,7 @@ void LLModelPreview::loadModelCallback(S32 lod)  							mModel[lod].resize(idx+1);  						} -						mModel[lod][idx] = list_iter->mModel;	 +						mModel[lod][idx] = list_iter->mModel;  						if (!list_iter->mModel->mSkinWeights.empty())  						{  							skin_weights = true; @@ -3817,6 +1948,8 @@ void LLModelPreview::loadModelCallback(S32 lod)  	refresh();  	mModelLoadedSignal(); + +	mModelLoader = NULL;  }  void LLModelPreview::resetPreviewTarget() @@ -4104,6 +2237,19 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim  			volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);  			mModel[lod][mdl_idx] = new LLModel(volume_params, 0.f); +            std::string name = base->mLabel; + +            switch (lod) +            { +                case LLModel::LOD_IMPOSTOR: name += "_LOD0"; break; +                case LLModel::LOD_LOW:      name += "_LOD1"; break; +		        case LLModel::LOD_MEDIUM:   name += "_LOD2"; break; +                case LLModel::LOD_PHYSICS:  name += "_PHYS"; break; +                case LLModel::LOD_HIGH:                      break; +            } + +            mModel[lod][mdl_idx]->mLabel = name; +              			GLint* sizes = new GLint[patch_count*2];  			glodGetObjectParameteriv(mObject[base], GLOD_PATCH_SIZES, sizes);  			stop_gloderror(); @@ -4216,17 +2362,6 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim  	{  		shader->bind();  	} - -	/*if (which_lod == -1 && mScene[LLModel::LOD_PHYSICS].empty()) -	 { //build physics scene -	 mScene[LLModel::LOD_PHYSICS] = mScene[LLModel::LOD_LOW]; -	 mModel[LLModel::LOD_PHYSICS] = mModel[LLModel::LOD_LOW]; - -	 for (U32 i = 1; i < mModel[LLModel::LOD_PHYSICS].size(); ++i) -	 { -	 mPhysicsQ.push(mModel[LLModel::LOD_PHYSICS][i]); -	 } -	 }*/  }  void LLModelPreview::updateStatusMessages() @@ -4243,43 +2378,88 @@ void LLModelPreview::updateStatusMessages()  	S32 total_verts[LLModel::NUM_LODS];  	S32 total_submeshes[LLModel::NUM_LODS]; -	for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod) +    for (U32 i = 0; i < LLModel::NUM_LODS-1; i++) +    { +        total_tris[i] = 0; +	    total_verts[i] = 0; +	    total_submeshes[i] = 0; +    } + +    for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)  	{ -		//initialize total for this lod to 0 -		total_tris[lod] = total_verts[lod] = total_submeshes[lod] = 0; +		LLModelInstance& instance = *iter; + +        LLModel* model_high_lod = instance.mLOD[LLModel::LOD_HIGH]; +        llassert(model_high_lod); -		for (LLModelLoader::scene::iterator iter = mScene[lod].begin(), endIter = mScene[lod].end(); iter != endIter; ++iter) +        for (U32 i = 0; i < LLModel::NUM_LODS-1; i++)  		{ -			for (LLModelLoader::model_instance_list::iterator instance = iter->second.begin(), end_instance = iter->second.end(); instance != end_instance; ++instance) -			{ -				LLModel* model = instance->mModel; -				if (model) -				{ -					 //for each model in the lod -					S32 cur_tris = 0; -					S32 cur_verts = 0; -					S32 cur_submeshes = model->getNumVolumeFaces(); +            LLModel* lod_model = instance.mLOD[i]; +            llassert(lod_model); +            if (!lod_model) +            { +                setLoadState( LLModelLoader::ERROR_MATERIALS ); +                mFMP->childDisable( "calculate_btn" ); +            } -					for (S32 j = 0; j < cur_submeshes; ++j) -					{ //for each submesh (face), add triangles and vertices to current total -						const LLVolumeFace& face = model->getVolumeFace(j); -						cur_tris += face.mNumIndices/3; -						cur_verts += face.mNumVertices; -					} +            int refFaceCnt = 0; +            int modelFaceCnt = 0; -					//add this model to the lod total -					total_tris[lod] += cur_tris; -					total_verts[lod] += cur_verts; -					total_submeshes[lod] += cur_submeshes; +            if (!lod_model->matchMaterialOrder(model_high_lod, refFaceCnt, modelFaceCnt ) ) +			{ +                setLoadState( LLModelLoader::ERROR_MATERIALS ); +				mFMP->childDisable( "calculate_btn" ); +			} -					//store this model's counts to asset data -					tris[lod].push_back(cur_tris); -					verts[lod].push_back(cur_verts); -					submeshes[lod].push_back(cur_submeshes); +            if (lod_model) +			{ +					//for each model in the lod +				S32 cur_tris = 0; +				S32 cur_verts = 0; +				S32 cur_submeshes = lod_model->getNumVolumeFaces(); + +				for (S32 j = 0; j < cur_submeshes; ++j) +				{ //for each submesh (face), add triangles and vertices to current total +					const LLVolumeFace& face = lod_model->getVolumeFace(j); +					cur_tris += face.mNumIndices/3; +					cur_verts += face.mNumVertices;  				} + +                std::string instance_name = instance.mLabel; + +                S32 importerDebug = gSavedSettings.getS32("ImporterDebug"); +                if (importerDebug > 0) +                { +                    // Useful for debugging generalized complaints below about total submeshes which don't have enough +                    // context to address exactly what needs to be fixed to move towards compliance with the rules. +                    // +                    llinfos << "Instance " << lod_model->mLabel << " LOD " << i << " Verts: "   << cur_verts     << llendl; +                    llinfos << "Instance " << lod_model->mLabel << " LOD " << i << " Tris:  "   << cur_tris      << llendl; +                    llinfos << "Instance " << lod_model->mLabel << " LOD " << i << " Faces: "   << cur_submeshes << llendl; + +                    if (importerDebug > 1) +                    { +                        LLModel::material_list::iterator mat_iter = lod_model->mMaterialList.begin(); +                        while (mat_iter != lod_model->mMaterialList.end()) +                        { +                            llinfos << "Instance " << lod_model->mLabel << " LOD " << i << " Material " << *(mat_iter) << llendl; +                            mat_iter++; +                        } +                    } +                } + +                //add this model to the lod total +				total_tris[i] += cur_tris; +				total_verts[i] += cur_verts; +				total_submeshes[i] += cur_submeshes; + +				//store this model's counts to asset data +				tris[i].push_back(cur_tris); +				verts[i].push_back(cur_verts); +				submeshes[i].push_back(cur_submeshes);  			}  		} -	} +    }  	if (mMaxTriangleLimit == 0)  	{ @@ -4293,28 +2473,36 @@ void LLModelPreview::updateStatusMessages()  		const LLVector4a scale(0.5f);  		for (U32 i = 0; i < mModel[lod].size() && !has_degenerate; ++i)  		{ //for each model in the lod -			if (mModel[lod][i]->mPhysics.mHull.empty()) +			if (mModel[lod][i] && mModel[lod][i]->mPhysics.mHull.empty())  			{ //no decomp exists  				S32 cur_submeshes = mModel[lod][i]->getNumVolumeFaces();  				for (S32 j = 0; j < cur_submeshes && !has_degenerate; ++j)  				{ //for each submesh (face), add triangles and vertices to current total -					const LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j); -					for (S32 k = 0; k < face.mNumIndices && !has_degenerate; ) +					LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j); +					for (S32 k = 0; (k < face.mNumIndices) && !has_degenerate; )  					{ -						LLVector4a v1; v1.setMul(face.mPositions[face.mIndices[k++]], scale); -						LLVector4a v2; v2.setMul(face.mPositions[face.mIndices[k++]], scale); -						LLVector4a v3; v3.setMul(face.mPositions[face.mIndices[k++]], scale); +						U16 index_a = face.mIndices[k+0]; +						U16 index_b = face.mIndices[k+1]; +						U16 index_c = face.mIndices[k+2]; + +						LLVector4a v1; v1.setMul(face.mPositions[index_a], scale); +						LLVector4a v2; v2.setMul(face.mPositions[index_b], scale); +						LLVector4a v3; v3.setMul(face.mPositions[index_c], scale);  						if (ll_is_degenerate(v1,v2,v3))  						{  							has_degenerate = true;  						} +						else +						{ +							k += 3; +						}  					}  				}  			}  		}  	} -	 +  	mFMP->childSetTextArg("submeshes_info", "[SUBMESHES]", llformat("%d", total_submeshes[LLModel::LOD_HIGH]));  	std::string mesh_status_na = mFMP->getString("mesh_status_na"); @@ -4417,13 +2605,16 @@ void LLModelPreview::updateStatusMessages()  	{  		LLModel* mdl = mModel[LLModel::LOD_PHYSICS][i]; -		for (U32 j = 0; upload_ok && j < mdl->mPhysics.mHull.size(); ++j) +		if (mdl)  		{ -			if (mdl->mPhysics.mHull[j].size() > 256) +			for (U32 j = 0; upload_ok && j < mdl->mPhysics.mHull.size(); ++j)  			{ -				upload_ok = false; +				if (mdl->mPhysics.mHull[j].size() > 256) +				{ +					upload_ok = false; +				}  			} -		} +		}		  	}  	bool errorStateFromLoader = getLoadState() >= LLModelLoader::ERROR_PARSING ? true : false; @@ -4939,6 +3130,58 @@ void LLModelPreview::createPreviewAvatar( void )  	}  } +void LLModelPreview::loadedCallback( +	LLModelLoader::scene& scene, +	LLModelLoader::model_list& model_list, +	S32 lod, +	void* opaque) +{ +	LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque); +	if (pPreview) +	{ +		pPreview->loadModelCallback(lod); +	}	 +} + +void LLModelPreview::stateChangedCallback(U32 state,void* opaque) +{ +	LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque); +	if (pPreview) +	{ +	 pPreview->setLoadState(state); +	} +} + +LLJoint* LLModelPreview::lookupJointByName(const std::string& str, void* opaque) +{ +	LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque); +	if (pPreview) +	{ +		return pPreview->getPreviewAvatar()->getJoint(str); +	} +	return NULL; +} + +U32 LLModelPreview::loadTextures(LLImportMaterial& material,void* opaque) +{ +	(void)opaque; + +	if (material.mDiffuseMapFilename.size()) +	{ +		material.mOpaqueData = new LLPointer< LLViewerFetchedTexture >; +		LLPointer< LLViewerFetchedTexture >& tex = (*reinterpret_cast< LLPointer< LLViewerFetchedTexture > * >(material.mOpaqueData)); + +		tex = LLViewerTextureManager::getFetchedTextureFromUrl("file://" + material.mDiffuseMapFilename, FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_PREVIEW); +		tex->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, opaque, NULL, FALSE); +		tex->forceToSaveRawImage(0, F32_MAX); +		material.setDiffuseMap(tex->getID()); // record tex ID +		return 1; +	} + +	material.mOpaqueData = NULL; +	return 0;	 +} +  void LLModelPreview::addEmptyFace( LLModel* pTarget )  {  	U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0; @@ -5181,24 +3424,6 @@ BOOL LLModelPreview::render()  			}  		} -		//make sure material lists all match -		for (U32 i = 0; i < LLModel::NUM_LODS-1; i++) -		{ -			if (mBaseModel.size() == mModel[i].size()) -			{ -				for (U32 j = 0; j < mBaseModel.size(); ++j) -				{ -					int refFaceCnt = 0; -					int modelFaceCnt = 0; -										 -					if ( !mModel[i][j]->matchMaterialOrder(mBaseModel[j], refFaceCnt, modelFaceCnt ) ) -					{ -						mFMP->childDisable( "calculate_btn" ); -					} -				} -			} -		} -  		if (regen)  		{  			genBuffers(mPreviewLOD, skin_weight); @@ -5212,62 +3437,61 @@ BOOL LLModelPreview::render()  				LLModel* model = instance.mLOD[mPreviewLOD]; -				if (!model) -				{ -					continue; -				} +					if (!model) +					{ +						continue; +					} -				gGL.pushMatrix(); -				LLMatrix4 mat = instance.mTransform; +					gGL.pushMatrix(); +					LLMatrix4 mat = instance.mTransform; -				gGL.multMatrix((GLfloat*) mat.mMatrix); +					gGL.multMatrix((GLfloat*) mat.mMatrix); -				for (U32 i = 0; i < mVertexBuffer[mPreviewLOD][model].size(); ++i) -				{ -					LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i]; +					for (U32 i = 0; i < mVertexBuffer[mPreviewLOD][model].size(); ++i) +					{ +						LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i]; -					buffer->setBuffer(type_mask & buffer->getTypeMask()); +						buffer->setBuffer(type_mask & buffer->getTypeMask()); -					if (textures) -					{ -						int materialCnt = instance.mModel->mMaterialList.size(); -						if ( i < materialCnt ) +						if (textures)  						{ -							const std::string& binding = instance.mModel->mMaterialList[i];						 -							const LLImportMaterial& material = instance.mMaterial[binding]; +							int materialCnt = instance.mModel->mMaterialList.size(); +							if ( i < materialCnt ) +							{ +								const std::string& binding = instance.mModel->mMaterialList[i];						 +								const LLImportMaterial& material = instance.mMaterial[binding]; -							gGL.diffuseColor4fv(material.mDiffuseColor.mV); +								gGL.diffuseColor4fv(material.mDiffuseColor.mV); -							if (material.mDiffuseMap.notNull()) -							{ -								if (material.mDiffuseMap->getDiscardLevel() > -1) +								// Find the tex for this material, bind it, and add it to our set +								// +								LLViewerFetchedTexture* tex = bindMaterialDiffuseTexture(material); +								if (tex)  								{ -									gGL.getTexUnit(0)->bind(material.mDiffuseMap, true); -									mTextureSet.insert(material.mDiffuseMap.get()); +									mTextureSet.insert(tex);  								}  							}  						} -					} -					else -					{ -						gGL.diffuseColor4f(1,1,1,1); -					} - -					buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); -					gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -					gGL.diffuseColor3f(0.4f, 0.4f, 0.4f); +						else +						{ +							gGL.diffuseColor4f(1,1,1,1); +						} -					if (edges) -					{ -						glLineWidth(3.f); -						glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);  						buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); -						glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); -						glLineWidth(1.f); +						gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); +						gGL.diffuseColor3f(0.4f, 0.4f, 0.4f); + +						if (edges) +						{ +							glLineWidth(3.f); +							glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +							buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); +							glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +							glLineWidth(1.f); +						}  					} +					gGL.popMatrix();  				} -				gGL.popMatrix(); -			}  			if (physics)  			{ @@ -5295,97 +3519,97 @@ BOOL LLModelPreview::render()  						LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS]; -						if (!model) -						{ -							continue; -						} +							if (!model) +							{ +								continue; +							} -						gGL.pushMatrix(); -						LLMatrix4 mat = instance.mTransform; +							gGL.pushMatrix(); +							LLMatrix4 mat = instance.mTransform;  						gGL.multMatrix((GLfloat*) mat.mMatrix); -						bool render_mesh = true; +							bool render_mesh = true; -						LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread; -						if (decomp) -						{ -							LLMutexLock(decomp->mMutex); +							LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread; +							if (decomp) +							{ +								LLMutexLock(decomp->mMutex); -							LLModel::Decomposition& physics = model->mPhysics; +								LLModel::Decomposition& physics = model->mPhysics; -							if (!physics.mHull.empty()) -							{ -								render_mesh = false; +								if (!physics.mHull.empty()) +								{ +									render_mesh = false; -								if (physics.mMesh.empty()) -								{ //build vertex buffer for physics mesh -									gMeshRepo.buildPhysicsMesh(physics); -								} +									if (physics.mMesh.empty()) +									{ //build vertex buffer for physics mesh +										gMeshRepo.buildPhysicsMesh(physics); +									} -								if (!physics.mMesh.empty()) -								{ //render hull instead of mesh -									for (U32 i = 0; i < physics.mMesh.size(); ++i) -									{ -										if (explode > 0.f) +									if (!physics.mMesh.empty()) +									{ //render hull instead of mesh +										for (U32 i = 0; i < physics.mMesh.size(); ++i)  										{ -											gGL.pushMatrix(); +											if (explode > 0.f) +											{ +												gGL.pushMatrix(); -											LLVector3 offset = model->mHullCenter[i]-model->mCenterOfHullCenters; -											offset *= explode; +												LLVector3 offset = model->mHullCenter[i]-model->mCenterOfHullCenters; +												offset *= explode; -											gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]); -										} +												gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]); +											} -										static std::vector<LLColor4U> hull_colors; +											static std::vector<LLColor4U> hull_colors; -										if (i+1 >= hull_colors.size()) -										{ -											hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 128)); -										} +											if (i+1 >= hull_colors.size()) +											{ +												hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 128)); +											} -										gGL.diffuseColor4ubv(hull_colors[i].mV); -										LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals); +											gGL.diffuseColor4ubv(hull_colors[i].mV); +											LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals); -										if (explode > 0.f) -										{ -											gGL.popMatrix(); +											if (explode > 0.f) +											{ +												gGL.popMatrix(); +											}  										}  									}  								}  							} -						} - -						if (render_mesh) -						{ -							if (mVertexBuffer[LLModel::LOD_PHYSICS].empty()) -							{ -								genBuffers(LLModel::LOD_PHYSICS, false); -							} -							for (U32 i = 0; i < mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); ++i) +						 +							if (render_mesh)  							{ -								LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i]; +								if (mVertexBuffer[LLModel::LOD_PHYSICS].empty()) +								{ +									genBuffers(LLModel::LOD_PHYSICS, false); +								} +								for (U32 i = 0; i < mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); ++i) +								{ +									LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i]; -								gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -								gGL.diffuseColor4f(0.4f, 0.4f, 0.0f, 0.4f); +									gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); +									gGL.diffuseColor4f(0.4f, 0.4f, 0.0f, 0.4f); -								buffer->setBuffer(type_mask & buffer->getTypeMask()); -								buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); +									buffer->setBuffer(type_mask & buffer->getTypeMask()); +									buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); -								gGL.diffuseColor3f(1.f, 1.f, 0.f); +									gGL.diffuseColor3f(1.f, 1.f, 0.f); -								glLineWidth(2.f); -								glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); -								buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); +									glLineWidth(2.f); +									glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +									buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); -								glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); -								glLineWidth(1.f); +									glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +									glLineWidth(1.f); +								}  							} -						} -						gGL.popMatrix(); -					} +							gGL.popMatrix(); +						}  					glLineWidth(3.f);  					glPointSize(8.f); @@ -5572,13 +3796,13 @@ BOOL LLModelPreview::render()  							buffer->setBuffer(type_mask & buffer->getTypeMask());  							gGL.diffuseColor4fv(material.mDiffuseColor.mV);  							gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -							if (material.mDiffuseMap.notNull()) + +							// Find the tex for this material, bind it, and add it to our set +							// +							LLViewerFetchedTexture* tex = bindMaterialDiffuseTexture(material); +							if (tex)  							{ -								if (material.mDiffuseMap->getDiscardLevel() > -1) -								{ -									gGL.getTexUnit(0)->bind(material.mDiffuseMap, true); -									mTextureSet.insert(material.mDiffuseMap.get()); -								} +								mTextureSet.insert(tex);  							}  							buffer->draw(LLRender::TRIANGLES, buffer->getNumIndices(), 0); diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index e588418f7b..9948bb35a8 100755 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -37,6 +37,8 @@  #include "llviewermenufile.h"  #include "llfloatermodeluploadbase.h" +#include "lldaeloader.h" +  class LLComboBox;  class LLJoint;  class LLViewerJointMesh; @@ -45,103 +47,18 @@ class LLTextBox;  class LLVertexBuffer;  class LLModelPreview;  class LLFloaterModelPreview; +class DAE;  class daeElement;  class domProfile_COMMON;  class domInstance_geometry;  class domNode;  class domTranslate;  class domController; +class domSkin; +class domMesh;  class LLMenuButton;  class LLToggleableMenu; -typedef std::map<std::string, LLMatrix4> JointTransformMap; -typedef std::map<std::string, LLMatrix4>:: iterator JointTransformMapIt; - -const S32 NUM_LOD = 4; - -class LLModelLoader : public LLThread -{ -public: -	typedef enum -	{ -		STARTING = 0, -		READING_FILE, -		CREATING_FACES, -		GENERATING_VERTEX_BUFFERS, -		GENERATING_LOD, -		DONE, -		ERROR_PARSING, //basically loading failed -		ERROR_MATERIALS, -	} eLoadState; - -	U32 mState; -	std::string mFilename; -	S32 mLod; -	LLModelPreview* mPreview; -	LLMatrix4 mTransform; -	BOOL mFirstTransform; -	LLVector3 mExtents[2]; -	bool mTrySLM; -	 -	std::map<daeElement*, LLPointer<LLModel> > mModel; -	 -	typedef std::vector<LLPointer<LLModel> > model_list; -	model_list mModelList; - -	typedef std::vector<LLModelInstance> model_instance_list; -	 -	typedef std::map<LLMatrix4, model_instance_list > scene; - -	scene mScene; - -	typedef std::queue<LLPointer<LLModel> > model_queue; - -	//queue of models that need a physics rep -	model_queue mPhysicsQ; - -	LLModelLoader( std::string filename, S32 lod, LLModelPreview* preview, JointTransformMap& jointMap,  -				   std::deque<std::string>& jointsFromNodes ); -	~LLModelLoader() ; - -	virtual void run(); -	bool doLoadModel(); -	bool loadFromSLM(const std::string& filename); -	void loadModelCallback(); - -	void loadTextures() ; //called in the main thread. -	void processElement(daeElement* element, bool& badElement); -	std::map<std::string, LLImportMaterial> getMaterials(LLModel* model, domInstance_geometry* instance_geo); -	LLImportMaterial profileToMaterial(domProfile_COMMON* material); -	std::string getElementLabel(daeElement *element); -	LLColor4 getDaeColor(daeElement* element); -	 -	daeElement* getChildFromElement( daeElement* pElement, std::string const & name ); -	 -	bool isNodeAJoint( domNode* pNode ); -	void processJointNode( domNode* pNode, std::map<std::string,LLMatrix4>& jointTransforms ); -	void extractTranslation( domTranslate* pTranslate, LLMatrix4& transform ); -	void extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform ); -	void extractTranslationViaSID( daeElement* pElement, LLMatrix4& transform ); - -	void setLoadState(U32 state); - -	void buildJointToNodeMappingFromScene( daeElement* pRoot ); -	void processJointToNodeMapping( domNode* pNode ); -	void processChildJoints( domNode* pParentNode ); - -	//map of avatar joints as named in COLLADA assets to internal joint names -	std::map<std::string, std::string> mJointMap; -	JointTransformMap& mJointList;	 -	std::deque<std::string>& mJointsFromNode; - -	S32 mNumOfFetchingTextures ; //updated in the main thread -	bool areTexturesReady() { return !mNumOfFetchingTextures; } //called in the main thread. - -private: -	static std::list<LLModelLoader*> sActiveLoaderList; -	static bool isAlive(LLModelLoader* loader) ; -}; -  class LLFloaterModelPreview : public LLFloaterModelUploadBase  {  public: @@ -358,21 +275,14 @@ public:  	void setHasPivot( bool val ) { mHasPivot = val; }  	void setModelPivot( const LLVector3& pivot ) { mModelPivot = pivot; } -	//Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps) -	void critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset ); -	void critiqueJointToNodeMappingFromScene( void  );  	//Is a rig valid so that it can be used as a criteria for allowing for uploading of joint positions  	//Accessors for joint position upload friendly rigs  	const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; }  	void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; } -	bool isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset ); -	//Determines if a rig is a legacy from the joint list -	bool isRigLegacy( const std::vector<std::string> &jointListFromAsset );	 +  	//Accessors for the legacy rigs  	const bool isLegacyRigValid( void ) const { return mLegacyRigValid; } -	void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; }	 -	//Verify that a controller matches vertex counts -	bool verifyController( domController* pController ); +	void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; }		  	static void	textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata ); @@ -387,6 +297,14 @@ public:  	LLVector3 getTranslationForJointOffset( std::string joint ); +protected: + +	static void			loadedCallback(LLModelLoader::scene& scene,LLModelLoader::model_list& model_list, S32 lod, void* opaque); +	static void			stateChangedCallback(U32 state, void* opaque); + +	static LLJoint*	lookupJointByName(const std::string&, void* opaque); +	static U32			loadTextures(LLImportMaterial& material, void* opaque); +  private:  	//Utility function for controller vertex compare  	bool verifyCount( int expected, int result ); @@ -452,7 +370,7 @@ private:  	U32 mMaxTriangleLimit;  	LLMeshUploadThread::instance_list mUploadData; -	std::set<LLViewerFetchedTexture* > mTextureSet; +	std::set<LLViewerFetchedTexture * > mTextureSet;  	//map of vertex buffers to models (one vertex buffer in vector per face in model  	std::map<LLModel*, std::vector<LLPointer<LLVertexBuffer> > > mVertexBuffer[LLModel::NUM_LODS+1]; @@ -470,11 +388,10 @@ private:  	bool		mLegacyRigValid;  	bool		mLastJointUpdate; +	 +	JointSet				mJointsFromNode; +	JointTransformMap	mJointTransformMap; -	std::deque<std::string> mMasterJointList; -	std::deque<std::string> mMasterLegacyJointList; -	std::deque<std::string> mJointsFromNode; -	JointTransformMap		mJointTransformMap;  	LLPointer<LLVOAvatar>	mPreviewAvatar;  }; diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 5afd2cb329..f36fb971b5 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -498,6 +498,12 @@ void get_vertex_buffer_from_mesh(LLCDMeshData& mesh, LLModel::PhysicsMesh& res,  	}  } +LLViewerFetchedTexture* LLMeshUploadThread::FindViewerTexture(const LLImportMaterial& material) +{ +	LLPointer< LLViewerFetchedTexture > * ppTex = static_cast< LLPointer< LLViewerFetchedTexture > * >(material.mOpaqueData); +	return ppTex ? (*ppTex).get() : NULL; +} +  volatile S32 LLMeshRepoThread::sActiveHeaderRequests = 0;  volatile S32 LLMeshRepoThread::sActiveLODRequests = 0;  U32	LLMeshRepoThread::sMaxConcurrentRequests = 1; @@ -2027,6 +2033,14 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)  	{  		LLMeshUploadData data;  		data.mBaseModel = iter->first; + +		if (data.mBaseModel->mSubmodelID) +		{ +			// These are handled below to insure correct parenting order on creation +			// due to map walking being based on model address (aka random) +			continue; +		} +  		LLModelInstance& first_instance = *(iter->second.begin());  		for (S32 i = 0; i < 5; i++)  		{ @@ -2064,7 +2078,10 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)  				data.mModel[LLModel::LOD_IMPOSTOR],   				decomp,  				mUploadSkin, -				mUploadJoints); +				mUploadJoints, +				FALSE, +				FALSE, +				data.mBaseModel->mSubmodelID);  			data.mAssetData = ostr.str();  			std::string str = ostr.str(); @@ -2098,17 +2115,26 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)  			instance_entry["scale"] = ll_sd_from_vector3(scale);  			instance_entry["material"] = LL_MCODE_WOOD; -			instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL); +			instance_entry["physics_shape_type"] = data.mModel[LLModel::LOD_PHYSICS].notNull() ? (U8)(LLViewerObject::PHYSICS_SHAPE_PRIM) : (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL);  			instance_entry["mesh"] = mesh_index[data.mBaseModel];  			instance_entry["face_list"] = LLSD::emptyArray(); -			S32 end = llmin((S32)data.mBaseModel->mMaterialList.size(), data.mBaseModel->getNumVolumeFaces()) ; +			// We want to be able to allow more than 8 materials... +			// +			S32 end = llmin((S32)instance.mMaterial.size(), instance.mModel->getNumVolumeFaces()) ; +  			for (S32 face_num = 0; face_num < end; face_num++)  			{  				LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]];  				LLSD face_entry = LLSD::emptyMap(); -				LLViewerFetchedTexture *texture = material.mDiffuseMap.get(); + +				LLViewerFetchedTexture *texture = NULL; + +				if (material.mDiffuseMapFilename.size()) +				{ +					texture = FindViewerTexture(material); +				}  				if ((texture != NULL) &&  					(textures.find(texture) == textures.end())) @@ -2123,9 +2149,171 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)  					{											  						LLPointer<LLImageJ2C> upload_file =  							LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage()); + +						if (!upload_file.isNull() && upload_file->getDataSize()) +						{ +						texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize()); +					} +				} +				} + +				if (texture != NULL && +					mUploadTextures && +					texture_index.find(texture) == texture_index.end()) +				{ +					texture_index[texture] = texture_num; +					std::string str = texture_str.str(); +					res["texture_list"][texture_num] = LLSD::Binary(str.begin(),str.end()); +					texture_num++; +				} + +				// Subset of TextureEntry fields. +				if (texture != NULL && mUploadTextures) +				{ +					face_entry["image"] = texture_index[texture]; +					face_entry["scales"] = 1.0; +					face_entry["scalet"] = 1.0; +					face_entry["offsets"] = 0.0; +					face_entry["offsett"] = 0.0; +					face_entry["imagerot"] = 0.0; +				} +				face_entry["diffuse_color"] = ll_sd_from_color4(material.mDiffuseColor); +				face_entry["fullbright"] = material.mFullbright; +				instance_entry["face_list"][face_num] = face_entry; +		    } + +			res["instance_list"][instance_num] = instance_entry; +			instance_num++; +		} +	} + +	for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter) +	{ +		LLMeshUploadData data; +		data.mBaseModel = iter->first; + +		if (!data.mBaseModel->mSubmodelID) +		{ +			// These were handled above already... +			// +			continue; +		} + +		LLModelInstance& first_instance = *(iter->second.begin()); +		for (S32 i = 0; i < 5; i++) +		{ +			data.mModel[i] = first_instance.mLOD[i]; +		} + +		if (mesh_index.find(data.mBaseModel) == mesh_index.end()) +		{ +			// Have not seen this model before - create a new mesh_list entry for it. +			if (model_name.empty()) +			{ +				model_name = data.mBaseModel->getName(); +			} + +			if (model_metric.empty()) +			{ +				model_metric = data.mBaseModel->getMetric(); +			} + +			std::stringstream ostr; +			 +			LLModel::Decomposition& decomp = +				data.mModel[LLModel::LOD_PHYSICS].notNull() ?  +				data.mModel[LLModel::LOD_PHYSICS]->mPhysics :  +				data.mBaseModel->mPhysics; + +			decomp.mBaseHull = mHullMap[data.mBaseModel]; + +			LLSD mesh_header = LLModel::writeModel( +				ostr,   +				data.mModel[LLModel::LOD_PHYSICS], +				data.mModel[LLModel::LOD_HIGH], +				data.mModel[LLModel::LOD_MEDIUM], +				data.mModel[LLModel::LOD_LOW], +				data.mModel[LLModel::LOD_IMPOSTOR],  +				decomp, +				mUploadSkin, +				mUploadJoints, +				FALSE, +				FALSE, +				data.mBaseModel->mSubmodelID); + +			data.mAssetData = ostr.str(); +			std::string str = ostr.str(); + +			res["mesh_list"][mesh_num] = LLSD::Binary(str.begin(),str.end());  +			mesh_index[data.mBaseModel] = mesh_num; +			mesh_num++; +		} + +		// For all instances that use this model +		for (instance_list::iterator instance_iter = iter->second.begin(); +			 instance_iter != iter->second.end(); +			 ++instance_iter) +		{ + +			LLModelInstance& instance = *instance_iter; +		 +			LLSD instance_entry; +		 +			for (S32 i = 0; i < 5; i++) +			{ +				data.mModel[i] = instance.mLOD[i]; +			} +		 +			LLVector3 pos, scale; +			LLQuaternion rot; +			LLMatrix4 transformation = instance.mTransform; +			decomposeMeshMatrix(transformation,pos,rot,scale); +			instance_entry["position"] = ll_sd_from_vector3(pos); +			instance_entry["rotation"] = ll_sd_from_quaternion(rot); +			instance_entry["scale"] = ll_sd_from_vector3(scale); +		 +			instance_entry["material"] = LL_MCODE_WOOD; +			instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_NONE); +			instance_entry["mesh"] = mesh_index[data.mBaseModel]; + +			instance_entry["face_list"] = LLSD::emptyArray(); + +			// We want to be able to allow more than 8 materials... +			// +			S32 end = llmin((S32)instance.mMaterial.size(), instance.mModel->getNumVolumeFaces()) ; + +			for (S32 face_num = 0; face_num < end; face_num++) +			{ +				LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]]; +				LLSD face_entry = LLSD::emptyMap(); + +				LLViewerFetchedTexture *texture = NULL; + +				if (material.mDiffuseMapFilename.size()) +				{ +					texture = FindViewerTexture(material); +				} + +				if ((texture != NULL) && +					(textures.find(texture) == textures.end())) +				{ +					textures.insert(texture); +				} + +				std::stringstream texture_str; +				if (texture != NULL && include_textures && mUploadTextures) +				{ +					if(texture->hasSavedRawImage()) +					{											 +						LLPointer<LLImageJ2C> upload_file = +							LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage()); + +						if (!upload_file.isNull() && upload_file->getDataSize()) +						{  						texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());  					}  				} +				}  				if (texture != NULL &&  					mUploadTextures && @@ -3756,37 +3944,6 @@ void LLMeshUploadThread::decomposeMeshMatrix(LLMatrix4& transformation,  	result_rot = quat_rotation;   } -bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const -{ -	if (mDiffuseMap != rhs.mDiffuseMap) -	{ -		return mDiffuseMap < rhs.mDiffuseMap; -	} - -	if (mDiffuseMapFilename != rhs.mDiffuseMapFilename) -	{ -		return mDiffuseMapFilename < rhs.mDiffuseMapFilename; -	} - -	if (mDiffuseMapLabel != rhs.mDiffuseMapLabel) -	{ -		return mDiffuseMapLabel < rhs.mDiffuseMapLabel; -	} - -	if (mDiffuseColor != rhs.mDiffuseColor) -	{ -		return mDiffuseColor < rhs.mDiffuseColor; -	} - -	if (mBinding != rhs.mBinding) -	{ -		return mBinding < rhs.mBinding; -	} - -	return mFullbright < rhs.mFullbright; -} - -  void LLMeshRepository::updateInventory(inventory_data data)  {  	LLMutexLock lock(mMeshMutex); @@ -4372,60 +4529,6 @@ void LLPhysicsDecomp::Request::setStatusMessage(const std::string& msg)  	mStatusMessage = msg;  } -LLModelInstance::LLModelInstance(LLSD& data) -{ -	mLocalMeshID = data["mesh_id"].asInteger(); -	mLabel = data["label"].asString(); -	mTransform.setValue(data["transform"]); - -	for (U32 i = 0; i < data["material"].size(); ++i) -	{ -		LLImportMaterial mat(data["material"][i]); -		mMaterial[mat.mBinding] = mat; -	} -} - - -LLSD LLModelInstance::asLLSD() -{	 -	LLSD ret; - -	ret["mesh_id"] = mModel->mLocalID; -	ret["label"] = mLabel; -	ret["transform"] = mTransform.getValue(); -	 -	U32 i = 0; -	for (std::map<std::string, LLImportMaterial>::iterator iter = mMaterial.begin(); iter != mMaterial.end(); ++iter) -	{ -		ret["material"][i++] = iter->second.asLLSD(); -	} - -	return ret; -} - -LLImportMaterial::LLImportMaterial(LLSD& data) -{ -	mDiffuseMapFilename = data["diffuse"]["filename"].asString(); -	mDiffuseMapLabel = data["diffuse"]["label"].asString(); -	mDiffuseColor.setValue(data["diffuse"]["color"]); -	mFullbright = data["fullbright"].asBoolean(); -	mBinding = data["binding"].asString(); -} - - -LLSD LLImportMaterial::asLLSD() -{ -	LLSD ret; - -	ret["diffuse"]["filename"] = mDiffuseMapFilename; -	ret["diffuse"]["label"] = mDiffuseMapLabel; -	ret["diffuse"]["color"] = mDiffuseColor.getValue(); -	ret["fullbright"] = mFullbright; -	ret["binding"] = mBinding; - -	return ret; -} -  void LLMeshRepository::buildPhysicsMesh(LLModel::Decomposition& decomp)  {  	decomp.mMesh.resize(decomp.mHull.size()); diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 39280bea3a..688cd01a87 100755 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -90,54 +90,6 @@ public:  	}  }; -class LLImportMaterial -{ -public: -	LLPointer<LLViewerFetchedTexture> mDiffuseMap; -	std::string mDiffuseMapFilename; -	std::string mDiffuseMapLabel; -	std::string mBinding; -	LLColor4 mDiffuseColor; -	bool mFullbright; - -	bool operator<(const LLImportMaterial ¶ms) const; - -	LLImportMaterial()  -		: mFullbright(false)  -	{  -		mDiffuseColor.set(1,1,1,1); -	} - -	LLImportMaterial(LLSD& data); - -	LLSD asLLSD(); -}; - -class LLModelInstance  -{ -public: -	LLPointer<LLModel> mModel; -	LLPointer<LLModel> mLOD[5]; -	 -	std::string mLabel; - -	LLUUID mMeshID; -	S32 mLocalMeshID; - -	LLMatrix4 mTransform; -	std::map<std::string, LLImportMaterial> mMaterial; - -	LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, std::map<std::string, LLImportMaterial>& materials) -		: mModel(model), mLabel(label), mTransform(transform), mMaterial(materials) -	{ -		mLocalMeshID = -1; -	} - -	LLModelInstance(LLSD& data); - -	LLSD asLLSD(); -}; -  class LLPhysicsDecomp : public LLThread  {  public: @@ -483,6 +435,8 @@ public:  	// Inherited from LLCore::HttpHandler  	virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response); +        LLViewerFetchedTexture* FindViewerTexture(const LLImportMaterial& material); +  private:  	LLHandle<LLWholeModelFeeObserver> mFeeObserverHandle;  	LLHandle<LLWholeModelUploadObserver> mUploadObserverHandle; | 
