summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorDave Parks <davep@lindenlab.com>2010-10-16 04:02:52 -0500
committerDave Parks <davep@lindenlab.com>2010-10-16 04:02:52 -0500
commit028bb02a6b325f8a1079030414872ab20db944ca (patch)
tree0886d724386cdc3c8b24259dd816c5f9c0ae565a /indra/newview
parent22edf673cf99b6bfe77808fb262f73202c1007ff (diff)
Better physics shape display.
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/llmeshrepository.cpp326
-rw-r--r--indra/newview/llmeshrepository.h24
-rw-r--r--indra/newview/llspatialpartition.cpp224
-rw-r--r--indra/newview/llspatialpartition.h1
-rw-r--r--indra/newview/llviewerdisplay.cpp1
-rw-r--r--indra/newview/pipeline.cpp124
-rw-r--r--indra/newview/pipeline.h6
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];