diff options
| -rw-r--r-- | indra/newview/llmeshrepository.cpp | 326 | ||||
| -rw-r--r-- | indra/newview/llmeshrepository.h | 24 | ||||
| -rw-r--r-- | indra/newview/llspatialpartition.cpp | 224 | ||||
| -rw-r--r-- | indra/newview/llspatialpartition.h | 1 | ||||
| -rw-r--r-- | indra/newview/llviewerdisplay.cpp | 1 | ||||
| -rw-r--r-- | indra/newview/pipeline.cpp | 124 | ||||
| -rw-r--r-- | indra/newview/pipeline.h | 6 | 
7 files changed, 613 insertions, 93 deletions
| diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 3c51781dfa..5f70fb6345 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -125,7 +125,7 @@ LLVertexBuffer* get_vertex_buffer_from_mesh(LLCDMeshData& mesh, F32 scale = 1.f)  	LLStrider<LLVector3> pos;  	LLStrider<LLVector3> norm; - +	  	buff->getVertexStrider(pos);  	buff->getNormalStrider(norm); @@ -442,6 +442,24 @@ public:  }; +class LLMeshPhysicsShapeResponder : public LLCurl::Responder +{ +public: +	LLUUID mMeshID; +	U32 mRequestedBytes; +	U32 mOffset; + +	LLMeshPhysicsShapeResponder(const LLUUID& id, U32 offset, U32 size) +		: mMeshID(id), mRequestedBytes(size), mOffset(offset) +	{ +	} + +	virtual void completedRaw(U32 status, const std::string& reason, +							  const LLChannelDescriptors& channels, +							  const LLIOPipe::buffer_ptr_t& buffer); + +}; +  LLMeshRepoThread::LLMeshRepoThread()  : LLThread("mesh repo", NULL)  @@ -538,6 +556,19 @@ void LLMeshRepoThread::run()  				mDecompositionRequests = incomplete;  			} +			{ +				std::set<LLUUID> incomplete; +				for (std::set<LLUUID>::iterator iter = mPhysicsShapeRequests.begin(); iter != mPhysicsShapeRequests.end(); ++iter) +				{ +					LLUUID mesh_id = *iter; +					if (!fetchMeshPhysicsShape(mesh_id)) +					{ +						incomplete.insert(mesh_id); +					} +				} +				mPhysicsShapeRequests = incomplete; +			} +  		} @@ -563,7 +594,13 @@ void LLMeshRepoThread::loadMeshDecomposition(const LLUUID& mesh_id)  { //protected by mSignal, no locking needed here  	mDecompositionRequests.insert(mesh_id);  } -	 + +void LLMeshRepoThread::loadMeshPhysicsShape(const LLUUID& mesh_id) +{ //protected by mSignal, no locking needed here +	mPhysicsShapeRequests.insert(mesh_id); +} + +  void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)  { //protected by mSignal, no locking needed here @@ -763,6 +800,82 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)  	return true;  } +bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) +{ //protected by mMutex +	mHeaderMutex->lock(); + +	if (mMeshHeader.find(mesh_id) == mMeshHeader.end()) +	{ //we have no header info for this mesh, do nothing +		mHeaderMutex->unlock(); +		return false; +	} + +	U32 header_size = mMeshHeaderSize[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(); + +		mHeaderMutex->unlock(); + +		if (offset >= 0 && size > 0) +		{ +			//check VFS for mesh physics shape info +			LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH); +			if (file.getSize() >= offset+size) +			{ +				LLMeshRepository::sCacheBytesRead += size; +				file.seek(offset); +				U8* buffer = new U8[size]; +				file.read(buffer, size); + +				//make sure buffer isn't all 0's (reserved block but not written) +				bool zero = true; +				for (S32 i = 0; i < llmin(size, 1024) && zero; ++i) +				{ +					zero = buffer[i] > 0 ? false : true; +				} + +				if (!zero) +				{ //attempt to parse +					if (physicsShapeReceived(mesh_id, buffer, size)) +					{ +						delete[] buffer; +						return true; +					} +				} + +				delete[] buffer; +			} + +			//reading from VFS failed for whatever reason, fetch from sim +			std::vector<std::string> headers; +			headers.push_back("Accept: application/octet-stream"); + +			std::string http_url = constructUrl(mesh_id); +			if (!http_url.empty()) +			{ +				++sActiveLODRequests; +				LLMeshRepository::sHTTPRequestCount++; +				mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size, +										   new LLMeshPhysicsShapeResponder(mesh_id, offset, size)); +			} +		} +		else +		{ //no physics shape whatsoever, report back NULL +			physicsShapeReceived(mesh_id, NULL, 0); +		} +	} +	else +	{	 +		mHeaderMutex->unlock(); +	} + +	//early out was not hit, effectively fetched +	return true; +} +  bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)  {  	bool retval = false; @@ -1166,6 +1279,12 @@ bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S3  			d->mBaseHullMesh = get_vertex_buffer_from_mesh(mesh);  		} +		else +		{ +			//empty vertex buffer to indicate decomposition has been fetched +			//but contains no base hull +			d->mBaseHullMesh = new LLVertexBuffer(0, 0); +		}  		mDecompositionQ.push(d);  	} @@ -1173,6 +1292,74 @@ bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S3  	return true;  } +bool LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size) +{ +	LLSD physics_shape; + +	LLMeshDecomposition* d = new LLMeshDecomposition(); +	d->mMeshID = mesh_id; + +	if (data == NULL) +	{ //no data, no physics shape exists +		d->mPhysicsShapeMesh = new LLVertexBuffer(0,0); +	} +	else +	{ +		LLVolumeParams volume_params; +		volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); +		volume_params.setSculptID(mesh_id, LL_SCULPT_TYPE_MESH); +		LLPointer<LLVolume> volume = new LLVolume(volume_params,0); +		std::string mesh_string((char*) data, data_size); +		std::istringstream stream(mesh_string); + +		if (volume->unpackVolumeFaces(stream, data_size)) +		{ +			//load volume faces into decomposition buffer +			S32 vertex_count = 0; +			S32 index_count = 0; + +			for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) +			{ +				const LLVolumeFace& face = volume->getVolumeFace(i); +				vertex_count += face.mNumVertices; +				index_count += face.mNumIndices; +			} + +			d->mPhysicsShapeMesh = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0); + +			d->mPhysicsShapeMesh->allocateBuffer(vertex_count, index_count, true); + +			LLStrider<LLVector3> pos; +			LLStrider<U16> idx; + +			d->mPhysicsShapeMesh->getVertexStrider(pos); +			d->mPhysicsShapeMesh->getIndexStrider(idx); + +			S32 idx_offset = 0; +			for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) +			{ +				const LLVolumeFace& face = volume->getVolumeFace(i); +				if (idx_offset + face.mNumIndices > 65535) +				{ //avoid 16-bit index overflow +					continue; +				} + +				LLVector4a::memcpyNonAliased16(pos[idx_offset].mV, face.mPositions[0].getF32ptr(), face.mNumVertices*sizeof(LLVector4a)); +			 +				for (S32 i = 0; i < face.mNumIndices; ++i) +				{ +					*idx++ = face.mIndices[i] + idx_offset; +				} + +				idx_offset += face.mNumVertices; +			} +		} +	} + +	mDecompositionQ.push(d); +	return true; +} +  LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data, LLVector3& scale, bool upload_textures,  										bool upload_skin, bool upload_joints)  : LLThread("mesh upload") @@ -1729,6 +1916,60 @@ void LLMeshDecompositionResponder::completedRaw(U32 status, const std::string& r  	delete [] data;  } +void LLMeshPhysicsShapeResponder::completedRaw(U32 status, const std::string& reason, +							  const LLChannelDescriptors& channels, +							  const LLIOPipe::buffer_ptr_t& buffer) +{ +	S32 data_size = buffer->countAfter(channels.in(), NULL); + +	if (status < 200 || status > 400) +	{ +		llwarns << status << ": " << reason << llendl; +	} + +	if (data_size < mRequestedBytes) +	{ +		if (status == 499 || status == 503) +		{ //timeout or service unavailable, try again +			LLMeshRepository::sHTTPRetryCount++; +			gMeshRepo.mThread->loadMeshPhysicsShape(mMeshID); +		} +		else +		{ +			llwarns << "Unhandled status " << status << llendl; +		} +		return; +	} + +	LLMeshRepository::sBytesReceived += mRequestedBytes; + +	U8* data = NULL; + +	if (data_size > 0) +	{ +		data = new U8[data_size]; +		buffer->readAfter(channels.in(), NULL, data, data_size); +	} + +	if (gMeshRepo.mThread->physicsShapeReceived(mMeshID, data, data_size)) +	{ +		//good fetch from sim, write to VFS for caching +		LLVFile file(gVFS, mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE); + +		S32 offset = mOffset; +		S32 size = mRequestedBytes; + +		if (file.getSize() >= offset+size) +		{ +			LLMeshRepository::sCacheBytesWritten += size; +			file.seek(offset); +			file.write(data, size); +		} +	} + +	delete [] data; +} +  void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason,  							  const LLChannelDescriptors& channels,  							  const LLIOPipe::buffer_ptr_t& buffer) @@ -2096,6 +2337,13 @@ void LLMeshRepository::notifyLoadedMeshes()  		mPendingDecompositionRequests.pop();  	} +	//send physics shapes decomposition requests +	while (!mPendingPhysicsShapeRequests.empty()) +	{ +		mThread->loadMeshPhysicsShape(mPendingPhysicsShapeRequests.front()); +		mPendingPhysicsShapeRequests.pop(); +	} +	  	mThread->notifyLoadedMeshes();  	mThread->mMutex->unlock(); @@ -2110,9 +2358,45 @@ void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo& info)  	mLoadingSkins.erase(info.mMeshID);  } +void LLMeshDecomposition::merge(const LLMeshDecomposition* rhs) +{ +	if (!rhs) +	{ +		return; +	} + +	if (mMeshID != rhs->mMeshID) +	{ +		llerrs << "Attempted to merge with decomposition of some other mesh." << llendl; +	} + +	if (mBaseHull.empty()) +	{ //take base hull and decomposition from rhs +		mHull = rhs->mHull; +		mBaseHull = rhs->mBaseHull; +		mMesh = rhs->mMesh; +		mBaseHullMesh = rhs->mBaseHullMesh; +	} + +	if (mPhysicsShapeMesh.isNull()) +	{ //take physics shape mesh from rhs +		mPhysicsShapeMesh = rhs->mPhysicsShapeMesh; +	} +} +  void LLMeshRepository::notifyDecompositionReceived(LLMeshDecomposition* decomp)  { -	mDecompositionMap[decomp->mMeshID] = decomp; +	decomposition_map::iterator iter = mDecompositionMap.find(decomp->mMeshID); +	if (iter == mDecompositionMap.end()) +	{ //just insert decomp into map +		mDecompositionMap[decomp->mMeshID] = decomp; +	} +	else +	{ //merge decomp with existing entry +		iter->second->merge(decomp); +		delete decomp; +	} +  	mLoadingDecompositions.erase(decomp->mMeshID);  } @@ -2238,17 +2522,47 @@ const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id)  	return NULL;  } +void LLMeshRepository::fetchPhysicsShape(const LLUUID& mesh_id) +{ +	if (mesh_id.notNull()) +	{ +		LLMeshDecomposition* decomp = NULL; +		decomposition_map::iterator iter = mDecompositionMap.find(mesh_id); +		if (iter != mDecompositionMap.end()) +		{ +			decomp = iter->second; +		} +		 +		//decomposition block hasn't been fetched yet +		if (!decomp || decomp->mPhysicsShapeMesh.isNull()) +		{ +			LLMutexLock lock(mMeshMutex); +			//add volume to list of loading meshes +			std::set<LLUUID>::iterator iter = mLoadingPhysicsShapes.find(mesh_id); +			if (iter == mLoadingPhysicsShapes.end()) +			{ //no request pending for this skin info +				mLoadingPhysicsShapes.insert(mesh_id); +				mPendingPhysicsShapeRequests.push(mesh_id); +			} +		} +	} + +} +  const LLMeshDecomposition* LLMeshRepository::getDecomposition(const LLUUID& mesh_id)  { +	LLMeshDecomposition* ret = NULL; +  	if (mesh_id.notNull())  	{  		decomposition_map::iterator iter = mDecompositionMap.find(mesh_id);  		if (iter != mDecompositionMap.end())  		{ -			return iter->second; +			ret = iter->second;  		} -		//no skin info known about given mesh, try to fetch it +		//decomposition block hasn't been fetched yet +		if (!ret || ret->mBaseHullMesh.isNull())  		{  			LLMutexLock lock(mMeshMutex);  			//add volume to list of loading meshes @@ -2261,7 +2575,7 @@ const LLMeshDecomposition* LLMeshRepository::getDecomposition(const LLUUID& mesh  		}  	} -	return NULL; +	return ret;  }  void LLMeshRepository::buildHull(const LLVolumeParams& params, S32 detail) diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index e3fb91b9d8..bbfe2e46f2 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -136,12 +136,15 @@ class LLMeshDecomposition  public:  	LLMeshDecomposition() { } +	void merge(const LLMeshDecomposition* rhs); +  	LLUUID mMeshID;  	LLModel::physics_shape mHull;  	LLModel::hull mBaseHull;  	std::vector<LLPointer<LLVertexBuffer> > mMesh;  	LLPointer<LLVertexBuffer> mBaseHullMesh; +	LLPointer<LLVertexBuffer> mPhysicsShapeMesh;  };  class LLPhysicsDecomp : public LLThread @@ -282,7 +285,10 @@ public:  	//set of requested decompositions  	std::set<LLUUID> mDecompositionRequests; -	 + +	//set of requested physics shapes +	std::set<LLUUID> mPhysicsShapeRequests; +  	//queue of completed Decomposition info requests  	std::queue<LLMeshDecomposition*> mDecompositionQ; @@ -316,6 +322,7 @@ public:  	bool lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size);  	bool skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size);  	bool decompositionReceived(const LLUUID& mesh_id, U8* data, S32 data_size); +	bool physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size);  	const LLSD& getMeshHeader(const LLUUID& mesh_id);  	void notifyLoadedMeshes(); @@ -324,6 +331,7 @@ public:  	void loadMeshSkinInfo(const LLUUID& mesh_id);  	void loadMeshDecomposition(const LLUUID& mesh_id); +	void loadMeshPhysicsShape(const LLUUID& mesh_id);  	//send request for skin info, returns true if header info exists   	//  (should hold onto mesh_id and try again later if header info does not exist) @@ -332,6 +340,12 @@ public:  	//send request for decomposition, returns true if header info exists   	//  (should hold onto mesh_id and try again later if header info does not exist)  	bool fetchMeshDecomposition(const LLUUID& mesh_id); + +	//send request for PhysicsShape, returns true if header info exists  +	//  (should hold onto mesh_id and try again later if header info does not exist) +	bool fetchMeshPhysicsShape(const LLUUID& mesh_id); + +  };  class LLMeshUploadThread : public LLThread  @@ -443,6 +457,8 @@ public:  	U32 getResourceCost(const LLUUID& mesh_params);  	const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id);  	const LLMeshDecomposition* getDecomposition(const LLUUID& mesh_id); +	void fetchPhysicsShape(const LLUUID& mesh_id); +  	void buildHull(const LLVolumeParams& params, S32 detail);  	const LLSD& getMeshHeader(const LLUUID& mesh_id); @@ -476,6 +492,12 @@ public:  	//list of mesh ids that need to send decomposition fetch requests  	std::queue<LLUUID> mPendingDecompositionRequests; +	//list of mesh ids awaiting physics shapes +	std::set<LLUUID> mLoadingPhysicsShapes; + +	//list of mesh ids that need to send physics shape fetch requests +	std::queue<LLUUID> mPendingPhysicsShapeRequests; +	  	U32 mMeshThreadCount;  	void cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 6ce6a3ecdb..e763f92fab 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -2794,43 +2794,68 @@ S32 get_physics_detail(const LLVolumeParams& volume_params, const LLVector3& sca  	return detail;  } -void renderMeshBaseHull(LLVOVolume* volume, U32 data_mask, LLColor4& color) +void renderMeshBaseHull(LLVOVolume* volume, U32 data_mask, LLColor4& color, LLColor4& line_color)  {  	LLUUID mesh_id = volume->getVolume()->getParams().getSculptID();  	const LLMeshDecomposition* decomp = gMeshRepo.getDecomposition(mesh_id); +	const LLVector3 center(0,0,0); +	const LLVector3 size(0.25f,0.25f,0.25f); +  	if (decomp)  	{		  		LLVertexBuffer* buff = decomp->mBaseHullMesh; -		if (buff) +		if (buff && buff->getNumVerts() > 0)  		{ -			gGL.pushMatrix(); -			glMultMatrixf((F32*) volume->getRelativeXform().mMatrix); -			 -			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -  			buff->setBuffer(data_mask);  			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); -			glColor3fv(color.mV); +			glColor4fv(line_color.mV);  			buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts());  			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);  			{ -				LLGLEnable blend(GL_BLEND); -				gGL.setSceneBlendType(LLRender::BT_ALPHA); -				LLGLDepthTest depth(GL_TRUE, GL_FALSE);  				glColor4fv(color.mV);  				buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts());  			} -			gGL.popMatrix();  		} +		else +		{ +			gGL.color3f(0,1,1); +			drawBoxOutline(center, size); +		} + +	} +	else +	{ +		gGL.color3f(1,0,1); +		drawBoxOutline(center, size);  	}  } +void render_hull(LLVertexBuffer* buff, U32 data_mask, const LLColor4& color, const LLColor4& line_color) +{ +	buff->setBuffer(data_mask); + +	glColor4fv(color.mV); +	buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts()); + +	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +	glColor4fv(line_color.mV); +	buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts()); +	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +} +  void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)  { +	if (volume->isSelected()) +	{ +		LLVector3 construct_me(5,5,5); +		construct_me.normalize(); +	} + +	  	U8 physics_type = volume->getPhysicsShapeType();  	if (physics_type == LLViewerObject::PHYSICS_SHAPE_NONE || volume->isFlexible()) @@ -2838,6 +2863,8 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)  		return;  	} +	//not allowed to return at this point without rendering *something* +  	F32 threshold = gSavedSettings.getF32("ObjectCostHighThreshold");  	F32 cost = volume->getObjectCost(); @@ -2857,6 +2884,8 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)  		color = lerp( mid, high, 2.f * ( normalizedCost - 0.5f ) );  	} +	LLColor4 line_color = color*0.5f; +  	U32 data_mask = LLVertexBuffer::MAP_VERTEX;  	LLVolumeParams volume_params = volume->getVolume()->getParams(); @@ -2869,39 +2898,55 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)  	U32 type = physics_spec.getType(); +	LLVector3 center(0,0,0); +	LLVector3 size(0.25f,0.25f,0.25f); + +	gGL.pushMatrix(); +	glMultMatrixf((F32*) volume->getRelativeXform().mMatrix); +		  	if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::USER_MESH)  	{  		LLUUID mesh_id = volume->getVolume()->getParams().getSculptID();  		const LLMeshDecomposition* decomp = gMeshRepo.getDecomposition(mesh_id); - +			  		if (decomp) -		{ -			gGL.pushMatrix(); -			glMultMatrixf((F32*) volume->getRelativeXform().mMatrix); +		{ //render a physics based mesh  			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -			for (U32 i = 0; i < decomp->mHull.size(); ++i) -			{		 -				LLVertexBuffer* buff = decomp->mMesh[i]; - -				buff->setBuffer(data_mask); - +			if (!decomp->mHull.empty()) +			{ //decomposition exists, use that +				for (U32 i = 0; i < decomp->mHull.size(); ++i) +				{		 +					render_hull(decomp->mMesh[i], data_mask, color, line_color); +				} +			} +			else if (decomp->mPhysicsShapeMesh.notNull() && decomp->mPhysicsShapeMesh->getNumVerts() > 0) +			{  +				//decomp has physics mesh, render that mesh +				glColor4fv(color.mV); +				pushBufferVerts(decomp->mPhysicsShapeMesh, data_mask); +				  				glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); -				glColor3fv(color.mV); -				buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts()); +				glColor4fv(line_color.mV); +				pushBufferVerts(decomp->mPhysicsShapeMesh, data_mask);  				glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +			} +			else +			{ //no mesh or decomposition, render base hull +				renderMeshBaseHull(volume, data_mask, color, line_color); +				if (decomp->mPhysicsShapeMesh.isNull())  				{ -					LLGLEnable blend(GL_BLEND); -					gGL.setSceneBlendType(LLRender::BT_ALPHA); -					LLGLDepthTest depth(GL_TRUE, GL_FALSE); -					glColor4fv(color.mV); -					buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts()); +					//attempt to fetch physics shape mesh if available +					gMeshRepo.fetchPhysicsShape(mesh_id);  				}  			} - -			gGL.popMatrix(); +		} +		else +		{	 +			gGL.color3f(1,1,0); +			drawBoxOutline(center, size);  		}  	}  	else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::USER_CONVEX || @@ -2909,7 +2954,7 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)  	{  		if (volume->isMesh())  		{ -			renderMeshBaseHull(volume, data_mask, color); +			renderMeshBaseHull(volume, data_mask, color, line_color);  		}  #if LL_WINDOWS   		else @@ -3003,11 +3048,10 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)  			if (phys_volume->mHullPoints)  			{  				//render hull -				gGL.pushMatrix(); -				glMultMatrixf((GLfloat*) volume->getRelativeXform().mMatrix); +			  				glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); -				glColor3fv(color.mV); +				glColor4fv(line_color.mV);  				LLVertexBuffer::unbind();  				glVertexPointer(3, GL_FLOAT, 16, phys_volume->mHullPoints); @@ -3016,7 +3060,11 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)  				glColor4fv(color.mV);  				glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);  				glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices); -				gGL.popMatrix(); +			} +			else +			{ +				gGL.color3f(1,0,1); +				drawBoxOutline(center, size);  			}  			LLPrimitive::sVolumeManager->unrefVolume(phys_volume); @@ -3025,8 +3073,6 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)  	}  	else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::BOX)  	{ -		gGL.pushMatrix(); -		glMultMatrixf((GLfloat*) volume->getRelativeXform().mMatrix);  		LLVector3 center = physics_spec.getCenter();  		LLVector3 scale = physics_spec.getScale();  		LLVector3 vscale = volume->getScale()*2.f; @@ -3034,7 +3080,6 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)  		gGL.color4fv(color.mV);  		drawBox(center, scale); -		gGL.popMatrix();  	}  	else if	(type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::SPHERE)  	{ @@ -3046,11 +3091,8 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)  		volume_params.setShear	( 0, 0 );  		LLVolume* sphere = LLPrimitive::sVolumeManager->refVolume(volume_params, 3); -		gGL.pushMatrix(); -		glMultMatrixf((GLfloat*) volume->getRelativeXform().mMatrix);  		glColor4fv(color.mV);  		pushVerts(sphere); -		gGL.popMatrix();  		LLPrimitive::sVolumeManager->unrefVolume(sphere);  	}  	else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::CYLINDER) @@ -3063,11 +3105,8 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)  		volume_params.setShear	( 0, 0 );  		LLVolume* cylinder = LLPrimitive::sVolumeManager->refVolume(volume_params, 3); -		gGL.pushMatrix(); -		glMultMatrixf((GLfloat*) volume->getRelativeXform().mMatrix);  		glColor4fv(color.mV);  		pushVerts(cylinder); -		gGL.popMatrix();  		LLPrimitive::sVolumeManager->unrefVolume(cylinder);  	}  	else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_MESH) @@ -3076,17 +3115,14 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)  		S32 detail = get_physics_detail(volume_params, volume->getScale());  		LLVolume* phys_volume = LLPrimitive::sVolumeManager->refVolume(volume_params, detail); -		gGL.pushMatrix(); -		glMultMatrixf((GLfloat*) volume->getRelativeXform().mMatrix);  		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); -		glColor3fv(color.mV); +		glColor4fv(line_color.mV);  		pushVerts(phys_volume);  		glColor4fv(color.mV);  		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);  		pushVerts(phys_volume); -		gGL.popMatrix();  		LLPrimitive::sVolumeManager->unrefVolume(phys_volume);  	}  	else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_CONVEX) @@ -3098,26 +3134,35 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)  		if (phys_volume->mHullPoints && phys_volume->mHullIndices)  		{ -			gGL.pushMatrix(); -			glMultMatrixf((GLfloat*) volume->getRelativeXform().mMatrix);  			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);  			LLVertexBuffer::unbind();  			glVertexPointer(3, GL_FLOAT, 16, phys_volume->mHullPoints); -			glColor3fv(color.mV); +			glColor4fv(line_color.mV);  			glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices);  			glColor4fv(color.mV);  			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);  			glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices);			 -			gGL.popMatrix();  		}  		else  		{ +			gGL.color3f(1,0,1); +			drawBoxOutline(center, size);  			gMeshRepo.buildHull(volume_params, detail);  		}  		LLPrimitive::sVolumeManager->unrefVolume(phys_volume);  	} +	else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::SCULPT) +	{ +		//TODO: implement sculpted prim physics display +	} +	else  +	{ +		llerrs << "Unhandled type" << llendl; +	} + +	gGL.popMatrix();  	/*{ //analytical shape, just push visual rep.  		glColor3fv(color.mV); @@ -3131,13 +3176,6 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)  void renderPhysicsShapes(LLSpatialGroup* group)  { -	LLGLEnable blend(GL_BLEND); -	LLGLDepthTest test(GL_TRUE, GL_FALSE); - -	LLGLEnable offset_fill(GL_POLYGON_OFFSET_FILL); -	LLGLEnable offset_line(GL_POLYGON_OFFSET_LINE); -	glPolygonOffset(-1.f, -1.f); -  	for (LLSpatialGroup::OctreeNode::const_element_iter i = group->getData().begin(); i != group->getData().end(); ++i)  	{  		LLDrawable* drawable = *i; @@ -3541,7 +3579,6 @@ void renderAgentTarget(LLVOAvatar* avatar)  	}  } -  class LLOctreeRenderNonOccluded : public LLOctreeTraveler<LLDrawable>  {  public: @@ -3573,14 +3610,6 @@ public:  				stop_glerror();  			} -			if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES)) -			{ -				group->rebuildGeom(); -				group->rebuildMesh(); - -				renderPhysicsShapes(group); -			} -  			//render visibility wireframe  			if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))  			{ @@ -3712,6 +3741,41 @@ public:  	}  }; + +class LLOctreeRenderPhysicsShapes : public LLOctreeTraveler<LLDrawable> +{ +public: +	LLCamera* mCamera; +	LLOctreeRenderPhysicsShapes(LLCamera* camera): mCamera(camera) {} +	 +	virtual void traverse(const LLSpatialGroup::OctreeNode* node) +	{ +		LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); +		 +		if (!mCamera || mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1])) +		{ +			node->accept(this); +			stop_glerror(); + +			for (U32 i = 0; i < node->getChildCount(); i++) +			{ +				traverse(node->getChild(i)); +				stop_glerror(); +			} +			 +			group->rebuildGeom(); +			group->rebuildMesh(); + +			renderPhysicsShapes(group); +		} +	} + +	virtual void visit(const LLSpatialGroup::OctreeNode* branch) +	{ +		 +	} +}; +  class LLOctreePushBBoxVerts : public LLOctreeTraveler<LLDrawable>  {  public: @@ -3830,6 +3894,25 @@ public:  }; +void LLSpatialPartition::renderPhysicsShapes() +{ +	LLSpatialBridge* bridge = asBridge(); +	LLCamera* camera = LLViewerCamera::getInstance(); +	 +	if (bridge) +	{ +		camera = NULL; +	} + +	gGL.flush(); +	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); +	glLineWidth(3.f); +	LLOctreeRenderPhysicsShapes render_physics(camera); +	render_physics.traverse(mOctree); +	gGL.flush(); +	glLineWidth(1.f); +} +  void LLSpatialPartition::renderDebug()  {  	if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE | @@ -3845,8 +3928,7 @@ void LLSpatialPartition::renderDebug()  									  LLPipeline::RENDER_DEBUG_AVATAR_VOLUME |  									  LLPipeline::RENDER_DEBUG_AGENT_TARGET |  									  LLPipeline::RENDER_DEBUG_BUILD_QUEUE | -									  LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA | -									  LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))  +									  LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))   	{  		return;  	} diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index c21662d5da..ea843a6eeb 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -459,6 +459,7 @@ public:  	virtual LLSpatialBridge* asBridge() { return NULL; }  	virtual BOOL isBridge() { return asBridge() != NULL; } +	void renderPhysicsShapes();  	void renderDebug();  	void renderIntersectingBBoxes(LLCamera* camera);  	void restoreGL(); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 5b1f0d9a3a..e2e2e0d04e 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -816,6 +816,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)  		if (to_texture)  		{  			gGL.setColorMask(true, true); +					  			if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)  			{  				gPipeline.mDeferredScreen.bindTarget(); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 28a8de3d47..0e55a9cb00 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -537,6 +537,22 @@ void LLPipeline::resizeScreenTexture()  	}  } +void LLPipeline::allocatePhysicsBuffer() +{ +	GLuint resX = gViewerWindow->getWorldViewWidthRaw(); +	GLuint resY = gViewerWindow->getWorldViewHeightRaw(); + +	if (mPhysicsDisplay.getWidth() != resX || mPhysicsDisplay.getHeight() != resY) +	{ +		mPhysicsDisplay.allocate(resX, resY, GL_RGBA, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); +		if (mSampleBuffer.getWidth() == mPhysicsDisplay.getWidth() &&  +			mSampleBuffer.getHeight() == mPhysicsDisplay.getHeight()) +		{ +			mPhysicsDisplay.setSampleBuffer(&mSampleBuffer); +		} +	} +} +  void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)  {  	// remember these dimensions @@ -677,6 +693,7 @@ void LLPipeline::releaseGLBuffers()  	mWaterRef.release();  	mWaterDis.release();  	mScreen.release(); +	mPhysicsDisplay.release();  	mUIScreen.release();  	mSampleBuffer.releaseSampleBuffer();  	mDeferredScreen.release(); @@ -3786,6 +3803,59 @@ void LLPipeline::addTrianglesDrawn(S32 index_count, U32 render_type)  	}  } +void LLPipeline::renderPhysicsDisplay() +{ +	if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES)) +	{ +		return; +	} + +	allocatePhysicsBuffer(); + +	gGL.flush(); +	mPhysicsDisplay.bindTarget(); +	glClearColor(0,0,0,1); +	gGL.setColorMask(true, true); +	mPhysicsDisplay.clear(); +	glClearColor(0,0,0,0); + +	gGL.setColorMask(true, false); + +	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();  +			iter != LLWorld::getInstance()->getRegionList().end(); ++iter) +	{ +		LLViewerRegion* region = *iter; +		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) +		{ +			LLSpatialPartition* part = region->getSpatialPartition(i); +			if (part) +			{ +				if (hasRenderType(part->mDrawableType)) +				{ +					part->renderPhysicsShapes(); +				} +			} +		} +	} + +	for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) +	{ +		LLSpatialBridge* bridge = *i; +		if (!bridge->isDead() && hasRenderType(bridge->mDrawableType)) +		{ +			glPushMatrix(); +			glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); +			bridge->renderPhysicsShapes(); +			glPopMatrix(); +		} +	} + + +	gGL.flush(); +	mPhysicsDisplay.flush(); +} + +  void LLPipeline::renderDebug()  {  	LLMemType mt(LLMemType::MTYPE_PIPELINE); @@ -3816,6 +3886,18 @@ void LLPipeline::renderDebug()  		}  	} +	for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) +	{ +		LLSpatialBridge* bridge = *i; +		if (!bridge->isDead() && hasRenderType(bridge->mDrawableType)) +		{ +			glPushMatrix(); +			glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); +			bridge->renderDebug(); +			glPopMatrix(); +		} +	} +  	if (gSavedSettings.getBOOL("DebugShowUploadCost"))  	{  		std::set<LLUUID> textures; @@ -3873,18 +3955,6 @@ void LLPipeline::renderDebug()  		gPipeline.mDebugMeshUploadCost = mesh_cost;  	} -	for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) -	{ -		LLSpatialBridge* bridge = *i; -		if (!bridge->isDead() && hasRenderType(bridge->mDrawableType)) -		{ -			glPushMatrix(); -			glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); -			bridge->renderDebug(); -			glPopMatrix(); -		} -	} -  	if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))  	{  		LLVertexBuffer::unbind(); @@ -4098,6 +4168,8 @@ void LLPipeline::renderDebug()  	}  	gGL.flush(); + +	gPipeline.renderPhysicsDisplay();  }  void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects, BOOL render_transparent, const LLRect& screen_rect) @@ -6125,7 +6197,6 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)  	}  	else  	{ -  		if (res_mod > 1)  		{  			tc2 /= (F32) res_mod; @@ -6191,8 +6262,33 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)  		}  	} -  	gGL.setSceneBlendType(LLRender::BT_ALPHA); + +	if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES)) +	{ +		LLVector2 tc1(0,0); +		LLVector2 tc2((F32) gViewerWindow->getWorldViewWidthRaw()*2, +				  (F32) gViewerWindow->getWorldViewHeightRaw()*2); + +		LLGLEnable blend(GL_BLEND); +		gGL.color4f(1,1,1,0.75f); + +		gGL.getTexUnit(0)->bind(&mPhysicsDisplay); + +		gGL.begin(LLRender::TRIANGLE_STRIP); +		gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); +		gGL.vertex2f(-1,-1); +		 +		gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); +		gGL.vertex2f(-1,3); +		 +		gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); +		gGL.vertex2f(3,-1); +		 +		gGL.end(); +		gGL.flush(); +	} +  	glMatrixMode(GL_PROJECTION);  	glPopMatrix();  	glMatrixMode(GL_MODELVIEW); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 0831a6c456..1c2ffd664c 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -114,8 +114,10 @@ public:  	void resizeScreenTexture();  	void releaseGLBuffers();  	void createGLBuffers(); -	void allocateScreenBuffer(U32 resX, U32 resY); +	void allocateScreenBuffer(U32 resX, U32 resY); +	void allocatePhysicsBuffer(); +	  	void resetVertexBuffers(LLDrawable* drawable);  	void setUseVBO(BOOL use_vbo);  	void generateImpostor(LLVOAvatar* avatar); @@ -259,6 +261,7 @@ public:  	void generateGI(LLCamera& camera, LLVector3& lightDir, std::vector<LLVector3>& vpc);  	void renderHighlights();  	void renderDebug(); +	void renderPhysicsDisplay();  	void renderForSelect(std::set<LLViewerObject*>& objects, BOOL render_transparent, const LLRect& screen_rect);  	void rebuildPools(); // Rebuild pools @@ -519,6 +522,7 @@ public:  	LLRenderTarget			mGIMapPost[2];  	LLRenderTarget			mLuminanceMap;  	LLRenderTarget			mHighlight; +	LLRenderTarget			mPhysicsDisplay;  	//sun shadow map  	LLRenderTarget			mShadow[6]; | 
