diff options
author | Dave Parks <davep@lindenlab.com> | 2010-10-16 04:02:52 -0500 |
---|---|---|
committer | Dave Parks <davep@lindenlab.com> | 2010-10-16 04:02:52 -0500 |
commit | 028bb02a6b325f8a1079030414872ab20db944ca (patch) | |
tree | 0886d724386cdc3c8b24259dd816c5f9c0ae565a | |
parent | 22edf673cf99b6bfe77808fb262f73202c1007ff (diff) |
Better physics shape display.
-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]; |