diff options
24 files changed, 749 insertions, 692 deletions
diff --git a/BuildParams b/BuildParams index a064faf870..df88b6be01 100644 --- a/BuildParams +++ b/BuildParams @@ -103,6 +103,16 @@ mesh-development.build_CYGWIN_Debug = false  mesh-development.build_viewer_update_version_manager = false  # ======================================== +# mesh-asset-deprecation +# ======================================== +mesh-asset-deprecation.viewer_channel = "Project Viewer - Mesh Asset Deprecation" +mesh-asset-deprecation.login_channel = "Project Viewer - Mesh Asset Deprecation" +mesh-asset-deprecation.viewer_grid = aditi +mesh-asset-deprecation.build_debug_release_separately = true +mesh-asset-deprecation.build_CYGWIN_Debug = false +mesh-asset-deprecation.build_viewer_update_version_manager = false + +# ========================================  # viewer-mesh  # ======================================== diff --git a/autobuild.xml b/autobuild.xml index ec52d6e331..6349ea47e2 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -18,9 +18,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>930bdd987a321eda1838caba8cd6098f</string> +              <string>76827e62b9af4756caa1d3d8da0bafc3</string>
                <key>url</key> -              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glod/rev/230348/arch/Darwin/installer/glod-1.0pre4-darwin-20110519.tar.bz2</string> +              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glod/rev/232275/arch/Darwin/installer/glod-1.0pre4-darwin-20110607.tar.bz2</string>
              </map>              <key>name</key>              <string>darwin</string> @@ -30,9 +30,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>fb33b6cac2e6b98f93c5efa2af2e5a00</string> +              <string>7841a681db47017ccc6527b52876bacb</string>
                <key>url</key> -              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glod/rev/230348/arch/Linux/installer/glod-1.0pre4-linux-20110519.tar.bz2</string> +              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glod/rev/232275/arch/Linux/installer/glod-1.0pre4-linux-20110607.tar.bz2</string>
              </map>              <key>name</key>              <string>linux</string> @@ -42,9 +42,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>388cf0e292f756b4bb37696622f0bbc5</string> +              <string>cca713fe7395260d91aaef2f2b5d820a</string>
                <key>url</key> -              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glod/rev/230348/arch/CYGWIN/installer/glod-1.0pre4-windows-20110519.tar.bz2</string> +              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glod/rev/232275/arch/CYGWIN/installer/glod-1.0pre4-windows-20110607.tar.bz2</string>
              </map>              <key>name</key>              <string>windows</string> diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 9eecb7bfe2..8c81f27784 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2419,12 +2419,25 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)  		for (U32 i = 0; i < face_count; ++i)  		{ +			LLVolumeFace& face = mVolumeFaces[i]; + +			if (mdl[i].has("NoGeometry")) +			{ //face has no geometry, continue +				face.resizeIndices(3); +				face.resizeVertices(1); +				memset(face.mPositions, 0, sizeof(LLVector4a)); +				memset(face.mNormals, 0, sizeof(LLVector4a)); +				memset(face.mTexCoords, 0, sizeof(LLVector2)); +				memset(face.mIndices, 0, sizeof(U16)*3); +				continue; +			} +  			LLSD::Binary pos = mdl[i]["Position"];  			LLSD::Binary norm = mdl[i]["Normal"];  			LLSD::Binary tc = mdl[i]["TexCoord0"];  			LLSD::Binary idx = mdl[i]["TriangleList"]; -			LLVolumeFace& face = mVolumeFaces[i]; +			  			//copy out indices  			face.resizeIndices(idx.size()/2); @@ -2629,14 +2642,20 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)  			LLVector4a& min = face.mExtents[0];  			LLVector4a& max = face.mExtents[1]; -			min.clear(); -			max.clear(); -			min = max = face.mPositions[0]; - -			for (S32 i = 1; i < face.mNumVertices; ++i) +			if (face.mNumVertices < 3) +			{ //empty face, use a dummy 1cm (at 1m scale) bounding box +				min.splat(-0.005f); +				max.splat(0.005f); +			} +			else  			{ -				min.setMin(min, face.mPositions[i]); -				max.setMax(max, face.mPositions[i]); +				min = max = face.mPositions[0]; + +				for (S32 i = 1; i < face.mNumVertices; ++i) +				{ +					min.setMin(min, face.mPositions[i]); +					max.setMax(max, face.mPositions[i]); +				}  			}  		}  	} @@ -5493,6 +5512,8 @@ LLVolumeFace::LLVolumeFace() :  	mOctree(NULL)  {  	mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3); +	mExtents[0].splat(-0.5f); +	mExtents[1].splat(0.5f);  	mCenter = mExtents+2;  } diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp index 5d03615e53..6133f50637 100644 --- a/indra/llmessage/message_prehash.cpp +++ b/indra/llmessage/message_prehash.cpp @@ -742,6 +742,7 @@ char const* const _PREHASH_MoneyData = LLMessageStringTable::getInstance()->getS  char const* const _PREHASH_ObjectDeselect = LLMessageStringTable::getInstance()->getString("ObjectDeselect");  char const* const _PREHASH_NewAssetID = LLMessageStringTable::getInstance()->getString("NewAssetID");  char const* const _PREHASH_ObjectAdd = LLMessageStringTable::getInstance()->getString("ObjectAdd"); +char const* const _PREHASH_SimulatorFeatures = LLMessageStringTable::getInstance()->getString("SimulatorFeatures");  char const* const _PREHASH_RayEndIsIntersection = LLMessageStringTable::getInstance()->getString("RayEndIsIntersection");  char const* const _PREHASH_CompleteAuction = LLMessageStringTable::getInstance()->getString("CompleteAuction");  char const* const _PREHASH_CircuitCode = LLMessageStringTable::getInstance()->getString("CircuitCode"); diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h index 8dc86601e6..f94ee1ed22 100644 --- a/indra/llmessage/message_prehash.h +++ b/indra/llmessage/message_prehash.h @@ -742,6 +742,7 @@ extern char const* const _PREHASH_MoneyData;  extern char const* const _PREHASH_ObjectDeselect;  extern char const* const _PREHASH_NewAssetID;  extern char const* const _PREHASH_ObjectAdd; +extern char const* const _PREHASH_SimulatorFeatures;  extern char const* const _PREHASH_RayEndIsIntersection;  extern char const* const _PREHASH_CompleteAuction;  extern char const* const _PREHASH_CircuitCode; diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index 9ae1bbacf1..b3d5c7b072 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -50,7 +50,7 @@ std::string model_names[] =  	"low_lod",  	"medium_lod",  	"high_lod", -	"physics_shape" +	"physics_mesh"  };  const int MODEL_NAMES_LENGTH = sizeof(model_names) / sizeof(std::string); @@ -1418,7 +1418,11 @@ LLSD LLModel::writeModel(  	if (!decomp.mBaseHull.empty() ||  		!decomp.mHull.empty())		  	{ -		mdl["decomposition"] = decomp.asLLSD(); +		mdl["physics_convex"] = decomp.asLLSD(); +		if (!decomp.mHull.empty()) +		{ //convex decomposition exists, physics mesh will not be used +			model[LLModel::LOD_PHYSICS] = NULL; +		}  	}  	for (U32 idx = 0; idx < MODEL_NAMES_LENGTH; ++idx) @@ -1443,8 +1447,9 @@ LLSD LLModel::writeModel(  			for (S32 i = 0; i < model[idx]->getNumVolumeFaces(); ++i)  			{ //for each face  				const LLVolumeFace& face = model[idx]->getVolumeFace(i); -				if (!face.mNumVertices) +				if (face.mNumVertices < 3)  				{ //don't export an empty face +					mdl[model_names[idx]][i]["NoGeometry"] = true;  					continue;  				}  				LLSD::Binary verts(face.mNumVertices*3*2); @@ -1477,7 +1482,6 @@ LLSD LLModel::writeModel(  					//position + normal  					for (U32 k = 0; k < 3; ++k)  					{ //for each component -  						//convert to 16-bit normalized across domain  						U16 val = (U16) (((pos[k]-min_pos.mV[k])/pos_range.mV[k])*65535); @@ -1521,7 +1525,6 @@ LLSD LLModel::writeModel(  				//write out face data  				mdl[model_names[idx]][i]["PositionDomain"]["Min"] = min_pos.getValue();  				mdl[model_names[idx]][i]["PositionDomain"]["Max"] = max_pos.getValue(); -  				mdl[model_names[idx]][i]["TexCoord0Domain"]["Min"] = min_tc.getValue();  				mdl[model_names[idx]][i]["TexCoord0Domain"]["Max"] = max_tc.getValue(); @@ -1614,15 +1617,15 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)  	std::string decomposition; -	if (mdl.has("decomposition")) +	if (mdl.has("physics_convex"))  	{ //write out convex decomposition -		decomposition = zip_llsd(mdl["decomposition"]); +		decomposition = zip_llsd(mdl["physics_convex"]);  		U32 size = decomposition.size();  		if (size > 0)  		{ -			header["decomposition"]["offset"] = (LLSD::Integer) cur_offset; -			header["decomposition"]["size"] = (LLSD::Integer) size; +			header["physics_convex"]["offset"] = (LLSD::Integer) cur_offset; +			header["physics_convex"]["size"] = (LLSD::Integer) size;  			cur_offset += size;  			bytes += size;  		} @@ -1643,11 +1646,6 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)  			cur_offset += size;  			bytes += size;  		} -		else -		{ -			header[model_names[i]]["offset"] = -1; -			header[model_names[i]]["size"] = 0; -		}  	}  	if (!nowrite) @@ -1661,7 +1659,7 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)  		if (!decomposition.empty())  		{ //write decomposition block -			ostr.write((const char*) decomposition.data(), header["decomposition"]["size"].asInteger()); +			ostr.write((const char*) decomposition.data(), header["physics_convex"]["size"].asInteger());  		}  		for (S32 i = 0; i < MODEL_NAMES_LENGTH; i++) @@ -1800,7 +1798,7 @@ bool LLModel::loadModel(std::istream& is)  		"low_lod",  		"medium_lod",  		"high_lod", -		"physics_shape", +		"physics_mesh",  	};  	const S32 MODEL_LODS = 5; @@ -1899,8 +1897,8 @@ bool LLModel::loadSkinInfo(LLSD& header, std::istream &is)  bool LLModel::loadDecomposition(LLSD& header, std::istream& is)  { -	S32 offset = header["decomposition"]["offset"].asInteger(); -	S32 size = header["decomposition"]["size"].asInteger(); +	S32 offset = header["physics_convex"]["offset"].asInteger(); +	S32 size = header["physics_convex"]["size"].asInteger();  	if (offset >= 0 && size > 0)  	{ @@ -2040,7 +2038,7 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)  	{  		// updated for const-correctness. gcc is picky about this type of thing - Nyx  		const LLSD::Binary& hulls = decomp["HullList"].asBinary(); -		const LLSD::Binary& position = decomp["Position"].asBinary(); +		const LLSD::Binary& position = decomp["Positions"].asBinary();  		U16* p = (U16*) &position[0]; @@ -2050,11 +2048,19 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)  		LLVector3 max;  		LLVector3 range; -		min.setValue(decomp["Min"]); -		max.setValue(decomp["Max"]); +		if (decomp.has("Min")) +		{ +			min.setValue(decomp["Min"]); +			max.setValue(decomp["Max"]); +		} +		else +		{ +			min.set(-0.5f, -0.5f, -0.5f); +			max.set(0.5f, 0.5f, 0.5f); +		} +  		range = max-min; -		  		for (U32 i = 0; i < hulls.size(); ++i)  		{  			U16 count = (hulls[i] == 0) ? 256 : hulls[i]; @@ -2070,6 +2076,7 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)  				//point must be unique  				//llassert(valid.find(test) == valid.end());  				valid.insert(test); +  				mHull[i].push_back(LLVector3(  					(F32) p[0]/65535.f*range.mV[0]+min.mV[0],  					(F32) p[1]/65535.f*range.mV[1]+min.mV[1], @@ -2084,9 +2091,9 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)  		}  	} -	if (decomp.has("Hull")) +	if (decomp.has("BoundingVerts"))  	{ -		const LLSD::Binary& position = decomp["Hull"].asBinary(); +		const LLSD::Binary& position = decomp["BundingVerts"].asBinary();  		U16* p = (U16*) &position[0]; @@ -2141,11 +2148,9 @@ LLSD LLModel::Decomposition::asLLSD() const  	}  	//write decomposition block -	// ["decomposition"]["HullList"] -- list of 8 bit integers, each entry represents a hull with specified number of points -	// ["decomposition"]["PositionDomain"]["Min"/"Max"] -	// ["decomposition"]["Position"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points -	// ["decomposition"]["Hull"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points representing a single hull approximation of given shape -	 +	// ["physics_convex"]["HullList"] -- list of 8 bit integers, each entry represents a hull with specified number of points +	// ["physics_convex"]["Position"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points +	// ["physics_convex"]["BoundingVerts"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points representing a single hull approximation of given shape  	//get minimum and maximum  	LLVector3 min; @@ -2194,6 +2199,8 @@ LLSD LLModel::Decomposition::asLLSD() const  	{  		LLSD::Binary p(total*3*2); +		LLVector3 min(-0.5f, -0.5f, -0.5f); +		LLVector3 max(0.5f, 0.5f, 0.5f);  		LLVector3 range = max-min;  		U32 vert_idx = 0; @@ -2209,8 +2216,12 @@ LLSD LLModel::Decomposition::asLLSD() const  				U64 test = 0;  				for (U32 k = 0; k < 3; k++)  				{ +					F32* src = (F32*) (mHull[i][j].mV); + +					llassert(src[k] <= 0.501f && src[k] >= -0.501f); +  					//convert to 16-bit normalized across domain -					U16 val = (U16) (((mHull[i][j].mV[k]-min.mV[k])/range.mV[k])*65535); +					U16 val = (U16) (((src[k]-min.mV[k])/range.mV[k])*65535);  					if(valid.size() < 3)  					{ @@ -2238,13 +2249,15 @@ LLSD LLModel::Decomposition::asLLSD() const  			llassert(valid.size() > 2);  		} -		ret["Position"] = p; +		ret["Positions"] = p;  	}  	if (!mBaseHull.empty())  	{  		LLSD::Binary p(mBaseHull.size()*3*2); +		LLVector3 min(-0.5f, -0.5f, -0.5f); +		LLVector3 max(0.5f, 0.5f, 0.5f);  		LLVector3 range = max-min;  		U32 vert_idx = 0; @@ -2252,6 +2265,8 @@ LLSD LLModel::Decomposition::asLLSD() const  		{  			for (U32 k = 0; k < 3; k++)  			{ +				llassert(mBaseHull[j].mV[k] <= 0.51f && mBaseHull[j].mV[k] >= -0.51f); +  				//convert to 16-bit normalized across domain  				U16 val = (U16) (((mBaseHull[j].mV[k]-min.mV[k])/range.mV[k])*65535); @@ -2267,7 +2282,7 @@ LLSD LLModel::Decomposition::asLLSD() const  			}  		} -		ret["Hull"] = p; +		ret["BoundingVerts"] = p;  	}  	return ret; diff --git a/indra/llui/llresmgr.cpp b/indra/llui/llresmgr.cpp index 39385786bc..820e7cb26a 100644 --- a/indra/llui/llresmgr.cpp +++ b/indra/llui/llresmgr.cpp @@ -337,7 +337,7 @@ LLLocale::LLLocale(const std::string& locale_string)  	char* new_locale_string = setlocale( LC_ALL, locale_string.c_str());  	if ( new_locale_string == NULL)  	{ -		llwarns << "Failed to set locale " << locale_string << llendl; +		LL_WARNS_ONCE("LLLocale") << "Failed to set locale " << locale_string << LL_ENDL;  		setlocale(LC_ALL, SYSTEM_LOCALE.c_str());  	}  	//else diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index 937c4e4c6a..9f4e89691f 100644 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -20,6 +20,7 @@  					<key>tags</key>  						<array>  							<string>AppInit</string> +              <string>Capabilities</string>  							<string>SystemInfo</string>  							<string>TextureCache</string>  							<string>AppCache</string> @@ -43,6 +44,7 @@  						<array>  							<!-- sample entry for debugging a specific item	-->  <!--						<string>Voice</string>							--> +              <string>Capabilities</string>  						</array>  				</map>  			</array> diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 870aec4eff..9f790d03fe 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -459,14 +459,6 @@ S32 LLDrawPoolAvatar::getNumPasses()  	{  		return 10;  	} -	if (LLPipeline::sImpostorRender) -	{ -		return 1; -	} -	else  -	{ -		return 3; -	}  } @@ -1419,7 +1411,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*  void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)  { -	if (avatar->isSelf() && !gAgent.needsRenderAvatar()) +	if (avatar->isSelf() && !gAgent.needsRenderAvatar() || !gMeshRepo.meshRezEnabled())  	{  		return;  	} diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 540ed054e9..b6566fcbd0 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -693,6 +693,19 @@ static void xform(LLVector2 &tex_coord, F32 cosAng, F32 sinAng, F32 offS, F32 of  } +bool less_than_max_mag(const LLVector4a& vec) +{ +	LLVector4a MAX_MAG; +	MAX_MAG.splat(1024.f*1024.f); + +	LLVector4a val; +	val.setAbs(vec); + +	S32 lt = val.lessThan(MAX_MAG).getGatheredBits() & 0x7; +	 +	return lt == 0x7; +} +  BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,  								const LLMatrix4& mat_vert_in, const LLMatrix3& mat_normal_in, BOOL global_volume)  { @@ -727,6 +740,8 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,  		min = face.mExtents[0];  		max = face.mExtents[1]; +		llassert(less_than_max_mag(min)); +		llassert(less_than_max_mag(max));  		//min, max are in volume space, convert to drawable render space  		LLVector4a center; @@ -738,6 +753,9 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,  		size.setSub(max, min);  		size.mul(0.5f); +		llassert(less_than_max_mag(min)); +		llassert(less_than_max_mag(max)); +  		if (!global_volume)  		{  			//VECTORIZE THIS @@ -775,6 +793,8 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,  		newMin = newMax = center; +		llassert(less_than_max_mag(center)); +		  		for (U32 i = 0; i < 4; i++)  		{  			LLVector4a delta; @@ -786,6 +806,9 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,  			newMin.setMin(newMin,min);  			newMax.setMax(newMax,max); + +			llassert(less_than_max_mag(newMin)); +			llassert(less_than_max_mag(newMax));  		}  		if (!mDrawablep->isActive()) @@ -794,14 +817,22 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,  			offset.load3(mDrawablep->getRegion()->getOriginAgent().mV);  			newMin.add(offset);  			newMax.add(offset); +			 +			llassert(less_than_max_mag(newMin)); +			llassert(less_than_max_mag(newMax));  		}  		t.setAdd(newMin, newMax);  		t.mul(0.5f); +		llassert(less_than_max_mag(t)); +		  		//VECTORIZE THIS  		mCenterLocal.set(t.getF32ptr()); +		llassert(less_than_max_mag(newMin)); +		llassert(less_than_max_mag(newMax)); +  		t.setSub(newMax,newMin);  		mBoundingSphereRadius = t.getLength3().getF32()*0.5f; diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 4e71aa7fa6..866cc39eec 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -178,6 +178,80 @@ std::string lod_label_name[NUM_LOD+1] =  	"I went off the end of the lod_label_name array.  Me so smart."  }; + +#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)  {  	for (U32 i = 0; i < face.mNumIndices; ++i) @@ -189,6 +263,31 @@ bool validate_face(const LLVolumeFace& face)  		}  	} +	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;  } @@ -1187,11 +1286,7 @@ void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3&  void LLModelLoader::run()  { -	if (!doLoadModel()) -	{ -		mPreview = NULL; -	} - +	doLoadModel();  	doOnIdleOneTime(boost::bind(&LLModelLoader::loadModelCallback,this));  } @@ -1322,7 +1417,7 @@ bool LLModelLoader::doLoadModel()  			if(model->getStatus() != LLModel::NO_ERRORS)  			{  				setLoadState(ERROR_PARSING + model->getStatus()) ; -				return true ; //abort +				return false; //abort  			}  			if (model.notNull() && validate_model(model)) @@ -2794,7 +2889,7 @@ LLModelPreview::~LLModelPreview()  {  	if (mModelLoader)  	{ -		delete mModelLoader; +		mModelLoader->mPreview = NULL;  		mModelLoader = NULL;  	}  	//*HACK : *TODO : turn this back on when we understand why this crashes @@ -3890,7 +3985,35 @@ void LLModelPreview::updateStatusMessages()  		mMaxTriangleLimit = total_tris[LLModel::LOD_HIGH];  	} +	bool has_degenerate = false; +	{//check for degenerate triangles in physics mesh +		U32 lod = LLModel::LOD_PHYSICS; +		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()) +			{ //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; ) +					{ +						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); + +						if (ll_is_degenerate(v1,v2,v3)) +						{ +							has_degenerate = true; +						} +					} +				} +			} +		} +	} +	  	mFMP->childSetTextArg("submeshes_info", "[SUBMESHES]", llformat("%d", total_submeshes[LLModel::LOD_HIGH]));  	std::string mesh_status_na = mFMP->getString("mesh_status_na"); @@ -3991,7 +4114,10 @@ void LLModelPreview::updateStatusMessages()  		for (U32 j = 0; upload_ok && j < mdl->mPhysics.mHull.size(); ++j)  		{ -			upload_ok = upload_ok && mdl->mPhysics.mHull[i].size() <= 256; +			if (mdl->mPhysics.mHull[j].size() > 256) +			{ +				upload_ok = false; +			}  		}  	} @@ -4015,7 +4141,7 @@ void LLModelPreview::updateStatusMessages()  	}  	const BOOL confirmed_checkbox = mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->getValue().asBoolean(); -	if ( upload_ok && !errorStateFromLoader && skinAndRigOk && confirmed_checkbox) +	if ( upload_ok && !errorStateFromLoader && skinAndRigOk && !has_degenerate && confirmed_checkbox)  	{  		mFMP->childEnable("ok_btn");  	} @@ -4740,39 +4866,43 @@ BOOL LLModelPreview::render()  						LLModel::Decomposition& physics = model->mPhysics; -						if (physics.mMesh.empty()) -						{ //build vertex buffer for physics mesh -							gMeshRepo.buildPhysicsMesh(physics); -						} -							 -						if (!physics.mMesh.empty()) -						{ //render hull instead of mesh +						if (!physics.mHull.empty()) +						{  							render_mesh = false; -							for (U32 i = 0; i < physics.mMesh.size(); ++i) -							{ -								if (explode > 0.f) + +							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)  								{ -									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, 255)); -								} +									if (i+1 >= hull_colors.size()) +									{ +										hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 255)); +									} -									glColor4ubv(hull_colors[i].mV); -								LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals); +										glColor4ubv(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(); +									}  								}  							}  						} @@ -4798,9 +4928,10 @@ BOOL LLModelPreview::render()  							glColor3f(1.f, 1.f, 0.f); -							glLineWidth(3.f); +							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);  						} @@ -4809,6 +4940,80 @@ BOOL LLModelPreview::render()  					gGL.popMatrix();  				} +				glLineWidth(3.f); +				glPointSize(8.f); +				gPipeline.enableLightsFullbright(LLColor4::white); +				//show degenerate triangles +				LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); +				LLGLDisable cull(GL_CULL_FACE); +				glColor4f(1.f,0.f,0.f,1.f); +				const LLVector4a scale(0.5f); + +				for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter) +				{ +					LLModelInstance& instance = *iter; + +					LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS]; + +					if (!model) +					{ +						continue; +					} + +					gGL.pushMatrix(); +					LLMatrix4 mat = instance.mTransform; + +					glMultMatrixf((GLfloat*) mat.mMatrix); + + +					LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread; +					if (decomp) +					{ +						LLMutexLock(decomp->mMutex); + +						LLModel::Decomposition& physics = model->mPhysics; + +						if (physics.mHull.empty()) +						{ +							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]; + +								buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0); + +								LLStrider<LLVector3> pos_strider;  +								buffer->getVertexStrider(pos_strider, 0); +								LLVector4a* pos = (LLVector4a*) pos_strider.get(); +							 +								LLStrider<U16> idx; +								buffer->getIndexStrider(idx, 0); + +								for (U32 i = 0; i < buffer->getNumIndices(); i += 3) +								{ +									LLVector4a v1; v1.setMul(pos[*idx++], scale); +									LLVector4a v2; v2.setMul(pos[*idx++], scale); +									LLVector4a v3; v3.setMul(pos[*idx++], scale); + +									if (ll_is_degenerate(v1,v2,v3)) +									{ +										buffer->draw(LLRender::LINE_LOOP, 3, i); +										buffer->draw(LLRender::POINTS, 3, i); +									} +								} +							} +						} +					} + +					gGL.popMatrix(); +				} +				glLineWidth(1.f); +				glPointSize(1.f); +				gPipeline.enableLightsPreview();  				gGL.setSceneBlendType(LLRender::BT_ALPHA);  			}  		} @@ -5094,54 +5299,7 @@ LLFloaterModelPreview::DecompRequest::DecompRequest(const std::string& stage, LL  	mParams = sInstance->mDecompParams;  	//copy out positions and indices -	if (mdl) -	{ -		U16 index_offset = 0; -		U16 tri[3] ; - -		mPositions.clear(); -		mIndices.clear(); -		mBBox[1] = LLVector3(F32_MIN, F32_MIN, F32_MIN) ; -		mBBox[0] = LLVector3(F32_MAX, F32_MAX, F32_MAX) ; - -		//queue up vertex positions and indices -		for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i) -		{ -			const LLVolumeFace& face = mdl->getVolumeFace(i); -			if (mPositions.size() + face.mNumVertices > 65535) -			{ -				continue; -			} - -			for (U32 j = 0; j < face.mNumVertices; ++j) -			{ -				mPositions.push_back(LLVector3(face.mPositions[j].getF32ptr())); -				for(U32 k = 0 ; k < 3 ; k++) -				{ -					mBBox[0].mV[k] = llmin(mBBox[0].mV[k], mPositions[j].mV[k]) ; -					mBBox[1].mV[k] = llmax(mBBox[1].mV[k], mPositions[j].mV[k]) ; -				} -			} - -			updateTriangleAreaThreshold() ; - -			for (U32 j = 0; j+2 < face.mNumIndices; j += 3) -			{ -				tri[0] = face.mIndices[j] + index_offset ; -				tri[1] = face.mIndices[j + 1] + index_offset ; -				tri[2] = face.mIndices[j + 2] + index_offset ; -				 -				if(isValidTriangle(tri[0], tri[1], tri[2])) -				{ -					mIndices.push_back(tri[0]); -					mIndices.push_back(tri[1]); -					mIndices.push_back(tri[2]); -				} -			}			 - -			index_offset += face.mNumVertices; -		} -	} +	assignData(mdl) ;	  }  void LLFloaterModelPreview::setStatusMessage(const std::string& msg) diff --git a/indra/newview/llfloatermodelwizard.cpp b/indra/newview/llfloatermodelwizard.cpp index e44737f39e..707c8288df 100644 --- a/indra/newview/llfloatermodelwizard.cpp +++ b/indra/newview/llfloatermodelwizard.cpp @@ -422,8 +422,11 @@ void LLFloaterModelWizard::executePhysicsStage(std::string stage_name)  			{  				LLModel* mdl = sInstance->mModelPreview->mModel[LLModel::LOD_PHYSICS][i];  				DecompRequest* request = new DecompRequest(stage_name, mdl); -				sInstance->mCurRequest.insert(request); -				gMeshRepo.mDecompThread->submitRequest(request); +				if(request->isValid()) +				{ +					sInstance->mCurRequest.insert(request); +					gMeshRepo.mDecompThread->submitRequest(request); +				}				  			}  		}  	} @@ -438,54 +441,7 @@ LLFloaterModelWizard::DecompRequest::DecompRequest(const std::string& stage, LLM  	mParams = sInstance->mDecompParams;  	//copy out positions and indices -	if (mdl) -	{ -		U16 index_offset = 0; -		U16 tri[3] ; - -		mPositions.clear(); -		mIndices.clear(); -		mBBox[1] = LLVector3(F32_MIN, F32_MIN, F32_MIN) ; -		mBBox[0] = LLVector3(F32_MAX, F32_MAX, F32_MAX) ; -		 -		//queue up vertex positions and indices -		for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i) -		{ -			const LLVolumeFace& face = mdl->getVolumeFace(i); -			if (mPositions.size() + face.mNumVertices > 65535) -			{ -				continue; -			} - -			for (U32 j = 0; j < face.mNumVertices; ++j) -			{ -				mPositions.push_back(LLVector3(face.mPositions[j].getF32ptr())); -				for(U32 k = 0 ; k < 3 ; k++) -				{ -					mBBox[0].mV[k] = llmin(mBBox[0].mV[k], mPositions[j].mV[k]) ; -					mBBox[1].mV[k] = llmax(mBBox[1].mV[k], mPositions[j].mV[k]) ; -				} -			} - -			updateTriangleAreaThreshold() ; - -			for (U32 j = 0; j+2 < face.mNumIndices; j += 3) -			{ -				tri[0] = face.mIndices[j] + index_offset ; -				tri[1] = face.mIndices[j + 1] + index_offset ; -				tri[2] = face.mIndices[j + 2] + index_offset ; -				 -				if(isValidTriangle(tri[0], tri[1], tri[2])) -				{ -					mIndices.push_back(tri[0]); -					mIndices.push_back(tri[1]); -					mIndices.push_back(tri[2]); -				} -			} - -			index_offset += face.mNumVertices; -		} -	} +	assignData(mdl) ;	  } diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index fc6976755f..6b3e3088d5 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -82,6 +82,7 @@  #include "llvlcomposition.h"  #include "lltrans.h"  #include "llagentui.h" +#include "llmeshrepository.h"  const S32 TERRAIN_TEXTURE_COUNT = 4;  const S32 CORNER_COUNT = 4; @@ -590,9 +591,7 @@ bool LLPanelRegionGeneralInfo::refreshFromRegion(LLViewerRegion* region)  	getChildView("im_btn")->setEnabled(allow_modify);  	getChildView("manage_telehub_btn")->setEnabled(allow_modify); -	const bool enable_mesh = gSavedSettings.getBOOL("MeshEnabled") &&  -		gAgent.getRegion() && -		!gAgent.getRegion()->getCapability("GetMesh").empty(); +	const bool enable_mesh = gMeshRepo.meshRezEnabled();  	getChildView("mesh_rez_enabled_check")->setVisible(enable_mesh);  	getChildView("mesh_rez_enabled_check")->setEnabled(getChildView("mesh_rez_enabled_check")->getEnabled() && enable_mesh);  	// Data gets filled in by processRegionInfo diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index edcb96314b..0d798afdcc 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -86,6 +86,7 @@  #include "llvovolume.h"  #include "lluictrlfactory.h"  #include "llaccountingquotamanager.h" +#include "llmeshrepository.h"  // Globals  LLFloaterTools *gFloaterTools = NULL; @@ -423,7 +424,8 @@ void LLFloaterTools::refresh()  	// Refresh object and prim count labels  	LLLocale locale(LLLocale::USER_LOCALE); -	if ((gAgent.getRegion() && (gAgent.getRegion()->getCapability("GetMesh").empty() || gAgent.getRegion()->getCapability("ObjectAdd").empty())) || !gSavedSettings.getBOOL("MeshEnabled")) +#if 0 +	if (gMeshRepo.meshRezEnabled())  	{		  		std::string obj_count_string;  		LLResMgr::getInstance()->getIntegerString(obj_count_string, LLSelectMgr::getInstance()->getSelection()->getRootObjectCount()); @@ -447,6 +449,7 @@ void LLFloaterTools::refresh()  		getChildView("RenderingCost")->setEnabled(have_selection && sShowObjectCost);  	}  	else +#endif  	{  		// Get the number of objects selected  		std::string root_object_count_string; @@ -788,10 +791,7 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)  		getChildView("Strength:")->setVisible( land_visible);  	} -	bool show_mesh_cost = gAgent.getRegion() &&  -		                  !gAgent.getRegion()->getCapability("GetMesh").empty() &&  -						  gSavedSettings.getBOOL("MeshEnabled") && -						  !gAgent.getRegion()->getCapability("ObjectAdd").empty(); +	bool show_mesh_cost = gMeshRepo.meshRezEnabled();  	getChildView("obj_count")->setVisible( !land_visible && !show_mesh_cost);  	getChildView("prim_count")->setVisible( !land_visible && !show_mesh_cost); diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp index 673f28e01f..4eb94dfb8e 100644 --- a/indra/newview/llmanipscale.cpp +++ b/indra/newview/llmanipscale.cpp @@ -58,6 +58,7 @@  #include "llworld.h"  #include "v2math.h"  #include "llvoavatar.h" +#include "llmeshrepository.h"  const F32 MAX_MANIP_SELECT_DISTANCE_SQUARED = 11.f * 11.f; @@ -90,10 +91,7 @@ F32 get_default_max_prim_scale(bool is_flora)  {  	// a bit of a hack, but if it's foilage, we don't want to use the  	// new larger scale which would result in giant trees and grass -	if (gSavedSettings.getBOOL("MeshEnabled") &&  -		gAgent.getRegion() &&  -		!gAgent.getRegion()->getCapability("GetMesh").empty() && -		!gAgent.getRegion()->getCapability("ObjectAdd").empty() && +	if (gMeshRepo.meshRezEnabled() &&  		!is_flora)  	{  		return DEFAULT_MAX_PRIM_SCALE; diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 8f084b9bfc..9855a641ed 100644..100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -61,6 +61,9 @@  #include "pipeline.h"  #include "llinventorymodel.h"  #include "llfoldertype.h" +#include "llviewerparcelmgr.h" + +#include "boost/lexical_cast.hpp"  #ifndef LL_WINDOWS  #include "netdb.h" @@ -85,6 +88,12 @@ U32 LLMeshRepository::sPeakKbps = 0;  const U32 MAX_TEXTURE_UPLOAD_RETRIES = 5; +static S32 dump_num = 0; +std::string make_dump_name(std::string prefix, S32 num) +{ +	return prefix + boost::lexical_cast<std::string>(num) + std::string(".xml"); +	 +}  void dumpLLSDToFile(const LLSD& content, std::string filename);  std::string header_lod[] =  @@ -459,6 +468,49 @@ public:  }; +void log_upload_error(const LLSD& content,std::string stage) +{ +	if (content.has("error")) +	{ +		const LLSD& err = content["error"]; +		llwarns << "mesh upload failed, stage " << stage +				<< " message " << err["message"].asString() << " id " << err["identifier"].asString() +				<< llendl; + +		if (content.has("errors")) +		{ +			const LLSD& err_list = content["errors"]; +			for (LLSD::array_const_iterator it = err_list.beginArray(); +				 it != err_list.endArray(); +				 ++it) +			{ +				const LLSD& err_entry = *it; +				std::string index_info; +				std::string texture_index_str = err_entry["TextureIndex"].asString(); +				if (!texture_index_str.empty()) +				{ +					index_info += " texture_index: " + texture_index_str; +				} +				std::string	mesh_index_str = err_entry["MeshIndex"].asString(); +				if (!mesh_index_str.empty()) +				{ +					index_info += " mesh_index: " + mesh_index_str; +				} +				llwarns << "mesh err code " << err_entry["error"].asString() +						<< " message " << err_entry["message"] +						<< index_info +						<< llendl; +			} +		} +	} +	else +	{ +		llwarns << "bad mesh, no error information available" << llendl; +	} + +	 +} +  class LLModelObjectUploadResponder: public LLCurl::Responder  {  	LLSD mObjectAsset; @@ -498,18 +550,21 @@ public:  		//assert_main_thread();  		llinfos << "completed" << llendl;  		mThread->mPendingUploads--; -		dumpLLSDToFile(content,"whole_model_fee_response.xml"); +		dumpLLSDToFile(content,make_dump_name("whole_model_fee_response_",dump_num)); +		llinfos << "LLWholeModelFeeResponder content: " << content << llendl;  		if (isGoodStatus(status))  		{ +			llinfos << "fee request succeeded" << llendl;  			mThread->mWholeModelUploadURL = content["uploader"].asString();   		}  		else  		{ -			llinfos << "upload failed" << llendl; +			llwarns << "fee request failed" << llendl; +			log_upload_error(content,"fee");  			mThread->mWholeModelUploadURL = "";  		} -  	} +  };  class LLWholeModelUploadResponder: public LLCurl::Responder @@ -528,13 +583,22 @@ public:  						   const LLSD& content)  	{  		//assert_main_thread(); -		llinfos << "upload completed" << llendl;  		mThread->mPendingUploads--; -		dumpLLSDToFile(content,"whole_model_upload_response.xml"); +		dumpLLSDToFile(content,make_dump_name("whole_model_upload_response_",dump_num)); +		llinfos << "LLWholeModelUploadResponder content: " << content << llendl;  		// requested "mesh" asset type isn't actually the type  		// of the resultant object, fix it up here. -		mPostData["asset_type"] = "object"; -		gMeshRepo.updateInventory(LLMeshRepository::inventory_data(mPostData,content)); +		if (isGoodStatus(status)) +		{ +			llinfos << "upload succeeded" << llendl; +			mPostData["asset_type"] = "object"; +			gMeshRepo.updateInventory(LLMeshRepository::inventory_data(mPostData,content)); +		} +		else +		{ +			llwarns << "upload failed" << llendl; +			log_upload_error(content,"upload"); +		}  	}  }; @@ -829,8 +893,8 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)  	if (header_size > 0)  	{ -		S32 offset = header_size + mMeshHeader[mesh_id]["decomposition"]["offset"].asInteger(); -		S32 size = mMeshHeader[mesh_id]["decomposition"]["size"].asInteger(); +		S32 offset = header_size + mMeshHeader[mesh_id]["physics_convex"]["offset"].asInteger(); +		S32 size = mMeshHeader[mesh_id]["physics_convex"]["size"].asInteger();  		mHeaderMutex->unlock(); @@ -901,8 +965,8 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)  	if (header_size > 0)  	{ -		S32 offset = header_size + mMeshHeader[mesh_id]["physics_shape"]["offset"].asInteger(); -		S32 size = mMeshHeader[mesh_id]["physics_shape"]["size"].asInteger(); +		S32 offset = header_size + mMeshHeader[mesh_id]["physics_mesh"]["offset"].asInteger(); +		S32 size = mMeshHeader[mesh_id]["physics_mesh"]["size"].asInteger();  		mHeaderMutex->unlock(); @@ -1294,8 +1358,6 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data,  	mOrigin = gAgent.getPositionAgent();  	mHost = gAgent.getRegionHost(); -	mUploadObjectAssetCapability = gAgent.getRegion()->getCapability("UploadObjectAsset"); -	mNewInventoryCapability = gAgent.getRegion()->getCapability("NewFileAgentInventoryVariablePrice");  	mWholeModelFeeCapability = gAgent.getRegion()->getCapability("NewFileAgentInventory");  	mOrigin += gAgent.getAtAxis() * scale.magVec(); @@ -1315,35 +1377,7 @@ LLMeshUploadThread::DecompRequest::DecompRequest(LLModel* mdl, LLModel* base_mod  	mThread = thread;  	//copy out positions and indices -	if (mdl) -	{ -		U16 index_offset = 0; - -		mPositions.clear(); -		mIndices.clear(); -			 -		//queue up vertex positions and indices -		for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i) -		{ -			const LLVolumeFace& face = mdl->getVolumeFace(i); -			if (mPositions.size() + face.mNumVertices > 65535) -			{ -				continue; -			} - -			for (U32 j = 0; j < face.mNumVertices; ++j) -			{ -				mPositions.push_back(LLVector3(face.mPositions[j].getF32ptr())); -			} - -			for (U32 j = 0; j < face.mNumIndices; ++j) -			{ -				mIndices.push_back(face.mIndices[j]+index_offset); -			} - -			index_offset += face.mNumVertices; -		} -	} +	assignData(mdl) ;	  	mThread->mFinalDecomp = this;  	mThread->mPhysicsComplete = false; @@ -1385,14 +1419,7 @@ BOOL LLMeshUploadThread::isDiscarded()  void LLMeshUploadThread::run()  { -	if (gSavedSettings.getBOOL("MeshUseWholeModelUpload")) -	{ -		doWholeModelUpload(); -	} -	else -	{ -		doIterativeUpload(); -	} +	doWholeModelUpload();  }  void dumpLLSDToFile(const LLSD& content, std::string filename) @@ -1431,9 +1458,13 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)  	{  		LLMeshUploadData data;  		data.mBaseModel = iter->first; -		LLModelInstance& instance = *(iter->second.begin()); -		LLModel* model = instance.mModel; -		if (mesh_index.find(model) == mesh_index.end()) +		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.  			std::string model_name = data.mBaseModel->getName(); @@ -1466,107 +1497,116 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)  			std::string str = ostr.str();  			res["mesh_list"][mesh_num] = LLSD::Binary(str.begin(),str.end());  -			mesh_index[model] = mesh_num; +			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; +			LLSD instance_entry; -		for (S32 i = 0; i < 5; i++) -		{ -			data.mModel[i] = instance.mLOD[i]; -		} +			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); +			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; -		LLPermissions perm; -		perm.setOwnerAndGroup(gAgent.getID(), gAgent.getID(), LLUUID::null, false); -		perm.setCreator(gAgent.getID()); +			instance_entry["material"] = LL_MCODE_WOOD; +			LLPermissions perm; +			perm.setOwnerAndGroup(gAgent.getID(), gAgent.getID(), LLUUID::null, false); +			perm.setCreator(gAgent.getID()); -		perm.initMasks(PERM_ITEM_UNRESTRICTED | PERM_MOVE, //base -					   PERM_ITEM_UNRESTRICTED | PERM_MOVE, //owner -					   LLFloaterPerms::getEveryonePerms(), -					   LLFloaterPerms::getGroupPerms(), -					   LLFloaterPerms::getNextOwnerPerms()); -		instance_entry["permissions"] = ll_create_sd_from_permissions(perm); -		instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL); -		instance_entry["mesh"] = mesh_index[model]; +			perm.initMasks(PERM_ITEM_UNRESTRICTED | PERM_MOVE, //base +						   PERM_ITEM_UNRESTRICTED | PERM_MOVE, //owner +						   LLFloaterPerms::getEveryonePerms(), +						   LLFloaterPerms::getGroupPerms(), +						   LLFloaterPerms::getNextOwnerPerms()); +			instance_entry["permissions"] = ll_create_sd_from_permissions(perm); +			instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL); +			instance_entry["mesh"] = mesh_index[data.mBaseModel]; -		if (mUploadTextures) -		{  			instance_entry["face_list"] = LLSD::emptyArray(); -			for (S32 face_num = 0; face_num < model->getNumVolumeFaces(); face_num++) +			for (S32 face_num = 0; face_num < data.mBaseModel->getNumVolumeFaces(); face_num++)  			{  				LLImportMaterial& material = instance.mMaterial[face_num];  				LLSD face_entry = LLSD::emptyMap();  				LLViewerFetchedTexture *texture = material.mDiffuseMap.get(); -				if (texture != NULL) +				if ((texture != NULL) && +					(textures.find(texture) == textures.end()))  				{ -					if (textures.find(texture) == textures.end()) -					{ -						textures.insert(texture); -					} +					textures.insert(texture); +				} -					std::stringstream ostr; -					if (include_textures) // otherwise data is blank. +				std::stringstream texture_str; +				if (texture != NULL && include_textures && mUploadTextures) +				{ +					// Get binary rep of texture, if needed. +					LLTextureUploadData data(texture, material.mDiffuseMapLabel); +					if (!data.mTexture->isRawImageValid())  					{ -						LLTextureUploadData data(texture, material.mDiffuseMapLabel); -						if (!data.mTexture->isRawImageValid()) -						{ -							data.mTexture->reloadRawImage(data.mTexture->getDiscardLevel()); -						} -						 -						LLPointer<LLImageJ2C> upload_file = -							LLViewerTextureList::convertToUploadFile(data.mTexture->getRawImage()); -						ostr.write((const char*) upload_file->getData(), upload_file->getDataSize()); +						data.mTexture->reloadRawImage(data.mTexture->getDiscardLevel());  					} +						 +					LLPointer<LLImageJ2C> upload_file = +						LLViewerTextureList::convertToUploadFile(data.mTexture->getRawImage()); +					texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize()); +				} -					if (texture_index.find(texture) == texture_index.end()) -					{ -						texture_index[texture] = texture_num; -						std::string str = ostr.str(); -						res["texture_list"][texture_num] = LLSD::Binary(str.begin(),str.end()); -						texture_num++; -					} +				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) +				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["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["colors"] = ll_sd_from_color4(material.mDiffuseColor); +				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++; +			res["instance_list"][instance_num] = instance_entry; +			instance_num++; +		}  	}  	result["asset_resources"] = res; -	dumpLLSDToFile(result,"whole_model.xml"); +	dumpLLSDToFile(result,make_dump_name("whole_model_",dump_num));  	dest = result;  }  void LLMeshUploadThread::doWholeModelUpload()  { +	dump_num++; +	  	mCurlRequest = new LLCurlRequest();	  	// Queue up models for hull generation (viewer-side) @@ -1601,7 +1641,10 @@ void LLMeshUploadThread::doWholeModelUpload()  		llassert(physics != NULL);  		DecompRequest* request = new DecompRequest(physics, data.mBaseModel, this); -		gMeshRepo.mDecompThread->submitRequest(request); +		if(request->isValid()) +		{ +			gMeshRepo.mDecompThread->submitRequest(request); +		}		  	}  	while (!mPhysicsComplete) @@ -1611,7 +1654,7 @@ void LLMeshUploadThread::doWholeModelUpload()  	LLSD model_data;  	wholeModelToLLSD(model_data,false); -	dumpLLSDToFile(model_data,"whole_model_fee_request.xml"); +	dumpLLSDToFile(model_data,make_dump_name("whole_model_fee_request_",dump_num));  	mPendingUploads++;  	LLCurlRequest::headers_t headers; @@ -1633,7 +1676,7 @@ void LLMeshUploadThread::doWholeModelUpload()  		LLSD full_model_data;  		wholeModelToLLSD(full_model_data, true);  		LLSD body = full_model_data["asset_resources"]; -		dumpLLSDToFile(body,"whole_model_body.xml"); +		dumpLLSDToFile(body,make_dump_name("whole_model_body_",dump_num));  		mCurlRequest->post(mWholeModelUploadURL, headers, body,  						   new LLWholeModelUploadResponder(this, model_data));  		do @@ -1649,163 +1692,6 @@ void LLMeshUploadThread::doWholeModelUpload()  	mFinished = true;  } -void LLMeshUploadThread::doIterativeUpload() -{ -	if(isDiscarded()) -	{ -		mFinished = true; -		return ; -	} -	 -	mCurlRequest = new LLCurlRequest();	 - -	std::set<LLViewerTexture* > textures; - -	//populate upload queue with relevant models -	for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter) -	{ -		LLMeshUploadData data; -		data.mBaseModel = iter->first; - -		LLModelInstance& instance = *(iter->second.begin()); - -		for (S32 i = 0; i < 5; i++) -		{ -			data.mModel[i] = instance.mLOD[i]; -		} - -		uploadModel(data); - -		if (mUploadTextures) -		{ -			for (std::vector<LLImportMaterial>::iterator material_iter = instance.mMaterial.begin(); -				material_iter != instance.mMaterial.end(); ++material_iter) -			{ - -				if (textures.find(material_iter->mDiffuseMap.get()) == textures.end()) -				{ -					textures.insert(material_iter->mDiffuseMap.get()); -					 -					LLTextureUploadData data(material_iter->mDiffuseMap.get(), material_iter->mDiffuseMapLabel); -					uploadTexture(data); -				} -			} -		} - -		//queue up models for hull generation -		LLModel* physics = data.mModel[LLModel::LOD_PHYSICS]; -		if (physics == NULL) -		{ //no physics model available, use high lod -			physics = data.mModel[LLModel::LOD_HIGH]; -		} -		 -		DecompRequest* request = new DecompRequest(physics, data.mBaseModel, this); -		gMeshRepo.mDecompThread->submitRequest(request); -	} - -	while (!mPhysicsComplete) -	{ -		apr_sleep(100); -	} - -	//upload textures -	bool done = false; -	do -	{ -		if (!mTextureQ.empty()) -		{ -			sendCostRequest(mTextureQ.front()); -			mTextureQ.pop(); -		} - -		if (!mConfirmedTextureQ.empty()) -		{ -			doUploadTexture(mConfirmedTextureQ.front()); -			mConfirmedTextureQ.pop(); -		} - -		mCurlRequest->process(); - -		done = mTextureQ.empty() && mConfirmedTextureQ.empty(); -	} -	while (!done || mCurlRequest->getQueued() > 0); - -	LLSD object_asset; -	object_asset["objects"] = LLSD::emptyArray(); - -	done = false; -	do  -	{ -		static S32 count = 0; -		static F32 last_hundred = gFrameTimeSeconds; -		if (gFrameTimeSeconds - last_hundred > 1.f) -		{ -			last_hundred = gFrameTimeSeconds; -			count = 0; -		} - -		//how many requests to push before calling process -		const S32 PUSH_PER_PROCESS = 32; - -		S32 tcount = llmin(count+PUSH_PER_PROCESS, 100); - -		while (!mUploadQ.empty() && count < tcount) -		{ //send any pending upload requests -			mMutex->lock(); -			LLMeshUploadData data = mUploadQ.front(); -			mUploadQ.pop(); -			mMutex->unlock(); -			sendCostRequest(data); -			count++; -		} - -		tcount = llmin(count+PUSH_PER_PROCESS, 100); -		 -		while (!mConfirmedQ.empty() && count < tcount) -		{ //process any meshes that have been confirmed for upload -			LLMeshUploadData& data = mConfirmedQ.front(); -			doUploadModel(data); -			mConfirmedQ.pop(); -			count++; -		} -	 -		tcount = llmin(count+PUSH_PER_PROCESS, 100); - -		while (!mInstanceQ.empty() && count < tcount && !isDiscarded()) -		{ //create any objects waiting for upload -			count++; -			object_asset["objects"].append(createObject(mInstanceQ.front())); -			mInstanceQ.pop(); -		} -			 -		mCurlRequest->process(); -			 -		done = isDiscarded() || (mInstanceQ.empty() && mConfirmedQ.empty() && mUploadQ.empty()); -	} -	while (!done || mCurlRequest->getQueued() > 0); - -	delete mCurlRequest; -	mCurlRequest = NULL; - -	// now upload the object asset -	std::string url = mUploadObjectAssetCapability; - -	if (object_asset["objects"][0].has("permissions")) -	{ //copy permissions from first available object to be used for coalesced object -		object_asset["permissions"] = object_asset["objects"][0]["permissions"]; -	} - -	if(!isDiscarded()) -	{ -		mPendingUploads++; -		LLHTTPClient::post(url, object_asset, new LLModelObjectUploadResponder(this,object_asset)); -	} -	else -	{ -		mFinished = true; -	} -} -  void LLMeshUploadThread::uploadModel(LLMeshUploadData& data)  { //called from arbitrary thread  	{ @@ -2234,7 +2120,7 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason,  		//just in case skin info or decomposition is at the end of the file (which it shouldn't be)  		lod_bytes = llmax(lod_bytes, header["skin"]["offset"].asInteger() + header["skin"]["size"].asInteger()); -		lod_bytes = llmax(lod_bytes, header["decomposition"]["offset"].asInteger() + header["decomposition"]["size"].asInteger()); +		lod_bytes = llmax(lod_bytes, header["physics_convex"]["offset"].asInteger() + header["physics_convex"]["size"].asInteger());  		S32 header_bytes = (S32) gMeshRepo.mThread->mMeshHeaderSize[mesh_id];  		S32 bytes = lod_bytes + header_bytes;  @@ -2522,7 +2408,6 @@ void LLMeshRepository::notifyLoadedMeshes()  		if (gAgent.getRegion()->getName() != region_name && gAgent.getRegion()->capabilitiesReceived())  		{  			region_name = gAgent.getRegion()->getName(); -		  			mGetMeshCapability = gAgent.getRegion()->getCapability("GetMesh");  		}  	} @@ -2860,7 +2745,18 @@ void LLMeshRepository::buildHull(const LLVolumeParams& params, S32 detail)  bool LLMeshRepository::hasPhysicsShape(const LLUUID& mesh_id)  {  	LLSD mesh = mThread->getMeshHeader(mesh_id); -	return mesh.has("physics_shape") && mesh["physics_shape"].has("size") && (mesh["physics_shape"]["size"].asInteger() > 0); +	if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0)) +	{ +		return true; +	} + +	LLModel::Decomposition* decomp = getDecomposition(mesh_id); +	if (decomp && !decomp->mHull.empty()) +	{ +		return true; +	} + +	return false;  }  LLSD& LLMeshRepository::getMeshHeader(const LLUUID& mesh_id) @@ -2916,102 +2812,6 @@ S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod)  } -void LLMeshUploadThread::sendCostRequest(LLMeshUploadData& data) -{ -	if(isDiscarded()) -	{ -		return ; -	} - -	//write model file to memory buffer -	std::stringstream ostr; - -	LLModel::Decomposition& decomp = -		data.mModel[LLModel::LOD_PHYSICS].notNull() ?  -		data.mModel[LLModel::LOD_PHYSICS]->mPhysics :  -		data.mBaseModel->mPhysics; - -	LLSD 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, -		true); - -	std::string desc = data.mBaseModel->mLabel; -	 -	// Grab the total vertex count of the model -	// along with other information for the "asset_resources" map -	// to send to the server. -	LLSD asset_resources = LLSD::emptyMap(); - - -	std::string url = mNewInventoryCapability;  - -	if (!url.empty()) -	{ -		LLSD body = generate_new_resource_upload_capability_body( -			LLAssetType::AT_MESH, -			desc, -			desc, -			LLFolderType::FT_MESH, -			LLInventoryType::IT_MESH, -			LLFloaterPerms::getNextOwnerPerms(), -			LLFloaterPerms::getGroupPerms(), -			LLFloaterPerms::getEveryonePerms()); - -		body["asset_resources"] = asset_resources; - -		mPendingConfirmations++; -		LLCurlRequest::headers_t headers; - -		data.mPostData = body; - -		mCurlRequest->post(url, headers, body, new LLMeshCostResponder(data, this)); -	}	 -} - -void LLMeshUploadThread::sendCostRequest(LLTextureUploadData& data) -{ -	if(isDiscarded()) -	{ -		return ; -	} - -	if (data.mTexture && data.mTexture->getDiscardLevel() >= 0) -	{ -		LLSD asset_resources = LLSD::emptyMap(); - -		std::string url = mNewInventoryCapability;  - -		if (!url.empty()) -		{ -			LLSD body = generate_new_resource_upload_capability_body( -				LLAssetType::AT_TEXTURE, -				data.mLabel, -				data.mLabel, -				LLFolderType::FT_TEXTURE, -				LLInventoryType::IT_TEXTURE, -				LLFloaterPerms::getNextOwnerPerms(), -				LLFloaterPerms::getGroupPerms(), -				LLFloaterPerms::getEveryonePerms()); - -			body["asset_resources"] = asset_resources; - -			mPendingConfirmations++; -			LLCurlRequest::headers_t headers; -			 -			data.mPostData = body; -			mCurlRequest->post(url, headers, body, new LLTextureCostResponder(data, this)); -		}	 -	} -} -  void LLMeshUploadThread::doUploadModel(LLMeshUploadData& data)  { @@ -3314,8 +3114,8 @@ bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const  void LLMeshRepository::updateInventory(inventory_data data)  {  	LLMutexLock lock(mMeshMutex); -	dumpLLSDToFile(data.mPostData,"update_inventory_post_data.xml"); -	dumpLLSDToFile(data.mResponse,"update_inventory_response.xml"); +	dumpLLSDToFile(data.mPostData,make_dump_name("update_inventory_post_data_",dump_num)); +	dumpLLSDToFile(data.mResponse,make_dump_name("update_inventory_response_",dump_num));  	mInventoryQ.push(data);  } @@ -3473,15 +3273,18 @@ void LLPhysicsDecomp::setMeshData(LLCDMeshData& mesh)  	mesh.mNumTriangles = mCurRequest->mIndices.size()/3; -	LLCDResult ret = LLCD_OK; -	if (LLConvexDecomposition::getInstance() != NULL) +	if (mesh.mNumTriangles > 0 && mesh.mNumVertices > 2)  	{ -		ret  = LLConvexDecomposition::getInstance()->setMeshData(&mesh); -	} +		LLCDResult ret = LLCD_OK; +		if (LLConvexDecomposition::getInstance() != NULL) +		{ +			ret  = LLConvexDecomposition::getInstance()->setMeshData(&mesh); +		} -	if (ret) -	{ -		llerrs << "Convex Decomposition thread valid but could not set mesh data" << llendl; +		if (ret) +		{ +			llerrs << "Convex Decomposition thread valid but could not set mesh data" << llendl; +		}  	}  } @@ -3839,6 +3642,62 @@ void LLPhysicsDecomp::run()  	mDone = true;  } +void LLPhysicsDecomp::Request::assignData(LLModel* mdl)  +{ +	if (!mdl) +	{ +		return ; +	} + +	U16 index_offset = 0; +	U16 tri[3] ; + +	mPositions.clear(); +	mIndices.clear(); +	mBBox[1] = LLVector3(F32_MIN, F32_MIN, F32_MIN) ; +	mBBox[0] = LLVector3(F32_MAX, F32_MAX, F32_MAX) ; +		 +	//queue up vertex positions and indices +	for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i) +	{ +		const LLVolumeFace& face = mdl->getVolumeFace(i); +		if (mPositions.size() + face.mNumVertices > 65535) +		{ +			continue; +		} + +		for (U32 j = 0; j < face.mNumVertices; ++j) +		{ +			mPositions.push_back(LLVector3(face.mPositions[j].getF32ptr())); +			for(U32 k = 0 ; k < 3 ; k++) +			{ +				mBBox[0].mV[k] = llmin(mBBox[0].mV[k], mPositions[j].mV[k]) ; +				mBBox[1].mV[k] = llmax(mBBox[1].mV[k], mPositions[j].mV[k]) ; +			} +		} + +		updateTriangleAreaThreshold() ; + +		for (U32 j = 0; j+2 < face.mNumIndices; j += 3) +		{ +			tri[0] = face.mIndices[j] + index_offset ; +			tri[1] = face.mIndices[j + 1] + index_offset ; +			tri[2] = face.mIndices[j + 2] + index_offset ; +				 +			if(isValidTriangle(tri[0], tri[1], tri[2])) +			{ +				mIndices.push_back(tri[0]); +				mIndices.push_back(tri[1]); +				mIndices.push_back(tri[2]); +			} +		} + +		index_offset += face.mNumVertices; +	} + +	return ; +} +  void LLPhysicsDecomp::Request::updateTriangleAreaThreshold()   {  	F32 range = mBBox[1].mV[0] - mBBox[0].mV[0] ; @@ -3955,3 +3814,27 @@ void LLMeshRepository::buildPhysicsMesh(LLModel::Decomposition& decomp)  		}  	}  } + + +bool LLMeshRepository::meshUploadEnabled() +{ +	LLViewerRegion *region = gAgent.getRegion(); +	if(gSavedSettings.getBOOL("MeshEnabled") &&  +	   LLViewerParcelMgr::getInstance()->allowAgentBuild() && +	   region) +	{ +		return region->meshUploadEnabled(); +	} +	return false; +} + +bool LLMeshRepository::meshRezEnabled() +{ +	LLViewerRegion *region = gAgent.getRegion(); +	if(gSavedSettings.getBOOL("MeshEnabled") &&  +	   region) +	{ +		return region->meshRezEnabled(); +	} +	return false; +} diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 9b80fc02b3..f237c3a60e 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -161,11 +161,14 @@ public:  		virtual void setStatusMessage(const std::string& msg); +		bool isValid() const {return mPositions.size() > 2 && mIndices.size() > 2 ;} +  	protected:  		//internal use  		LLVector3 mBBox[2] ;  		F32 mTriangleAreaThreshold ; +		void assignData(LLModel* mdl) ;  		void updateTriangleAreaThreshold() ;  		bool isValidTriangle(U16 idx1, U16 idx2, U16 idx3) ;  	}; @@ -393,8 +396,6 @@ public:  	BOOL            mDiscarded ;  	LLHost			mHost; -	std::string		mUploadObjectAssetCapability; -	std::string		mNewInventoryCapability;  	std::string		mWholeModelFeeCapability;  	std::string		mWholeModelUploadURL; @@ -413,12 +414,10 @@ public:  	void uploadTexture(LLTextureUploadData& data);  	void doUploadTexture(LLTextureUploadData& data); -	void sendCostRequest(LLTextureUploadData& data);  	void priceResult(LLTextureUploadData& data, const LLSD& content);  	void onTextureUploaded(LLTextureUploadData& data);  	void uploadModel(LLMeshUploadData& data); -	void sendCostRequest(LLMeshUploadData& data);  	void doUploadModel(LLMeshUploadData& data);  	void onModelUploaded(LLMeshUploadData& data);  	void createObjects(LLMeshUploadData& data); @@ -432,7 +431,6 @@ public:  	BOOL isDiscarded();  	void doWholeModelUpload(); -	void doIterativeUpload();  	void wholeModelToLLSD(LLSD& dest, bool include_textures); @@ -482,6 +480,10 @@ public:  	void buildHull(const LLVolumeParams& params, S32 detail);  	void buildPhysicsMesh(LLModel::Decomposition& decomp); +	 +	bool meshUploadEnabled(); +	bool meshRezEnabled(); +	  	LLSD& getMeshHeader(const LLUUID& mesh_id); diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index 7839cdd811..bb87601d20 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -530,17 +530,24 @@ void LLPanelVolume::refresh()  	getChildView("Light Ambiance")->setVisible( visible);  	getChildView("light texture control")->setVisible( visible); -	bool enable_mesh = gSavedSettings.getBOOL("MeshEnabled") &&  -					   gAgent.getRegion() && -					   !gAgent.getRegion()->getCapability("GetMesh").empty() && -					   !gAgent.getRegion()->getCapability("ObjectAdd").empty(); +	bool enable_mesh = false; +	LLSD sim_features; +	LLViewerRegion *region = gAgent.getRegion(); +	if(region) +	{ +		LLSD sim_features; +		region->getSimulatorFeatures(sim_features);		  +		enable_mesh = sim_features.has("PhysicsShapeTypes"); +	}  	getChildView("label physicsshapetype")->setVisible(enable_mesh);  	getChildView("Physics Shape Type Combo Ctrl")->setVisible(enable_mesh);  	getChildView("Physics Gravity")->setVisible(enable_mesh);  	getChildView("Physics Friction")->setVisible(enable_mesh);  	getChildView("Physics Density")->setVisible(enable_mesh);  	getChildView("Physics Restitution")->setVisible(enable_mesh); +	 +    /* TODO: add/remove individual physics shape types as per the PhysicsShapeTypes simulator features */  } diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 37640ad0d4..b9293b3b31 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -107,9 +107,7 @@ class LLMeshUploadVisible : public view_listener_t  {  	bool handleEvent(const LLSD& userdata)  	{ -		return gSavedSettings.getBOOL("MeshEnabled") &&  -			   LLViewerParcelMgr::getInstance()->allowAgentBuild() &&  -			   !gAgent.getRegion()->getCapability("ObjectAdd").empty(); +		return gMeshRepo.meshUploadEnabled();  	}  }; @@ -1203,78 +1201,6 @@ void upload_new_resource(  	}  } -BOOL upload_new_variable_price_resource( -	const LLTransactionID &tid,  -	LLAssetType::EType asset_type, -	std::string name, -	std::string desc,  -	LLFolderType::EType destination_folder_type, -	LLInventoryType::EType inv_type, -	U32 next_owner_perms, -	U32 group_perms, -	U32 everyone_perms, -	const std::string& display_name, -	const LLSD& asset_resources) -{ -	LLAssetID uuid =  -		upload_new_resource_prep( -			tid, -			asset_type, -			inv_type, -			name, -			display_name, -			desc); - -	llinfos << "*** Uploading: " << llendl; -	llinfos << "Type: " << LLAssetType::lookup(asset_type) << llendl; -	llinfos << "UUID: " << uuid << llendl; -	llinfos << "Name: " << name << llendl; -	llinfos << "Desc: " << desc << llendl; -	lldebugs << "Folder: " -		<< gInventory.findCategoryUUIDForType((destination_folder_type == LLFolderType::FT_NONE) ? (LLFolderType::EType)asset_type : destination_folder_type) << llendl; -	lldebugs << "Asset Type: " << LLAssetType::lookup(asset_type) << llendl; - -	std::string url = gAgent.getRegion()->getCapability( -		"NewFileAgentInventoryVariablePrice"); - -	if ( !url.empty() ) -	{ -		lldebugs -			<< "New Agent Inventory variable price upload" << llendl; -		 -		// Each of the two capabilities has similar data, so -		// let's reuse that code - -		LLSD body; - -		body = generate_new_resource_upload_capability_body( -			asset_type, -			name, -			desc, -			destination_folder_type, -			inv_type, -			next_owner_perms, -			group_perms, -			everyone_perms); - -		body["asset_resources"] = asset_resources; - -		LLHTTPClient::post( -			url, -			body, -			new LLNewAgentInventoryVariablePriceResponder( -				uuid, -				asset_type, -				body)); - -		return TRUE; -	} -	else -	{ -		return FALSE; -	} -} -  LLAssetID generate_asset_id_for_new_upload(const LLTransactionID& tid)  {  	if ( gDisconnected ) diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h index 1597821504..3136358b83 100644 --- a/indra/newview/llviewermenufile.h +++ b/indra/newview/llviewermenufile.h @@ -68,23 +68,6 @@ void upload_new_resource(  	S32 expected_upload_cost,  	void *userdata); -// TODO* : Move all uploads to use this new function -// since at some point, that upload path will be deprecated and no longer -// used - -// We make a new function here to ensure that previous code is not broken -BOOL upload_new_variable_price_resource( -	const LLTransactionID& tid,  -	LLAssetType::EType type, -	std::string name, -	std::string desc,  -	LLFolderType::EType destination_folder_type, -	LLInventoryType::EType inv_type, -	U32 next_owner_perms, -	U32 group_perms, -	U32 everyone_perms, -	const std::string& display_name, -	const LLSD& asset_resources);  LLAssetID generate_asset_id_for_new_upload(const LLTransactionID& tid);  void increase_new_upload_stats(LLAssetType::EType asset_type); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index e876294ef2..002e0567e4 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -69,6 +69,7 @@  #include "llspatialpartition.h"  #include "stringize.h"  #include "llviewercontrol.h" +#include "llsdserialize.h"  #ifdef LL_WINDOWS  	#pragma warning(disable:4355) @@ -1140,6 +1141,20 @@ void LLViewerRegion::getInfo(LLSD& info)  	info["Region"]["Handle"]["y"] = (LLSD::Integer)y;  } +void LLViewerRegion::getSimulatorFeatures(LLSD& sim_features) +{ +	sim_features = mSimulatorFeatures; +} + +void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features) +{ +	std::stringstream str; +	 +	LLSDSerialize::toPrettyXML(sim_features, str); +	llinfos << str.str() << llendl; +	mSimulatorFeatures = sim_features; +} +  LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp)  {  	U32 local_id = objectp->getLocalID(); @@ -1510,10 +1525,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)  	capabilityNames.append("LandResources");  	capabilityNames.append("MapLayer");  	capabilityNames.append("MapLayerGod"); -	capabilityNames.append("NewAccountingEnabled");  	capabilityNames.append("NewFileAgentInventory"); -	capabilityNames.append("NewFileAgentInventoryVariablePrice"); -	capabilityNames.append("ObjectAdd");  	capabilityNames.append("ParcelPropertiesUpdate");  	capabilityNames.append("ParcelMediaURLFilterList");  	capabilityNames.append("ParcelNavigateMedia"); @@ -1544,7 +1556,6 @@ void LLViewerRegion::setSeedCapability(const std::string& url)  	capabilityNames.append("UpdateNotecardTaskInventory");  	capabilityNames.append("UpdateScriptTask");  	capabilityNames.append("UploadBakedTexture"); -	capabilityNames.append("UploadObjectAsset");  	capabilityNames.append("ViewerMetrics");  	capabilityNames.append("ViewerStartAuction");  	capabilityNames.append("ViewerStats"); @@ -1562,6 +1573,42 @@ void LLViewerRegion::setSeedCapability(const std::string& url)  	LLHTTPClient::post(url, capabilityNames, mImpl->mHttpResponderPtr);  } +class SimulatorFeaturesReceived : public LLHTTPClient::Responder +{ +	LOG_CLASS(SimulatorFeaturesReceived); +public: +    SimulatorFeaturesReceived(LLViewerRegion* region) +	: mRegion(region) +    { } +	 +	 +    void error(U32 statusNum, const std::string& reason) +    { +		LL_WARNS2("AppInit", "SimulatorFeatures") << statusNum << ": " << reason << LL_ENDL; +    } +	 +    void result(const LLSD& content) +    { +		if(!mRegion) //region is removed or responder is not created. +		{ +			return ; +		} +		 +		mRegion->setSimulatorFeatures(content); +	} +	 +    static boost::intrusive_ptr<SimulatorFeaturesReceived> build( +																 LLViewerRegion* region) +    { +		return boost::intrusive_ptr<SimulatorFeaturesReceived>( +															   new SimulatorFeaturesReceived(region)); +    } +	 +private: +	LLViewerRegion* mRegion; +}; + +  void LLViewerRegion::setCapability(const std::string& name, const std::string& url)  {  	if(name == "EventQueueGet") @@ -1574,6 +1621,11 @@ void LLViewerRegion::setCapability(const std::string& name, const std::string& u  	{  		LLHTTPSender::setSender(mImpl->mHost, new LLCapHTTPSender(url));  	} +	else if (name == "SimulatorFeatures") +	{ +		// kick off a request for simulator features +		LLHTTPClient::get(url, new SimulatorFeaturesReceived(this)); +	}  	else  	{  		mImpl->mCapabilities[name] = url; @@ -1667,3 +1719,16 @@ std::string LLViewerRegion::getDescription() const      return stringize(*this);  } +bool LLViewerRegion::meshUploadEnabled() const +{ +	return (mSimulatorFeatures.has("MeshUploadEnabled") && +		mSimulatorFeatures["MeshUploadEnabled"].asBoolean()); +} + +bool LLViewerRegion::meshRezEnabled() const +{ +	return (mSimulatorFeatures.has("MeshRezEnabled") && +				mSimulatorFeatures["MeshRezEnabled"].asBoolean()); +} + + diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index a6e5c47b86..3811b989e7 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -276,6 +276,11 @@ public:  	void getInfo(LLSD& info); +	bool meshRezEnabled() const; +	bool meshUploadEnabled() const; + +	void getSimulatorFeatures(LLSD& info);	 +	void setSimulatorFeatures(const LLSD& info);  	typedef enum  	{ @@ -401,6 +406,8 @@ private:  	bool	mCapabilitiesReceived;  	BOOL mReleaseNotesRequested; +	 +	LLSD mSimulatorFeatures;  };  inline BOOL LLViewerRegion::getAllowDamage() const diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 34d15a597e..b1441cc281 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -601,7 +601,7 @@ public:  			ypos += y_inc; -			if (gSavedSettings.getBOOL("MeshEnabled")) +			if (gMeshRepo.meshRezEnabled())  			{  				addText(xpos, ypos, llformat("%.3f MB Mesh Data Received", LLMeshRepository::sBytesReceived/(1024.f*1024.f))); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 6de334eb82..c5e2c56e4b 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3984,7 +3984,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  		LLVOVolume* vobj = drawablep->getVOVolume(); -		if (vobj->getVolume() && vobj->getVolume()->isTetrahedron()) +		if (vobj->getVolume() && vobj->getVolume()->isTetrahedron() || (vobj->isMesh() && !gMeshRepo.meshRezEnabled()))  		{  			continue;  		}  | 
